Skip to main content

luaur_ast/methods/
parser_parse_function_args.rs

1//! Node: `cxx:Method:Luau.Ast:Ast/src/Parser.cpp:4068:parseFunctionArgs`
2//!
3//! Faithful port of `Parser::parseFunctionArgs` — the function-call argument
4//! parser (`args ::= '(' [explist] ')' | tableconstructor | String`). Each
5//! variant produces an `AstExprCall` node; the parenthesised branch collects
6//! comma positions under `store_cst_data` and records CST open/close parens.
7
8use crate::records::ast_array::AstArray;
9use crate::records::ast_expr::AstExpr;
10use crate::records::ast_expr_call::AstExprCall;
11use crate::records::ast_node::AstNode;
12use crate::records::ast_type_or_pack::AstTypeOrPack;
13use crate::records::cst_expr_call::CstExprCall;
14use crate::records::cst_node::CstNode;
15use crate::records::lexeme::Type;
16use crate::records::location::Location;
17use crate::records::parser::Parser;
18use crate::records::position::Position;
19use crate::records::temp_vector::TempVector;
20
21impl Parser {
22    pub fn parse_function_args(&mut self, func: *mut AstExpr, self_: bool) -> *mut AstExpr {
23        if self.lexer.current().r#type == Type('(' as i32) {
24            let arg_start = self.lexer.current().location.end;
25
26            if unsafe { (*func).base.location.end.line } != self.lexer.current().location.begin.line
27            {
28                self.report_ambiguous_call_error();
29            }
30
31            let match_paren =
32                crate::records::match_lexeme::MatchLexeme::new(&*self.lexer.current());
33            self.next_lexeme();
34
35            let mut args = TempVector::new(&mut self.scratch_expr);
36            let mut comma_positions = TempVector::new(&mut self.scratch_position);
37
38            if self.lexer.current().r#type != Type(')' as i32) {
39                self.parse_expr_list(
40                    &mut args,
41                    if self.options.store_cst_data {
42                        Some(&mut comma_positions)
43                    } else {
44                        None
45                    },
46                );
47            }
48
49            let end = self.lexer.current().location;
50            let arg_end = end.end;
51
52            let closing_paren_found = self.expect_match_and_consume(')', &match_paren, true);
53
54            let args_array = self.copy_temp_vector_t(&args);
55            let explicit_types: AstArray<AstTypeOrPack> = AstArray {
56                data: core::ptr::null_mut(),
57                size: 0,
58            };
59
60            let node = unsafe {
61                (*self.allocator).alloc(AstExprCall::new(
62                    Location::new((*func).base.location.begin, end.end),
63                    func,
64                    args_array,
65                    self_,
66                    explicit_types,
67                    Location::new(arg_start, arg_end),
68                ))
69            };
70
71            if self.options.store_cst_data {
72                let comma_positions_array = self.copy_temp_vector_t(&comma_positions);
73                let cst_node = unsafe {
74                    (*self.allocator).alloc(CstExprCall::new(
75                        match_paren.position,
76                        if closing_paren_found {
77                            self.lexer.previous_location().begin
78                        } else {
79                            Position::missing()
80                        },
81                        comma_positions_array,
82                    ))
83                };
84                self.cst_node_map
85                    .try_insert(node as *mut AstNode, cst_node as *mut CstNode);
86            }
87
88            node as *mut AstExpr
89        } else if self.lexer.current().r#type == Type('{' as i32) {
90            let arg_start = self.lexer.current().location.end;
91            let expr = self.parse_table_constructor();
92            let arg_end = self.lexer.previous_location().end;
93
94            let exprs = self.copy_t_usize(&expr as *const *mut AstExpr, 1);
95            let explicit_types: AstArray<AstTypeOrPack> = AstArray {
96                data: core::ptr::null_mut(),
97                size: 0,
98            };
99
100            let node = unsafe {
101                (*self.allocator).alloc(AstExprCall::new(
102                    Location::new((*func).base.location.begin, (*expr).base.location.end),
103                    func,
104                    exprs,
105                    self_,
106                    explicit_types,
107                    Location::new(arg_start, arg_end),
108                ))
109            };
110
111            if self.options.store_cst_data {
112                let cst_node = unsafe {
113                    (*self.allocator).alloc(CstExprCall::new(
114                        Position::missing(),
115                        Position::missing(),
116                        AstArray {
117                            data: core::ptr::null_mut(),
118                            size: 0,
119                        },
120                    ))
121                };
122                self.cst_node_map
123                    .try_insert(node as *mut AstNode, cst_node as *mut CstNode);
124            }
125
126            node as *mut AstExpr
127        } else if self.lexer.current().r#type == Type::RawString
128            || self.lexer.current().r#type == Type::QuotedString
129        {
130            let arg_location = self.lexer.current().location;
131            let expr = self.parse_string();
132
133            let exprs = self.copy_t_usize(&expr as *const *mut AstExpr, 1);
134            let explicit_types: AstArray<AstTypeOrPack> = AstArray {
135                data: core::ptr::null_mut(),
136                size: 0,
137            };
138
139            let node = unsafe {
140                (*self.allocator).alloc(AstExprCall::new(
141                    Location::new((*func).base.location.begin, (*expr).base.location.end),
142                    func,
143                    exprs,
144                    self_,
145                    explicit_types,
146                    arg_location,
147                ))
148            };
149
150            if self.options.store_cst_data {
151                let cst_node = unsafe {
152                    (*self.allocator).alloc(CstExprCall::new(
153                        Position::missing(),
154                        Position::missing(),
155                        AstArray {
156                            data: core::ptr::null_mut(),
157                            size: 0,
158                        },
159                    ))
160                };
161                self.cst_node_map
162                    .try_insert(node as *mut AstNode, cst_node as *mut CstNode);
163            }
164
165            node as *mut AstExpr
166        } else {
167            self.report_function_args_error(func, self_)
168        }
169    }
170}