Skip to main content

luaur_ast/methods/
parser_parse_table_constructor.rs

1use 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}