1mod function;
4mod table;
5mod var;
6
7use luau_lexer::prelude::{
8 Keyword, Lexer, Literal, Operator, ParseError, Symbol, Token, TokenType,
9};
10
11use crate::{
12 handle_error_token, parse_bracketed, safe_unwrap,
13 types::{
14 Bracketed, Closure, ElseIfExpression, Expression, ExpressionWrap, FunctionArguments,
15 FunctionCall, FunctionCallInvoked, IfExpression, Parse, ParseWithArgs, Pointer, PrefixExp,
16 Table, TableAccess, TableAccessPrefix, TryParse, TypeValue, Var,
17 },
18 utils::get_token_type_display,
19};
20
21impl PrefixExp {
22 fn parse_more(&self, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
24 maybe_next_token!(lexer, colon, TokenType::Symbol(Symbol::Colon));
25
26 let invoked = if let Some(colon) = colon {
27 next_token_recoverable!(
28 lexer,
29 method,
30 TokenType::Identifier(_) | TokenType::PartialKeyword(_),
31 TokenType::Identifier("*error*".into(),),
32 errors,
33 "Expected ".to_string()
34 + get_token_type_display(&TokenType::Identifier("".into(),))
35 );
36
37 FunctionCallInvoked::TableMethod {
38 table: Pointer::new(self.clone()),
39 colon: Pointer::new(colon),
40 method: Pointer::new(method),
41 }
42 } else {
43 FunctionCallInvoked::Function(Pointer::new(self.clone()))
44 };
45
46 if let Some(call) = FunctionCall::try_parse_with_invoked(lexer, errors, invoked) {
47 let prefix_exp = Self::FunctionCall(call);
48
49 return prefix_exp.parse_more(lexer, errors).or(Some(prefix_exp));
50 }
51
52 if let Some(accessed_keys) = Vec::try_parse(lexer, errors) {
53 let prefix_exp = Self::Var(Var::TableAccess(TableAccess {
54 prefix: match self {
55 PrefixExp::FunctionCall(function_call) => {
56 TableAccessPrefix::FunctionCall(Pointer::new(function_call.clone()))
57 }
58 PrefixExp::ExpressionWrap(bracketed) => {
59 TableAccessPrefix::ExpressionWrap(Pointer::new(bracketed.clone()))
60 }
61 _ => unreachable!(),
62 },
63 accessed_keys,
64 }));
65
66 return prefix_exp.parse_more(lexer, errors).or(Some(prefix_exp));
67 }
68
69 None
70 }
71}
72
73impl Parse for PrefixExp {
74 fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
75 let var = Var::parse(token.clone(), lexer, errors);
76 if let Some(var) = var {
77 let prefix_exp = Self::Var(var);
78
79 return prefix_exp.parse_more(lexer, errors).or(Some(prefix_exp));
80 }
81
82 if token == TokenType::Symbol(Symbol::OpeningParenthesis) {
83 let expression_wrap = Bracketed::<Pointer<Expression>>::parse_with(
84 token,
85 lexer,
86 errors,
87 ("Expected <expr>", Symbol::ClosingParenthesis),
88 );
89
90 if let Some(expression_wrap) = expression_wrap {
91 FunctionCall::try_parse_with_invoked(
92 lexer,
93 errors,
94 FunctionCallInvoked::Function(Pointer::new(PrefixExp::ExpressionWrap(
95 expression_wrap.clone(),
96 ))),
97 )
98 .map(Self::FunctionCall)
99 .or(Some(Self::ExpressionWrap(expression_wrap)))
100 } else {
101 None
102 }
103 } else {
104 None
105 }
106 }
107}
108impl TryParse for PrefixExp {}
109
110impl Expression {
111 pub fn parse_from_literal(token: Token) -> Option<Self> {
113 match &token.token_type {
114 TokenType::Literal(literal) => match literal {
115 Literal::Number(_) => Some(Self::Number(token)),
116 Literal::String(_) => Some(Self::String(token)),
117 Literal::Boolean(_) => Some(Self::Boolean(token)),
118 },
119 _ => None,
120 }
121 }
122
123 fn parse_inner(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
126 match token.token_type {
127 TokenType::Error(error) => handle_error_token!(errors, error),
128 TokenType::Literal(_) => Self::parse_from_literal(token),
129 TokenType::Identifier(_)
130 | TokenType::PartialKeyword(_)
131 | TokenType::Symbol(Symbol::OpeningParenthesis) => {
132 match PrefixExp::parse(token, lexer, errors) {
133 Some(PrefixExp::ExpressionWrap(wrap)) => Some(Self::ExpressionWrap(wrap)),
134 Some(PrefixExp::FunctionCall(function_call)) => {
135 Some(Self::FunctionCall(function_call))
136 }
137 Some(PrefixExp::Var(var)) => Some(Self::Var(var)),
138 None => None,
139 }
140 }
141 TokenType::Symbol(Symbol::OpeningCurlyBrackets) => {
142 Table::parse_with(token, lexer, errors, false).map(Self::Table)
143 }
144 TokenType::Keyword(Keyword::Function) | TokenType::Symbol(Symbol::At) => {
145 Closure::parse(token, lexer, errors).map(Self::Closure)
146 }
147 TokenType::Keyword(Keyword::Nil) => Some(Self::Nil(token)),
148 TokenType::Keyword(Keyword::If) => {
149 IfExpression::parse(token, lexer, errors).map(Self::IfExpression)
150 }
151 _ => None,
152 }
153 }
154}
155
156impl Parse for Expression {
157 fn parse(mut token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
158 let maybe_unary_operator = match token.token_type {
159 TokenType::Operator(Operator::Minus | Operator::Not | Operator::Length) => {
160 let temp = token;
161 token = lexer.next_token();
162
163 Some(temp)
164 }
165 _ => None,
166 };
167
168 let left = Self::parse_inner(token, lexer, errors)?;
169 let left = if let Some(operator) = maybe_unary_operator {
170 Self::UnaryExpression {
171 operator,
172 expression: Pointer::new(left),
173 }
174 } else {
175 left
176 };
177
178 let state = lexer.save_state();
179 let next_token = lexer.next_token();
180
181 match next_token.token_type {
182 TokenType::Operator(_)
183 | TokenType::CompoundOperator(_)
184 | TokenType::Symbol(Symbol::OpeningAngleBrackets)
185 | TokenType::Symbol(Symbol::ClosingAngleBrackets) => Some(Self::BinaryExpression {
186 left: Pointer::new(left),
187 operator: next_token,
188 right: safe_unwrap!(
189 lexer,
190 errors,
191 "Expected <expr>",
192 Self::try_parse(lexer, errors).map(Pointer::new)
193 ),
194 }),
195 TokenType::Symbol(Symbol::Typecast) => Some(Self::TypeCast {
196 expression: Pointer::new(left),
197 operator: next_token,
198 cast_to: safe_unwrap!(
199 lexer,
200 errors,
201 "Expected <type>",
202 TypeValue::try_parse(lexer, errors).map(Pointer::new)
203 ),
204 }),
205 _ => {
206 lexer.set_state(state);
207 Some(left)
208 }
209 }
210 }
211}
212impl TryParse for Expression {}
213
214impl Parse for IfExpression {
215 fn parse(if_keyword: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
216 if if_keyword != TokenType::Keyword(Keyword::If) {
217 return None;
218 }
219
220 let condition = safe_unwrap!(
221 lexer,
222 errors,
223 "Expected <expr>",
224 Pointer::<Expression>::try_parse(lexer, errors)
225 );
226
227 next_token_recoverable!(
228 lexer,
229 then_keyword,
230 TokenType::Keyword(Keyword::Then),
231 TokenType::Keyword(Keyword::Then),
232 errors,
233 "Expected `then`"
234 );
235
236 let if_expression = safe_unwrap!(
237 lexer,
238 errors,
239 "Expected <expr>",
240 Pointer::<Expression>::try_parse(lexer, errors)
241 );
242
243 let else_if_expressions =
244 Pointer::<Vec<ElseIfExpression>>::try_parse(lexer, errors).unwrap_or_default();
245
246 next_token_recoverable!(
247 lexer,
248 else_keyword,
249 TokenType::Keyword(Keyword::Else),
250 TokenType::Keyword(Keyword::Else),
251 errors,
252 "Expected `else`"
253 );
254 let else_expression = safe_unwrap!(
255 lexer,
256 errors,
257 "Expected <expr>",
258 Expression::try_parse(lexer, errors).map(Pointer::new)
259 );
260
261 Some(Self {
262 if_keyword,
263 condition,
264 then_keyword,
265 if_expression,
266 else_if_expressions,
267 else_keyword,
268 else_expression,
269 })
270 }
271}
272impl TryParse for IfExpression {}
273
274impl Parse for ElseIfExpression {
275 fn parse(
276 else_if_keyword: Token,
277 lexer: &mut Lexer,
278 errors: &mut Vec<ParseError>,
279 ) -> Option<Self> {
280 if else_if_keyword != TokenType::Keyword(Keyword::Elseif) {
281 return None;
282 }
283
284 let condition = safe_unwrap!(
285 lexer,
286 errors,
287 "Expected <expr>",
288 Pointer::<Expression>::try_parse(lexer, errors)
289 );
290
291 next_token_recoverable!(
292 lexer,
293 then_keyword,
294 TokenType::Keyword(Keyword::Then),
295 TokenType::Keyword(Keyword::Then),
296 errors,
297 "Expected `then`"
298 );
299
300 let expression = safe_unwrap!(
301 lexer,
302 errors,
303 "Expected <expr>",
304 Pointer::<Expression>::try_parse(lexer, errors)
305 );
306
307 Some(Self {
308 else_if_keyword,
309 condition,
310 then_keyword,
311 expression,
312 })
313 }
314}
315impl TryParse for ElseIfExpression {}