luau_parser/impl/expression/
mod.rs

1//! All `impl` blocks for expression-related types
2
3mod 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    /// Tries parsing more [`PrefixExp`]s starting with this one.
23    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                let prefix_exp = Self::ExpressionWrap(expression_wrap);
92
93                prefix_exp.parse_more(lexer, errors).or(Some(prefix_exp))
94            } else {
95                None
96            }
97        } else {
98            None
99        }
100    }
101}
102impl TryParse for PrefixExp {}
103
104impl Expression {
105    /// Parses an [`Expression`] from a literal [`TokenType::Literal`]
106    pub fn parse_from_literal(token: Token) -> Option<Self> {
107        match &token.token_type {
108            TokenType::Literal(literal) => match literal {
109                Literal::Number(_) => Some(Self::Number(token)),
110                Literal::String(_) => Some(Self::String(token)),
111                Literal::Boolean(_) => Some(Self::Boolean(token)),
112            },
113            _ => None,
114        }
115    }
116
117    /// Inner function for [`Expression::parse`]. This function doesn't check for
118    /// operators before nor after the expression, which [`Expression::parse`] does.
119    fn parse_inner(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
120        match token.token_type {
121            TokenType::Error(error) => handle_error_token!(errors, error),
122            TokenType::Literal(_) => Self::parse_from_literal(token),
123            TokenType::Identifier(_)
124            | TokenType::PartialKeyword(_)
125            | TokenType::Symbol(Symbol::OpeningParenthesis) => {
126                match PrefixExp::parse(token, lexer, errors) {
127                    Some(PrefixExp::ExpressionWrap(wrap)) => Some(Self::ExpressionWrap(wrap)),
128                    Some(PrefixExp::FunctionCall(function_call)) => {
129                        Some(Self::FunctionCall(function_call))
130                    }
131                    Some(PrefixExp::Var(var)) => Some(Self::Var(var)),
132                    None => None,
133                }
134            }
135            TokenType::Symbol(Symbol::OpeningCurlyBrackets) => {
136                Table::parse_with(token, lexer, errors, false).map(Self::Table)
137            }
138            TokenType::Keyword(Keyword::Function) | TokenType::Symbol(Symbol::At) => {
139                Closure::parse(token, lexer, errors).map(Self::Closure)
140            }
141            TokenType::Keyword(Keyword::Nil) => Some(Self::Nil(token)),
142            TokenType::Keyword(Keyword::If) => {
143                IfExpression::parse(token, lexer, errors).map(Self::IfExpression)
144            }
145            _ => None,
146        }
147    }
148}
149
150impl Parse for Expression {
151    fn parse(mut token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
152        let maybe_unary_operator = match token.token_type {
153            TokenType::Operator(Operator::Minus | Operator::Not | Operator::Length) => {
154                let temp = token;
155                token = lexer.next_token();
156
157                Some(temp)
158            }
159            _ => None,
160        };
161
162        let left = Self::parse_inner(token, lexer, errors)?;
163        let left = if let Some(operator) = maybe_unary_operator {
164            Self::UnaryExpression {
165                operator,
166                expression: Pointer::new(left),
167            }
168        } else {
169            left
170        };
171
172        let state = lexer.save_state();
173        let next_token = lexer.next_token();
174
175        match next_token.token_type {
176            TokenType::Operator(_)
177            | TokenType::CompoundOperator(_)
178            | TokenType::Symbol(Symbol::OpeningAngleBrackets)
179            | TokenType::Symbol(Symbol::ClosingAngleBrackets) => Some(Self::BinaryExpression {
180                left: Pointer::new(left),
181                operator: next_token,
182                right: safe_unwrap!(
183                    lexer,
184                    errors,
185                    "Expected <expr>",
186                    Self::try_parse(lexer, errors).map(Pointer::new)
187                ),
188            }),
189            TokenType::Symbol(Symbol::Typecast) => Some(Self::TypeCast {
190                expression: Pointer::new(left),
191                operator: next_token,
192                cast_to: safe_unwrap!(
193                    lexer,
194                    errors,
195                    "Expected <type>",
196                    TypeValue::try_parse(lexer, errors).map(Pointer::new)
197                ),
198            }),
199            _ => {
200                lexer.set_state(state);
201                Some(left)
202            }
203        }
204    }
205}
206impl TryParse for Expression {}
207
208impl Parse for IfExpression {
209    fn parse(if_keyword: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
210        if if_keyword != TokenType::Keyword(Keyword::If) {
211            return None;
212        }
213
214        let condition = safe_unwrap!(
215            lexer,
216            errors,
217            "Expected <expr>",
218            Pointer::<Expression>::try_parse(lexer, errors)
219        );
220
221        next_token_recoverable!(
222            lexer,
223            then_keyword,
224            TokenType::Keyword(Keyword::Then),
225            TokenType::Keyword(Keyword::Then),
226            errors,
227            "Expected `then`"
228        );
229
230        let if_expression = safe_unwrap!(
231            lexer,
232            errors,
233            "Expected <expr>",
234            Pointer::<Expression>::try_parse(lexer, errors)
235        );
236
237        let else_if_expressions =
238            Pointer::<Vec<ElseIfExpression>>::try_parse(lexer, errors).unwrap_or_default();
239
240        next_token_recoverable!(
241            lexer,
242            else_keyword,
243            TokenType::Keyword(Keyword::Else),
244            TokenType::Keyword(Keyword::Else),
245            errors,
246            "Expected `else`"
247        );
248        let else_expression = safe_unwrap!(
249            lexer,
250            errors,
251            "Expected <expr>",
252            Expression::try_parse(lexer, errors).map(Pointer::new)
253        );
254
255        Some(Self {
256            if_keyword,
257            condition,
258            then_keyword,
259            if_expression,
260            else_if_expressions,
261            else_keyword,
262            else_expression,
263        })
264    }
265}
266impl TryParse for IfExpression {}
267
268impl Parse for ElseIfExpression {
269    fn parse(
270        else_if_keyword: Token,
271        lexer: &mut Lexer,
272        errors: &mut Vec<ParseError>,
273    ) -> Option<Self> {
274        if else_if_keyword != TokenType::Keyword(Keyword::Elseif) {
275            return None;
276        }
277
278        let condition = safe_unwrap!(
279            lexer,
280            errors,
281            "Expected <expr>",
282            Pointer::<Expression>::try_parse(lexer, errors)
283        );
284
285        next_token_recoverable!(
286            lexer,
287            then_keyword,
288            TokenType::Keyword(Keyword::Then),
289            TokenType::Keyword(Keyword::Then),
290            errors,
291            "Expected `then`"
292        );
293
294        let expression = safe_unwrap!(
295            lexer,
296            errors,
297            "Expected <expr>",
298            Pointer::<Expression>::try_parse(lexer, errors)
299        );
300
301        Some(Self {
302            else_if_keyword,
303            condition,
304            then_keyword,
305            expression,
306        })
307    }
308}
309impl TryParse for ElseIfExpression {}