luaur_ast/methods/
parser_parse_assignment.rs1use crate::functions::is_expr_l_value::is_expr_l_value;
10use crate::records::ast_expr::AstExpr;
11use crate::records::ast_node::AstNode;
12use crate::records::ast_stat::AstStat;
13use crate::records::ast_stat_assign::AstStatAssign;
14use crate::records::cst_node::CstNode;
15use crate::records::cst_stat_assign::CstStatAssign;
16use crate::records::lexeme::Type;
17use crate::records::location::Location;
18use crate::records::parser::Parser;
19use crate::records::position::Position;
20use crate::records::temp_vector::TempVector;
21
22impl Parser {
23 pub fn parse_assignment(&mut self, mut initial: *mut AstExpr) -> *mut AstStat {
24 if !is_expr_l_value(initial) {
25 initial = if luaur_common::FFlag::LuauExportValueSyntax.get()
26 && luaur_common::FFlag::LuauConst2.get()
27 {
28 self.report_l_value_error(initial) as *mut AstExpr
29 } else {
30 let expressions = self.copy_initializer_list_t(&[initial]);
31 self.report_expr_error(
32 unsafe { (*initial).base.location },
33 expressions,
34 format_args!("Assigned expression must be a variable or a field"),
35 ) as *mut AstExpr
36 };
37 }
38
39 let mut vars = TempVector::new(&mut self.scratch_expr);
40 let mut vars_comma_positions = TempVector::new(&mut self.scratch_position);
41 vars.push_back(initial);
42
43 while self.lexer.current().r#type == Type(b',' as i32) {
44 if self.options.store_cst_data {
45 vars_comma_positions.push_back(self.lexer.current().location.begin);
46 }
47 self.next_lexeme();
48
49 let mut expr = self.parse_primary_expr(true);
50
51 if !is_expr_l_value(expr) {
52 expr = if luaur_common::FFlag::LuauExportValueSyntax.get()
53 && luaur_common::FFlag::LuauConst2.get()
54 {
55 self.report_l_value_error(expr) as *mut AstExpr
56 } else {
57 let expressions = self.copy_initializer_list_t(&[expr]);
58 self.report_expr_error(
59 unsafe { (*expr).base.location },
60 expressions,
61 format_args!("Assigned expression must be a variable or a field"),
62 ) as *mut AstExpr
63 };
64 }
65
66 vars.push_back(expr);
67 }
68
69 let equals_found = self.expect_and_consume_char('=', "assignment");
70 let equals_position = if equals_found {
71 self.lexer.previous_location().begin
72 } else {
73 Position::missing()
74 };
75
76 let mut values = TempVector::new(&mut self.scratch_expr_aux);
77 let mut values_comma_positions = TempVector::new(&mut self.scratch_position);
78 self.parse_expr_list(
79 &mut values,
80 if self.options.store_cst_data {
81 Some(&mut values_comma_positions)
82 } else {
83 None
84 },
85 );
86
87 let vars_array = self.copy_temp_vector_t(&vars);
88 let values_array = self.copy_temp_vector_t(&values);
89
90 let node = unsafe {
91 (*self.allocator).alloc(AstStatAssign::new(
92 Location::new(
93 (*initial).base.location.begin,
94 (**values.back()).base.location.end,
95 ),
96 vars_array,
97 values_array,
98 ))
99 };
100
101 if self.options.store_cst_data {
102 let vars_comma = self.copy_temp_vector_t(&vars_comma_positions);
103 let values_comma = self.copy_temp_vector_t(&values_comma_positions);
104 let cst_node = unsafe {
105 (*self.allocator).alloc(CstStatAssign::new(
106 vars_comma,
107 equals_position,
108 values_comma,
109 ))
110 };
111 self.cst_node_map
112 .try_insert(node as *mut AstNode, cst_node as *mut CstNode);
113 }
114
115 node as *mut AstStat
116 }
117}