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, safe_unwrap,
13    types::{
14        Bracketed, Closure, ElseIfExpression, Expression, FunctionCall, FunctionCallInvoked,
15        IfExpression, Parse, ParseWithArgs, Pointer, PrefixExp, Table, TableAccess,
16        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)
140                    .map(Pointer::new)
141                    .map(Self::Closure)
142            }
143            TokenType::Keyword(Keyword::Nil) => Some(Self::Nil(token)),
144            TokenType::Keyword(Keyword::If) => {
145                IfExpression::parse(token, lexer, errors).map(Self::IfExpression)
146            }
147            _ => None,
148        }
149    }
150}
151
152impl Parse for Expression {
153    fn parse(mut token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
154        let maybe_unary_operator = match token.token_type {
155            TokenType::Operator(Operator::Minus | Operator::Not | Operator::Length) => {
156                let temp = token;
157                token = lexer.next_token();
158
159                Some(temp)
160            }
161            _ => None,
162        };
163
164        let left = Self::parse_inner(token, lexer, errors)?;
165        let left = if let Some(operator) = maybe_unary_operator {
166            Self::UnaryExpression {
167                operator,
168                expression: Pointer::new(left),
169            }
170        } else {
171            left
172        };
173
174        let state = lexer.save_state();
175        let next_token = lexer.next_token();
176
177        match next_token.token_type {
178            TokenType::Operator(_)
179            | TokenType::CompoundOperator(_)
180            | TokenType::Symbol(Symbol::OpeningAngleBrackets)
181            | TokenType::Symbol(Symbol::ClosingAngleBrackets) => Some(Self::BinaryExpression {
182                left: Pointer::new(left),
183                operator: next_token,
184                right: safe_unwrap!(
185                    lexer,
186                    errors,
187                    "Expected <expr>",
188                    Self::try_parse(lexer, errors).map(Pointer::new)
189                ),
190            }),
191            TokenType::Symbol(Symbol::Typecast) => Some(Self::TypeCast {
192                expression: Pointer::new(left),
193                operator: next_token,
194                cast_to: safe_unwrap!(
195                    lexer,
196                    errors,
197                    "Expected <type>",
198                    TypeValue::try_parse(lexer, errors).map(Pointer::new)
199                ),
200            }),
201            _ => {
202                lexer.set_state(state);
203                Some(left)
204            }
205        }
206    }
207}
208impl TryParse for Expression {}
209
210impl Parse for IfExpression {
211    fn parse(if_keyword: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
212        if if_keyword != TokenType::Keyword(Keyword::If) {
213            return None;
214        }
215
216        let condition = safe_unwrap!(
217            lexer,
218            errors,
219            "Expected <expr>",
220            Pointer::<Expression>::try_parse(lexer, errors)
221        );
222
223        next_token_recoverable!(
224            lexer,
225            then_keyword,
226            TokenType::Keyword(Keyword::Then),
227            TokenType::Keyword(Keyword::Then),
228            errors,
229            "Expected `then`"
230        );
231
232        let if_expression = safe_unwrap!(
233            lexer,
234            errors,
235            "Expected <expr>",
236            Pointer::<Expression>::try_parse(lexer, errors)
237        );
238
239        let else_if_expressions =
240            Pointer::<Vec<ElseIfExpression>>::try_parse(lexer, errors).unwrap_or_default();
241
242        next_token_recoverable!(
243            lexer,
244            else_keyword,
245            TokenType::Keyword(Keyword::Else),
246            TokenType::Keyword(Keyword::Else),
247            errors,
248            "Expected `else`"
249        );
250        let else_expression = safe_unwrap!(
251            lexer,
252            errors,
253            "Expected <expr>",
254            Expression::try_parse(lexer, errors).map(Pointer::new)
255        );
256
257        Some(Self {
258            if_keyword,
259            condition,
260            then_keyword,
261            if_expression,
262            else_if_expressions,
263            else_keyword,
264            else_expression,
265        })
266    }
267}
268impl TryParse for IfExpression {}
269
270impl Parse for ElseIfExpression {
271    fn parse(
272        else_if_keyword: Token,
273        lexer: &mut Lexer,
274        errors: &mut Vec<ParseError>,
275    ) -> Option<Self> {
276        if else_if_keyword != TokenType::Keyword(Keyword::Elseif) {
277            return None;
278        }
279
280        let condition = safe_unwrap!(
281            lexer,
282            errors,
283            "Expected <expr>",
284            Pointer::<Expression>::try_parse(lexer, errors)
285        );
286
287        next_token_recoverable!(
288            lexer,
289            then_keyword,
290            TokenType::Keyword(Keyword::Then),
291            TokenType::Keyword(Keyword::Then),
292            errors,
293            "Expected `then`"
294        );
295
296        let expression = safe_unwrap!(
297            lexer,
298            errors,
299            "Expected <expr>",
300            Pointer::<Expression>::try_parse(lexer, errors)
301        );
302
303        Some(Self {
304            else_if_keyword,
305            condition,
306            then_keyword,
307            expression,
308        })
309    }
310}
311impl TryParse for ElseIfExpression {}