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