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