luaur_ast/methods/
parser_parse_stat.rs1use crate::functions::get_identifier::get_identifier;
2use crate::records::ast_array::AstArray;
3use crate::records::ast_attr::AstAttr;
4use crate::records::ast_expr::AstExpr;
5use crate::records::ast_expr_binary::AstExprBinaryOp;
6use crate::records::ast_expr_call::AstExprCall;
7use crate::records::ast_name::AstName;
8use crate::records::ast_stat::AstStat;
9use crate::records::ast_stat_expr::AstStatExpr;
10use crate::records::lexeme::Lexeme;
11use crate::records::lexeme::Type;
12use crate::records::location::Location;
13use crate::records::parser::Parser;
14
15impl Parser {
16 pub fn parse_stat(&mut self) -> *mut AstStat {
17 match self.lexer.current().r#type {
18 Type::ReservedIf => return self.parse_if(),
19 Type::ReservedWhile => return self.parse_while(),
20 Type::ReservedDo => return self.parse_do(),
21 Type::ReservedFor => return self.parse_for(),
22 Type::ReservedRepeat => return self.parse_repeat(),
23 Type::ReservedFunction => {
24 return self.parse_function_stat(&AstArray {
25 data: core::ptr::null_mut(),
26 size: 0,
27 }) as *mut AstStat;
28 }
29 Type::ReservedLocal => {
30 if luaur_common::FFlag::LuauConst2.get() {
31 let start = self.lexer.current().location;
32 return self.parse_local(
33 start,
34 start.begin,
35 &AstArray {
36 data: core::ptr::null_mut(),
37 size: 0,
38 },
39 false,
40 );
41 } else {
42 return self.parseLocal_DEPRECATED(&AstArray {
43 data: core::ptr::null_mut(),
44 size: 0,
45 });
46 }
47 }
48 Type::ReservedReturn => return self.parse_return(),
49 Type::ReservedBreak => return self.parser_parse_break(),
50 Type::Attribute | Type::AttributeOpen => return self.parse_attribute_stat(),
51 _ => {}
52 }
53
54 let start = self.lexer.current().location;
55 let expr = self.parse_primary_expr(true);
56
57 if unsafe {
58 crate::rtti::ast_node_is::<AstExprCall>(unsafe { &*std::ptr::addr_of!((*expr).base) })
59 } {
60 return unsafe {
61 (*self.allocator).alloc(AstStatExpr::new((*expr).base.location, expr))
62 as *mut AstStat
63 };
64 }
65
66 let current_type = self.lexer.current().r#type;
67 if current_type == Type(',' as i32) || current_type == Type('=' as i32) {
68 return self.parse_assignment(expr);
69 }
70
71 if let Some(op) = self.parse_compound_op(self.lexer.current()) {
72 return self.parse_compound_assignment(expr, op);
73 }
74
75 let ident = get_identifier(expr);
76
77 if ident.operator_eq_c_char(c"type".as_ptr()) {
78 return self.parse_type_alias(&unsafe { (*expr).base.location }, false, unsafe {
79 (*expr).base.location.begin
80 });
81 }
82
83 if luaur_common::FFlag::DebugLuauUserDefinedClasses.get()
84 && ident.operator_eq_c_char(c"class".as_ptr())
85 {
86 return self.parse_class_stat(&start, false);
87 }
88
89 if ident.operator_eq_c_char(c"export".as_ptr()) {
90 if luaur_common::FFlag::LuauConst2.get() {
91 let current = self.lexer.current();
92 let is_local = current.r#type == Type::ReservedLocal;
93 let is_function = current.r#type == Type::ReservedFunction;
94 let is_const = current.r#type == Type::Name
95 && AstName::ast_name_c_char(unsafe { current.data.name })
96 .operator_eq_c_char(c"const".as_ptr());
97 let is_class = luaur_common::FFlag::DebugLuauUserDefinedClasses.get()
98 && current.r#type == Type::Name
99 && AstName::ast_name_c_char(unsafe { current.data.name })
100 .operator_eq_c_char(c"class".as_ptr());
101
102 if is_local || is_function || is_const || is_class {
103 return self.parse_export_value(
104 &unsafe { (*expr).base.location },
105 unsafe { (*expr).base.location.begin },
106 &AstArray {
107 data: core::ptr::null_mut(),
108 size: 0,
109 },
110 );
111 } else if current.r#type == Type::Name
112 && AstName::ast_name_c_char(unsafe { current.data.name })
113 .operator_eq_c_char(c"type".as_ptr())
114 {
115 let type_keyword_position = current.location.begin;
116 self.next_lexeme();
117 return self.parse_type_alias(
118 &unsafe { (*expr).base.location },
119 true,
120 type_keyword_position,
121 );
122 }
123 } else if luaur_common::FFlag::DebugLuauUserDefinedClasses.get()
124 && AstName::ast_name_c_char(unsafe { self.lexer.current().data.name })
125 .operator_eq_c_char(c"class".as_ptr())
126 {
127 self.next_lexeme();
128 return self.parse_class_stat(&start, true);
129 } else if self.lexer.current().r#type == Type::Name
130 && AstName::ast_name_c_char(unsafe { self.lexer.current().data.name })
131 .operator_eq_c_char(c"type".as_ptr())
132 {
133 let type_keyword_position = self.lexer.current().location.begin;
134 self.next_lexeme();
135 return self.parse_type_alias(
136 &unsafe { (*expr).base.location },
137 true,
138 type_keyword_position,
139 );
140 }
141 }
142
143 if ident.operator_eq_c_char(c"continue".as_ptr()) {
144 return self.parser_parse_continue(&unsafe { (*expr).base.location });
145 }
146
147 if luaur_common::FFlag::LuauConst2.get() && ident.operator_eq_c_char(c"const".as_ptr()) {
148 return self.parse_local(
149 unsafe { (*expr).base.location },
150 unsafe { (*expr).base.location.begin },
151 &AstArray {
152 data: core::ptr::null_mut(),
153 size: 0,
154 },
155 true,
156 );
157 }
158
159 if self.options.allow_declaration_syntax {
160 if ident.operator_eq_c_char(c"declare".as_ptr()) {
161 return self.parse_declaration(
162 &unsafe { (*expr).base.location },
163 &AstArray {
164 data: core::ptr::null_mut(),
165 size: 0,
166 },
167 );
168 }
169 }
170
171 if start
172 .begin
173 .operator_eq(&self.lexer.current().location.begin)
174 {
175 self.next_lexeme();
176 }
177
178 let expr_location = unsafe { (*expr).base.location };
179 let exprs = self.copy_initializer_list_t(&[expr]);
180
181 self.report_stat_error(
182 expr_location,
183 exprs,
184 AstArray {
185 data: core::ptr::null_mut(),
186 size: 0,
187 },
188 format_args!("Incomplete statement: expected assignment or a function call"),
189 ) as *mut AstStat
190 }
191}