luau_parser/impl/expression/
function.rs

1//! All `impl` blocks for function call-related types:
2//!
3//! * [`FunctionCallInvoked`]
4//! * [`FunctionCall`]
5//! * [`FunctionArguments`]
6//! * [`FunctionArgument`]
7//! * [`Closure`]
8
9use luau_lexer::prelude::{Keyword, Lexer, Literal, ParseError, Symbol, Token, TokenType};
10
11use crate::{
12    force_parse_bracketed, parse_bracketed,
13    types::{
14        Block, BracketedList, Closure, Expression, FunctionArgument, FunctionArguments,
15        FunctionCall, FunctionCallInvoked, Parse, ParseWithArgs, Pointer, PrefixExp, Table,
16        TableAccessPrefix, TryParse, TryParseWithArgs, TypeValue,
17    },
18    utils::{get_token_type_display, get_token_type_display_extended},
19};
20
21impl Parse for FunctionCallInvoked {
22    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
23        let prefix_exp = Pointer::new(PrefixExp::parse(token, lexer, errors)?);
24
25        maybe_next_token!(lexer, colon, TokenType::Symbol(Symbol::Colon));
26        let Some(colon) = colon else {
27            return Some(Self::Function(prefix_exp));
28        };
29
30        next_token_recoverable!(
31            lexer,
32            method,
33            TokenType::Identifier(_) | TokenType::PartialKeyword(_),
34            TokenType::Identifier("*error*".into(),),
35            errors,
36            "Expected ".to_string() + get_token_type_display(&TokenType::Identifier("".into(),))
37        );
38
39        Some(Self::TableMethod {
40            table: prefix_exp,
41            colon: Pointer::new(colon),
42            method: Pointer::new(method),
43        })
44    }
45}
46impl TryParse for FunctionCallInvoked {}
47
48impl FunctionCall {
49    /// Parse a [`FunctionCall`] with the passed [`FunctionCallInvoked`]. This
50    /// method keeps parsing repeatedly to allow for chained of functions calls:
51    ///
52    /// ```lua
53    /// foo()()()
54    /// ```
55    pub fn try_parse_with_invoked(
56        lexer: &mut Lexer,
57        errors: &mut Vec<ParseError>,
58        mut invoked: FunctionCallInvoked,
59    ) -> Option<Self> {
60        let mut found_arguments = false;
61        while let Some(arguments) = FunctionArguments::try_parse(lexer, errors) {
62            found_arguments = true;
63            invoked = FunctionCallInvoked::Function(Pointer::new(PrefixExp::FunctionCall(Self {
64                invoked,
65                arguments,
66            })));
67        }
68
69        // Avoid infinite recursions.
70        if !found_arguments {
71            return None;
72        }
73
74        if let FunctionCallInvoked::Function(pointer) = invoked {
75            if let PrefixExp::FunctionCall(function_call) = (*pointer).clone() {
76                return Some(function_call);
77            }
78        }
79
80        None
81    }
82}
83
84impl Parse for FunctionCall {
85    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
86        let invoked = FunctionCallInvoked::parse(token, lexer, errors)?;
87        let arguments = FunctionArguments::try_parse(lexer, errors);
88
89        if let Some(arguments) = arguments {
90            return Some(FunctionCall { invoked, arguments });
91        }
92        if let FunctionCallInvoked::Function(pointer) = invoked {
93            if let PrefixExp::FunctionCall(call) = (*pointer).clone() {
94                return Some(call);
95            }
96        }
97
98        None
99    }
100}
101impl TryParse for FunctionCall {
102    fn try_parse(lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
103        Some(Self {
104            invoked: FunctionCallInvoked::try_parse(lexer, errors)?,
105            arguments: FunctionArguments::try_parse(lexer, errors)?,
106        })
107    }
108}
109
110impl Parse<PrefixExp> for FunctionCall {
111    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<PrefixExp> {
112        Self::parse(token, lexer, errors).map(PrefixExp::FunctionCall)
113    }
114}
115impl Parse<TableAccessPrefix> for FunctionCall {
116    fn parse(
117        token: Token,
118        lexer: &mut Lexer,
119        errors: &mut Vec<ParseError>,
120    ) -> Option<TableAccessPrefix> {
121        Pointer::<Self>::parse(token, lexer, errors).map(TableAccessPrefix::FunctionCall)
122    }
123}
124
125impl Parse for FunctionArguments {
126    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
127        if matches!(token.token_type, TokenType::Literal(Literal::String(_))) {
128            return Some(Self::String(token));
129        }
130        if token.token_type == TokenType::Symbol(Symbol::OpeningParenthesis) {
131            return BracketedList::parse_with(
132                token,
133                lexer,
134                errors,
135                ("Expected <expr>", Symbol::ClosingParenthesis),
136            )
137            .map(Self::List);
138        }
139
140        Table::parse(token.clone(), lexer, errors)
141    }
142}
143impl TryParse for FunctionArguments {}
144
145impl Parse for FunctionArgument {
146    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
147        if matches!(token.token_type, TokenType::Symbol(Symbol::Ellipses)) {
148            Some(Self::VariadicValues(token))
149        } else {
150            Expression::parse(token, lexer, errors).map(Self::Expression)
151        }
152    }
153}
154impl TryParse for FunctionArgument {}
155
156impl Parse for Closure {
157    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
158        let attributes;
159        let function_keyword;
160
161        match token.token_type {
162            TokenType::Keyword(Keyword::Function) => {
163                attributes = Vec::new();
164                function_keyword = token;
165            }
166            TokenType::Symbol(Symbol::At) => {
167                attributes = safe_unwrap!(
168                    lexer,
169                    errors,
170                    "Expected <attribute>",
171                    Vec::parse(token, lexer, errors)
172                );
173                function_keyword = lexer.next_token();
174            }
175            _ => return None,
176        }
177
178        parse_function!(
179            let attributes = attributes;
180            function_keyword,
181            lexer,
182            errors,
183            { attributes }
184        )
185    }
186}