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::{Error, Keyword, Lexer, Literal, 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<Error>) -> 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<Error>,
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<Error>) -> 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(Self { 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<Error>) -> 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<Error>) -> 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<Error>,
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<Error>) -> 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, lexer, errors)
141    }
142}
143impl TryParse for FunctionArguments {}
144
145impl Parse for FunctionArgument {
146    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<Error>) -> 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)
151                .map(Pointer::new)
152                .map(Self::Expression)
153        }
154    }
155}
156impl TryParse for FunctionArgument {}
157
158impl Parse for Closure {
159    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<Error>) -> Option<Self> {
160        let attributes;
161        let function_keyword;
162
163        match token.token_type {
164            TokenType::Keyword(Keyword::Function) => {
165                attributes = Vec::new();
166                function_keyword = token;
167            }
168            TokenType::Symbol(Symbol::At) => {
169                attributes = safe_unwrap!(
170                    lexer,
171                    errors,
172                    "Expected <attribute>",
173                    Vec::parse(token, lexer, errors)
174                );
175                function_keyword = lexer.next_token();
176            }
177            _ => return None,
178        }
179
180        parse_function!(
181            let attributes = attributes;
182            function_keyword,
183            lexer,
184            errors,
185            { attributes }
186        )
187    }
188}