luau_parser/impl/value/
table.rs

1//! All `impl` blocks for type-related types:
2//!
3//! * [`TableKey`]
4//! * [`TableField`]
5//! * [`TableFieldValue`]
6//! * [`Table`]
7
8use luau_lexer::prelude::{Lexer, ParseError, Symbol, Token, TokenType};
9use std::cell::Cell;
10
11use crate::{
12    safe_unwrap,
13    types::{
14        Bracketed, BracketedList, Expression, FunctionArguments, GetRange, GetRangeError, Parse,
15        ParseWithArgs, Pointer, Print, Range, Table, TableAccessKey, TableField, TableFieldValue,
16        TableKey, TryParse, TryParseWithArgs, TypeValue,
17    },
18};
19
20/// A simple struct holding arguments needed for parsing tables.
21#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
22struct ParseArgs {
23    /// Whether or not it's currently parsing a type.
24    is_type: bool,
25
26    /// The number of keys it inferred. Only for expressions.
27    inferred_keys: Cell<u32>,
28}
29impl ParseArgs {
30    /// Create new [`ParseArgs`].
31    #[inline]
32    fn new(is_type: bool, inferred_keys: u32) -> Self {
33        Self {
34            is_type,
35            inferred_keys: Cell::new(inferred_keys),
36        }
37    }
38}
39
40impl TableKey {
41    /// Crate a new [`TableKey::UndefinedNumber`] from the passed [`ParseArgs`].
42    #[inline]
43    fn undefined_number(parse_args: &ParseArgs) -> Self {
44        Self::UndefinedNumber(
45            parse_args
46                .inferred_keys
47                .replace(parse_args.inferred_keys.get() + 1),
48        )
49    }
50
51    /// Crate a new [`TableKey::UndefinedString`] from the passed [`ParseArgs`].
52    #[inline]
53    fn undefined_string() -> Self {
54        Self::UndefinedString("number".into())
55    }
56}
57
58impl ParseWithArgs<bool> for TableKey {
59    fn parse_with(
60        token: Token,
61        lexer: &mut Lexer,
62        errors: &mut Vec<ParseError>,
63        is_type: bool,
64    ) -> Option<Self> {
65        match token.token_type {
66            TokenType::Identifier(_) | TokenType::PartialKeyword(_) => Some(Self::Simple(token)),
67            TokenType::Symbol(Symbol::OpeningBrackets) => {
68                if is_type {
69                    Bracketed::<_>::parse_with(
70                        token,
71                        lexer,
72                        errors,
73                        ("Expected <type>", Symbol::ClosingBrackets),
74                    )
75                    .map(Self::Type)
76                } else {
77                    Bracketed::<_>::parse_with(
78                        token,
79                        lexer,
80                        errors,
81                        ("Expected <expr>", Symbol::ClosingBrackets),
82                    )
83                    .map(Self::Expression)
84                }
85            }
86            _ => None,
87        }
88    }
89}
90
91impl ParseWithArgs<&ParseArgs> for TableField {
92    fn parse_with(
93        token: Token,
94        lexer: &mut Lexer,
95        errors: &mut Vec<ParseError>,
96        parse_args: &ParseArgs,
97    ) -> Option<Self> {
98        if token == TokenType::Symbol(Symbol::ClosingCurlyBrackets) {
99            // Sometimes causes issues when the last item in the table is trailing
100            // this just ensures it never happens.
101            return None;
102        }
103
104        let state = lexer.save_state();
105
106        let (key, equal_or_colon) = if let Some(key) =
107            TableKey::parse_with(token.clone(), lexer, errors, parse_args.is_type)
108        {
109            let equal_or_colon = if parse_args.is_type {
110                maybe_next_token!(lexer, temp, TokenType::Symbol(Symbol::Colon));
111
112                temp
113            } else {
114                maybe_next_token!(lexer, temp, TokenType::Symbol(Symbol::Equal));
115
116                temp
117            };
118
119            (Some(Pointer::new(key)), equal_or_colon)
120        } else {
121            (None, None)
122        };
123
124        if key.is_none() || equal_or_colon.is_none() {
125            lexer.set_state(state);
126
127            return Some(Self {
128                key: if parse_args.is_type {
129                    Pointer::new(TableKey::undefined_string())
130                } else {
131                    Pointer::new(TableKey::undefined_number(parse_args))
132                },
133                equal_or_colon: None,
134                value: safe_unwrap!(
135                    lexer,
136                    errors,
137                    "Expected <type>",
138                    TableFieldValue::parse_with(token.clone(), lexer, errors, parse_args.is_type)
139                        .map(Pointer::new)
140                ),
141            });
142        }
143
144        let key = key.unwrap();
145
146        let value = Pointer::new(TableFieldValue::try_parse_with(
147            lexer,
148            errors,
149            parse_args.is_type,
150        )?);
151
152        Some(Self {
153            key,
154            equal_or_colon,
155            value,
156        })
157    }
158}
159
160impl ParseWithArgs<bool> for TableFieldValue {
161    #[inline]
162    fn parse_with(
163        token: Token,
164        lexer: &mut Lexer,
165        errors: &mut Vec<ParseError>,
166        is_type: bool,
167    ) -> Option<Self> {
168        if is_type {
169            TypeValue::parse(token, lexer, errors).map(Self::Type)
170        } else if token == TokenType::Symbol(Symbol::Ellipses) {
171            Some(Self::VariadicValues(token))
172        } else {
173            Expression::parse(token, lexer, errors).map(Self::Expression)
174        }
175    }
176}
177
178impl ParseWithArgs<bool> for Table {
179    fn parse_with(
180        token: Token,
181        lexer: &mut Lexer,
182        errors: &mut Vec<ParseError>,
183        is_type: bool,
184    ) -> Option<Self> {
185        if !matches!(
186            token.token_type,
187            TokenType::Symbol(Symbol::OpeningCurlyBrackets)
188        ) {
189            return None;
190        }
191
192        BracketedList::<TableField>::parse_with(
193            token,
194            lexer,
195            errors,
196            (
197                "Expected <table-field>",
198                Symbol::ClosingCurlyBrackets,
199                &ParseArgs::new(is_type, 1),
200            ),
201        )
202        .map(Self)
203    }
204}
205
206impl Parse<FunctionArguments> for Table {
207    #[inline]
208    fn parse(
209        token: Token,
210        lexer: &mut Lexer,
211        errors: &mut Vec<ParseError>,
212    ) -> Option<FunctionArguments> {
213        Self::parse_with(token, lexer, errors, false).map(FunctionArguments::Table)
214    }
215}
216impl TryParse<FunctionArguments> for Table {}
217
218impl Parse<TableAccessKey> for TableKey {
219    #[inline]
220    fn parse(
221        token: Token,
222        lexer: &mut Lexer,
223        errors: &mut Vec<ParseError>,
224    ) -> Option<TableAccessKey> {
225        Self::parse_with(token, lexer, errors, false)
226            .map(Pointer::new)
227            .map(TableAccessKey::Expression)
228    }
229}
230impl TryParse<TableAccessKey> for TableKey {}
231
232impl GetRange for TableKey {
233    #[inline]
234    fn get_range(&self) -> Result<Range, GetRangeError> {
235        match self {
236            TableKey::ERROR => Err(GetRangeError::ErrorVariant),
237            TableKey::UndefinedNumber(_) | TableKey::UndefinedString(_) => {
238                Err(GetRangeError::UndefinedKey)
239            }
240            TableKey::Simple(token) => token.get_range(),
241            TableKey::Expression(bracketed) => bracketed.get_range(),
242            TableKey::Type(bracketed) => bracketed.get_range(),
243        }
244    }
245}
246
247impl GetRange for TableField {
248    #[inline]
249    fn get_range(&self) -> Result<Range, GetRangeError> {
250        let value_range = self.value.get_range();
251
252        if let Ok(key_range) = self.key.get_range() {
253            Ok(Range::new(key_range.start, value_range?.end))
254        } else {
255            value_range
256        }
257    }
258}
259
260impl Print for TableKey {
261    fn print(&self) -> String {
262        match self {
263            Self::Simple(item) => item.print(),
264            Self::Expression(item) => item.print(),
265            Self::Type(item) => item.print(),
266            _ => "".to_string(),
267        }
268    }
269}
270
271impl Print for TableField {
272    fn print(&self) -> String {
273        self.key.print().trim_end().to_string()
274            + self.equal_or_colon.print().trim_end()
275            + &self.value.print()
276    }
277}