luaur_ast/methods/
parser_parse_table_constructor.rs1use crate::records::ast_expr::AstExpr;
2use crate::records::parser::Parser;
3
4impl Parser {
5 pub fn parse_table_constructor(&mut self) -> *mut AstExpr {
6 use crate::records::ast_array::AstArray;
7 use crate::records::lexeme::Type;
8 use crate::records::location::Location;
9 use crate::records::match_lexeme::MatchLexeme;
10 use crate::records::position::Position;
11 use crate::records::temp_vector::TempVector;
12 use luaur_common::FFlag;
13
14 let mut items = TempVector::new(&mut self.scratch_item);
15 let mut cst_items = TempVector::new(&mut self.scratch_cst_item);
16
17 let start = self.lexer.current().location;
18
19 let match_brace = MatchLexeme::new(self.lexer.current());
20 self.expect_and_consume_char('{', "table literal");
21
22 let mut last_element_indent_deprecated = 0u32;
23
24 while self.lexer.current().r#type != Type(b'}' as i32) {
25 if !FFlag::LuauTableEntriesDontNeedToMatchIndent.get() {
26 last_element_indent_deprecated = self.lexer.current().location.begin.column;
27 }
28
29 if self.lexer.current().r#type == Type(b'[' as i32) {
30 let indexer_open_position = self.lexer.current().location.begin;
31 let match_location_bracket = MatchLexeme::new(self.lexer.current());
32 self.next_lexeme();
33
34 let key = self.parse_expr_i32(0);
35
36 let closing_bracket_found =
37 self.expect_match_and_consume(']', &match_location_bracket, false);
38 let indexer_close_position = if closing_bracket_found {
39 self.lexer.previous_location().begin
40 } else {
41 Position::missing()
42 };
43
44 let equals_found = self.expect_and_consume_char('=', "table field");
45 let equals_position = if equals_found {
46 self.lexer.previous_location().begin
47 } else {
48 Position::missing()
49 };
50
51 let value = self.parse_expr_i32(0);
52
53 items.push_back(crate::records::ast_expr_table::Item {
54 kind: crate::records::ast_expr_table::ItemKind::General,
55 key,
56 value,
57 });
58
59 if self.options.store_cst_data {
60 let sep = self.table_separator();
61 let separator = match sep {
62 crate::enums::separator::Separator::Comma => {
63 crate::records::cst_expr_table::CstExprTableSeparator::Comma
64 }
65 crate::enums::separator::Separator::Semicolon => {
66 crate::records::cst_expr_table::CstExprTableSeparator::Semicolon
67 }
68 crate::enums::separator::Separator::Missing => {
69 crate::records::cst_expr_table::CstExprTableSeparator::Missing
70 }
71 };
72 cst_items.push_back(crate::records::cst_expr_table::CstExprTableItem {
73 indexer_open_position,
74 indexer_close_position,
75 equals_position,
76 separator,
77 separator_position: if separator
78 == crate::records::cst_expr_table::CstExprTableSeparator::Missing
79 {
80 Position::missing()
81 } else {
82 self.lexer.current().location.begin
83 },
84 });
85 }
86 } else if self.lexer.current().r#type == Type::Name
87 && self.lexer.lookahead().r#type == Type(b'=' as i32)
88 {
89 let name = self.parse_name("table field");
90
91 let equals_position = self.lexer.current().location.begin;
92 self.expect_and_consume_char('=', "table field");
93
94 let len = unsafe { core::ffi::CStr::from_ptr(name.name.value).to_bytes().len() };
95 let name_string = AstArray {
96 data: name.name.value as *mut core::ffi::c_char,
97 size: len,
98 };
99
100 let key = unsafe {
101 (*self.allocator).alloc(crate::methods::ast_expr_constant_string_ast_expr_constant_string::ast_expr_constant_string_ast_expr_constant_string(
102 name.location,
103 name_string,
104 crate::enums::quote_style_ast::QuoteStyle::Unquoted,
105 )) as *mut crate::records::ast_expr::AstExpr
106 };
107 let value = self.parse_expr_i32(0);
108
109 let func = unsafe {
110 crate::rtti::ast_node_as::<crate::records::ast_expr_function::AstExprFunction>(
111 value as *mut crate::records::ast_node::AstNode,
112 )
113 };
114 if !func.is_null() {
115 unsafe {
116 (*func).debugname = name.name;
117 }
118 }
119
120 items.push_back(crate::records::ast_expr_table::Item {
121 kind: crate::records::ast_expr_table::ItemKind::Record,
122 key,
123 value,
124 });
125
126 if self.options.store_cst_data {
127 let sep = self.table_separator();
128 let separator = match sep {
129 crate::enums::separator::Separator::Comma => {
130 crate::records::cst_expr_table::CstExprTableSeparator::Comma
131 }
132 crate::enums::separator::Separator::Semicolon => {
133 crate::records::cst_expr_table::CstExprTableSeparator::Semicolon
134 }
135 crate::enums::separator::Separator::Missing => {
136 crate::records::cst_expr_table::CstExprTableSeparator::Missing
137 }
138 };
139 cst_items.push_back(crate::records::cst_expr_table::CstExprTableItem {
140 indexer_open_position: Position::missing(),
141 indexer_close_position: Position::missing(),
142 equals_position,
143 separator,
144 separator_position: if separator
145 == crate::records::cst_expr_table::CstExprTableSeparator::Missing
146 {
147 Position::missing()
148 } else {
149 self.lexer.current().location.begin
150 },
151 });
152 }
153 } else {
154 let expr = self.parse_expr_i32(0);
155
156 items.push_back(crate::records::ast_expr_table::Item {
157 kind: crate::records::ast_expr_table::ItemKind::List,
158 key: core::ptr::null_mut(),
159 value: expr,
160 });
161
162 if self.options.store_cst_data {
163 let sep = self.table_separator();
164 let separator = match sep {
165 crate::enums::separator::Separator::Comma => {
166 crate::records::cst_expr_table::CstExprTableSeparator::Comma
167 }
168 crate::enums::separator::Separator::Semicolon => {
169 crate::records::cst_expr_table::CstExprTableSeparator::Semicolon
170 }
171 crate::enums::separator::Separator::Missing => {
172 crate::records::cst_expr_table::CstExprTableSeparator::Missing
173 }
174 };
175 cst_items.push_back(crate::records::cst_expr_table::CstExprTableItem {
176 indexer_open_position: Position::missing(),
177 indexer_close_position: Position::missing(),
178 equals_position: Position::missing(),
179 separator,
180 separator_position: if separator
181 == crate::records::cst_expr_table::CstExprTableSeparator::Missing
182 {
183 Position::missing()
184 } else {
185 self.lexer.current().location.begin
186 },
187 });
188 }
189 }
190
191 let current_type = self.lexer.current().r#type;
192 if current_type == Type(b',' as i32) || current_type == Type(b';' as i32) {
193 self.next_lexeme();
194 } else if (current_type == Type(b'[' as i32) || current_type == Type::Name)
195 && (FFlag::LuauTableEntriesDontNeedToMatchIndent.get()
196 || self.lexer.current().location.begin.column == last_element_indent_deprecated)
197 {
198 self.report(
199 self.lexer.current().location,
200 format_args!("Expected ',' after table constructor element"),
201 );
202 } else if current_type != Type(b'}' as i32) {
203 break;
204 }
205 }
206
207 let mut end = self.lexer.current().location;
208
209 if !self.expect_match_and_consume('}', &match_brace, false) {
210 end = *self.lexer.previous_location();
211 }
212
213 let items_array = self.copy_temp_vector_t(&items);
214
215 let node = unsafe {
216 (*self.allocator).alloc(
217 crate::methods::ast_expr_table_ast_expr_table::ast_expr_table_ast_expr_table(
218 Location::new(start.begin, end.end),
219 items_array,
220 ),
221 )
222 };
223
224 if self.options.store_cst_data {
225 let cst_items_array = self.copy_temp_vector_t(&cst_items);
226 let cst_node = unsafe {
227 (*self.allocator).alloc(
228 crate::methods::cst_expr_table_cst_expr_table::cst_expr_table_cst_expr_table(
229 cst_items_array,
230 ),
231 )
232 };
233 self.cst_node_map.try_insert(
234 node as *mut crate::records::ast_node::AstNode,
235 cst_node as *mut crate::records::cst_node::CstNode,
236 );
237 }
238
239 node as *mut AstExpr
240 }
241}