luaur_ast/methods/
parser_parse_number.rs1use crate::enums::constant_number_parse_result::ConstantNumberParseResult;
2use crate::functions::parse_double::parse_double;
3use crate::functions::parse_integer_64::parse_integer_64;
4use crate::records::ast_array::AstArray;
5use crate::records::ast_expr::AstExpr;
6use crate::records::ast_expr_constant_integer::AstExprConstantInteger;
7use crate::records::ast_expr_constant_number::AstExprConstantNumber;
8use crate::records::cst_expr_constant_integer::CstExprConstantInteger;
9use crate::records::cst_expr_constant_number::CstExprConstantNumber;
10use crate::records::parser::Parser;
11use luaur_common::FFlag;
12
13impl Parser {
14 pub fn parse_number(&mut self) -> *mut AstExpr {
15 let (start, data_ptr, lexeme_len) = {
17 let current = self.lexer.current();
18 (
19 current.location,
20 unsafe { current.data.data } as *const u8,
21 current.get_length() as usize,
22 )
23 };
24 self.scratch_data.clear();
25 let bytes = unsafe { core::slice::from_raw_parts(data_ptr, lexeme_len) };
26 self.scratch_data
27 .push_str(core::str::from_utf8(bytes).unwrap_or(""));
28
29 let mut source_data = AstArray::default();
30 if self.options.store_cst_data {
31 let sd = self.scratch_data.clone();
32 source_data = self.copy_string(&sd);
33 }
34
35 if self.scratch_data.contains('_') {
37 self.scratch_data.retain(|c| c != '_');
38 }
39
40 if FFlag::LuauIntegerType2.get() && self.scratch_data.ends_with('i') {
41 let mut value: i64 = 0;
42 let result: ConstantNumberParseResult;
43
44 if self.scratch_data.starts_with("0x") || self.scratch_data.starts_with("0X") {
45 result = parse_integer_64(&mut value, &self.scratch_data, 16);
46 } else if self.scratch_data.starts_with("0b") || self.scratch_data.starts_with("0B") {
47 result = parse_integer_64(&mut value, &self.scratch_data[2..], 2);
48 } else {
49 result = parse_integer_64(&mut value, &self.scratch_data, 10);
50 }
51
52 self.next_lexeme();
53
54 if result == ConstantNumberParseResult::Malformed {
55 return self.report_expr_error(
56 start,
57 AstArray::default(),
58 format_args!("Malformed integer"),
59 ) as *mut AstExpr;
60 }
61
62 if result != ConstantNumberParseResult::Ok {
63 return self.report_expr_error(
64 start,
65 AstArray::default(),
66 format_args!("Integer overflow"),
67 ) as *mut AstExpr;
68 }
69
70 let node = unsafe {
71 (*self.allocator).alloc(AstExprConstantInteger {
72 base: AstExpr {
73 base: crate::records::ast_node::AstNode {
74 class_index:
75 <AstExprConstantInteger as crate::rtti::AstNodeClass>::CLASS_INDEX,
76 location: start,
77 },
78 },
79 value,
80 parse_result: result,
81 })
82 };
83
84 if self.options.store_cst_data {
85 let cst_node = unsafe {
86 (*self.allocator).alloc(CstExprConstantInteger {
87 base: crate::records::cst_node::CstNode {
88 class_index:
89 <CstExprConstantInteger as crate::rtti::CstNodeClass>::CLASS_INDEX,
90 },
91 value: source_data,
92 })
93 };
94 self.cst_node_map.try_insert(
95 node as *mut crate::records::ast_node::AstNode,
96 cst_node as *mut crate::records::cst_node::CstNode,
97 );
98 }
99
100 node as *mut AstExpr
101 } else {
102 let mut value: f64 = 0.0;
103 let result = parse_double(&mut value, &self.scratch_data);
104
105 self.next_lexeme();
106
107 if result == ConstantNumberParseResult::Malformed {
108 return self.report_expr_error(
109 start,
110 AstArray::default(),
111 format_args!("Malformed number"),
112 ) as *mut AstExpr;
113 }
114
115 let node = unsafe {
116 (*self.allocator).alloc(AstExprConstantNumber {
117 base: AstExpr {
118 base: crate::records::ast_node::AstNode {
119 class_index:
120 <AstExprConstantNumber as crate::rtti::AstNodeClass>::CLASS_INDEX,
121 location: start,
122 },
123 },
124 value,
125 parse_result: result,
126 })
127 };
128
129 if self.options.store_cst_data {
130 let cst_node = unsafe {
131 (*self.allocator).alloc(CstExprConstantNumber {
132 base: crate::records::cst_node::CstNode {
133 class_index:
134 <CstExprConstantNumber as crate::rtti::CstNodeClass>::CLASS_INDEX,
135 },
136 value: source_data,
137 })
138 };
139 self.cst_node_map.try_insert(
140 node as *mut crate::records::ast_node::AstNode,
141 cst_node as *mut crate::records::cst_node::CstNode,
142 );
143 }
144
145 node as *mut AstExpr
146 }
147 }
148}