luaur_ast/methods/
parser_parse_local.rs1use crate::enums::type_lexer::Type;
2use crate::functions::is_enough_values::is_enough_values;
3use crate::records::ast_array::AstArray;
4use crate::records::ast_attr::AstAttr;
5use crate::records::ast_expr::AstExpr;
6use crate::records::ast_local::AstLocal;
7use crate::records::ast_stat::AstStat;
8use crate::records::ast_stat_local::AstStatLocal;
9use crate::records::ast_stat_local_function::AstStatLocalFunction;
10use crate::records::binding::Binding;
11use crate::records::cst_stat_local::CstStatLocal;
12use crate::records::cst_stat_local_function::CstStatLocalFunction;
13use crate::records::lexeme::Lexeme;
14use crate::records::location::Location;
15use crate::records::parser::Parser;
16use crate::records::position::Position;
17use crate::records::temp_vector::TempVector;
18
19impl Parser {
20 pub fn parse_local(
21 &mut self,
22 start: Location,
23 keyword_position: Position,
24 attributes: &AstArray<*mut AstAttr>,
25 is_const: bool,
26 ) -> *mut AstStat {
27 if !is_const {
28 self.next_lexeme();
29 }
30
31 if self.lexer.current().r#type == Type::ReservedFunction {
32 let mut match_function = *self.lexer.current();
33 self.next_lexeme();
34
35 let function_keyword_position = match_function.location.begin;
42 if match_function.location.begin.line == start.begin.line {
43 match_function.location.begin.column = start.begin.column;
44 }
45
46 let name = self.parse_name("variable name");
47
48 self.match_recovery_stop_on_token[Type::ReservedEnd.0 as usize] += 1;
49
50 let (body, var) = self.parse_function_body(
51 false,
52 &match_function,
53 &name.name,
54 Some(&name),
55 attributes,
56 is_const,
57 );
58
59 self.match_recovery_stop_on_token[Type::ReservedEnd.0 as usize] -= 1;
60
61 let location = Location::new(start.begin, unsafe { (*body).base.base.location.end });
62
63 let node = unsafe {
64 (*self.allocator).alloc(AstStatLocalFunction::new(location, var, body, is_const))
65 };
66
67 if self.options.store_cst_data {
68 let cst_node = unsafe {
69 (*self.allocator).alloc(CstStatLocalFunction::new(
70 keyword_position,
71 function_keyword_position,
72 ))
73 };
74 self.cst_node_map.try_insert(
75 node as *mut crate::records::ast_node::AstNode,
76 cst_node as *mut crate::records::cst_node::CstNode,
77 );
78 }
79
80 return node as *mut AstStat;
81 } else {
82 if attributes.size != 0 {
83 return self.report_stat_error(
84 self.lexer.current().location,
85 AstArray {
86 data: core::ptr::null_mut(),
87 size: 0,
88 },
89 AstArray {
90 data: core::ptr::null_mut(),
91 size: 0,
92 },
93 format_args!(
94 "Expected 'function' after local declaration with attribute, but got {} instead",
95 self.lexer.current().to_string()
96 ),
97 ) as *mut AstStat;
98 }
99
100 self.match_recovery_stop_on_token[Type::Operator.0 as usize] += 1;
101
102 let mut names = TempVector::new(&mut self.scratch_binding);
103 let mut vars_comma_positions = AstArray {
104 data: core::ptr::null_mut(),
105 size: 0,
106 };
107
108 if self.options.store_cst_data {
109 self.parse_binding_list(
110 &mut names,
111 false,
112 &mut vars_comma_positions,
113 core::ptr::null_mut(),
114 core::ptr::null_mut(),
115 is_const,
116 );
117 } else {
118 self.parse_binding_list(
119 &mut names,
120 false,
121 core::ptr::null_mut(),
122 core::ptr::null_mut(),
123 core::ptr::null_mut(),
124 is_const,
125 );
126 }
127
128 self.match_recovery_stop_on_token[Type::Operator.0 as usize] -= 1;
129
130 let mut vars = TempVector::new(&mut self.scratch_local);
131 let mut values = TempVector::new(&mut self.scratch_expr);
132 let mut values_comma_positions = TempVector::new(&mut self.scratch_position);
133
134 let mut equals_sign_location = None;
135
136 if self.lexer.current().r#type == Type::Operator {
137 equals_sign_location = Some(self.lexer.current().location);
138 self.next_lexeme();
139
140 if self.options.store_cst_data {
141 self.parse_expr_list(&mut values, Some(&mut values_comma_positions));
142 } else {
143 self.parse_expr_list(&mut values, None);
144 }
145 }
146
147 for i in 0..names.size() {
148 vars.push_back(self.push_local(names.operator_index(i)));
149 }
150
151 let end = if values.empty() {
152 *self.lexer.previous_location()
153 } else {
154 unsafe { (**values.back()).base.location }
155 };
156
157 if luaur_common::FFlag::LuauConstJustReportErrorForUnderfill.get() {
158 let node = unsafe {
159 (*self.allocator).alloc(AstStatLocal::new(
160 Location::new(start.begin, end.end),
161 self.copy_temp_vector_t(&vars),
162 self.copy_temp_vector_t(&values),
163 equals_sign_location,
164 is_const,
165 ))
166 };
167
168 if self.options.store_cst_data {
169 let cst_node = unsafe {
170 (*self.allocator).alloc(CstStatLocal::new(
171 self.extract_annotation_colon_positions(&names),
172 vars_comma_positions,
173 self.copy_temp_vector_t(&values_comma_positions),
174 ))
175 };
176 self.cst_node_map.try_insert(
177 node as *mut crate::records::ast_node::AstNode,
178 cst_node as *mut crate::records::cst_node::CstNode,
179 );
180 }
181
182 if is_const && !is_enough_values(&mut values, vars.size()) {
183 self.report(
184 unsafe { (*node).base.base.location },
185 format_args!("Missing initializer in const declaration"),
186 );
187 }
188
189 return node as *mut AstStat;
190 } else {
191 if is_const && !is_enough_values(&mut values, vars.size()) {
192 return self.report_stat_error(
193 Location::new(start.begin, end.end),
194 AstArray {
195 data: core::ptr::null_mut(),
196 size: 0,
197 },
198 AstArray {
199 data: core::ptr::null_mut(),
200 size: 0,
201 },
202 format_args!("Missing initializer in const declaration"),
203 ) as *mut AstStat;
204 }
205
206 let node = unsafe {
207 (*self.allocator).alloc(AstStatLocal::new(
208 Location::new(start.begin, end.end),
209 self.copy_temp_vector_t(&vars),
210 self.copy_temp_vector_t(&values),
211 equals_sign_location,
212 is_const,
213 ))
214 };
215
216 if self.options.store_cst_data {
217 let cst_node = unsafe {
218 (*self.allocator).alloc(CstStatLocal::new(
219 self.extract_annotation_colon_positions(&names),
220 vars_comma_positions,
221 self.copy_temp_vector_t(&values_comma_positions),
222 ))
223 };
224 self.cst_node_map.try_insert(
225 node as *mut crate::records::ast_node::AstNode,
226 cst_node as *mut crate::records::cst_node::CstNode,
227 );
228 }
229
230 return node as *mut AstStat;
231 }
232 }
233 }
234}