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                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    /// Parses an [`Expression`] from a literal [`TokenType::Literal`]
112    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    /// Inner function for [`Expression::parse`]. This function doesn't check for
124    /// operators before nor after the expression, which [`Expression::parse`] does.
125    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 {}