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        while let Some(arguments) = FunctionArguments::try_parse(lexer, errors) {
61            invoked = FunctionCallInvoked::Function(Pointer::new(PrefixExp::FunctionCall(Self {
62                invoked,
63                arguments,
64            })));
65        }
66
67        if let FunctionCallInvoked::Function(pointer) = invoked {
68            if let PrefixExp::FunctionCall(function_call) = (*pointer).clone() {
69                return Some(function_call);
70            }
71        }
72
73        None
74    }
75}
76
77impl Parse for FunctionCall {
78    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
79        let invoked = FunctionCallInvoked::parse(token, lexer, errors)?;
80        let arguments = FunctionArguments::try_parse(lexer, errors);
81
82        if let Some(arguments) = arguments {
83            return Some(FunctionCall { invoked, arguments });
84        }
85        if let FunctionCallInvoked::Function(pointer) = invoked {
86            if let PrefixExp::FunctionCall(call) = (*pointer).clone() {
87                return Some(call);
88            }
89        }
90
91        None
92    }
93}
94impl TryParse for FunctionCall {
95    fn try_parse(lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
96        Some(Self {
97            invoked: FunctionCallInvoked::try_parse(lexer, errors)?,
98            arguments: FunctionArguments::try_parse(lexer, errors)?,
99        })
100    }
101}
102
103impl Parse<PrefixExp> for FunctionCall {
104    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<PrefixExp> {
105        Self::parse(token, lexer, errors).map(PrefixExp::FunctionCall)
106    }
107}
108impl Parse<TableAccessPrefix> for FunctionCall {
109    fn parse(
110        token: Token,
111        lexer: &mut Lexer,
112        errors: &mut Vec<ParseError>,
113    ) -> Option<TableAccessPrefix> {
114        Pointer::<Self>::parse(token, lexer, errors).map(TableAccessPrefix::FunctionCall)
115    }
116}
117
118impl Parse for FunctionArguments {
119    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
120        if matches!(token.token_type, TokenType::Literal(Literal::String(_))) {
121            return Some(Self::String(token));
122        }
123        if token.token_type == TokenType::Symbol(Symbol::OpeningParenthesis) {
124            return BracketedList::parse_with(
125                token,
126                lexer,
127                errors,
128                ("Expected <expr>", Symbol::ClosingParenthesis),
129            )
130            .map(Self::List);
131        }
132
133        Table::parse(token.clone(), lexer, errors)
134    }
135}
136impl TryParse for FunctionArguments {}
137
138impl Parse for FunctionArgument {
139    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
140        if matches!(token.token_type, TokenType::Symbol(Symbol::Ellipses)) {
141            Some(Self::VariadicValues(token))
142        } else {
143            Expression::parse(token, lexer, errors).map(Self::Expression)
144        }
145    }
146}
147impl TryParse for FunctionArgument {}
148
149impl Parse for Closure {
150    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<Self> {
151        let attributes;
152        let function_keyword;
153
154        match token.token_type {
155            TokenType::Keyword(Keyword::Function) => {
156                attributes = Vec::new();
157                function_keyword = token;
158            }
159            TokenType::Symbol(Symbol::At) => {
160                attributes = safe_unwrap!(
161                    lexer,
162                    errors,
163                    "Expected <attribute>",
164                    Vec::parse(token, lexer, errors)
165                );
166                function_keyword = lexer.next_token();
167            }
168            _ => return None,
169        }
170
171        parse_function!(
172            let attributes = attributes;
173            function_keyword,
174            lexer,
175            errors,
176            { attributes }
177        )
178    }
179}