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