darklua_core/nodes/expressions/
table.rs

1use crate::{
2    nodes::{Expression, Identifier, Token, Trivia},
3    process::utils::is_valid_identifier,
4};
5
6use super::StringExpression;
7
8/// Represents a field entry in a table literal where the key is an identifier.
9///
10/// This corresponds to the form: `{ field = value }`
11#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct TableFieldEntry {
13    field: Identifier,
14    value: Expression,
15    token: Option<Token>,
16}
17
18impl TableFieldEntry {
19    /// Creates a new table field entry with the given field name and value.
20    pub fn new<I: Into<Identifier>, E: Into<Expression>>(field: I, value: E) -> Self {
21        Self {
22            field: field.into(),
23            value: value.into(),
24            token: None,
25        }
26    }
27
28    /// Attaches a token to this field entry.
29    pub fn with_token(mut self, token: Token) -> Self {
30        self.token = Some(token);
31        self
32    }
33
34    /// Sets the token for this field entry.
35    #[inline]
36    pub fn set_token(&mut self, token: Token) {
37        self.token = Some(token);
38    }
39
40    /// Returns the token associated with this field entry, if any.
41    #[inline]
42    pub fn get_token(&self) -> Option<&Token> {
43        self.token.as_ref()
44    }
45
46    /// Returns the field name.
47    #[inline]
48    pub fn get_field(&self) -> &Identifier {
49        &self.field
50    }
51
52    /// Returns a mutable reference to the field name.
53    #[inline]
54    pub fn mutate_field(&mut self) -> &mut Identifier {
55        &mut self.field
56    }
57
58    /// Returns the field value.
59    #[inline]
60    pub fn get_value(&self) -> &Expression {
61        &self.value
62    }
63
64    /// Returns a mutable reference to the field value.
65    #[inline]
66    pub fn mutate_value(&mut self) -> &mut Expression {
67        &mut self.value
68    }
69
70    super::impl_token_fns!(
71        target = [field]
72        iter = [token]
73    );
74}
75
76/// Contains tokens for a table index entry.
77#[derive(Clone, Debug, PartialEq, Eq)]
78pub struct TableIndexEntryTokens {
79    /// Token for the opening bracket `[`
80    pub opening_bracket: Token,
81    /// Token for the closing bracket `]`
82    pub closing_bracket: Token,
83    /// Token for the equals sign `=`
84    pub equal: Token,
85}
86
87impl TableIndexEntryTokens {
88    super::impl_token_fns!(target = [opening_bracket, closing_bracket, equal]);
89}
90
91/// Represents an index entry in a table literal where the key is a computed expression.
92#[derive(Clone, Debug, PartialEq, Eq)]
93pub struct TableIndexEntry {
94    key: Expression,
95    value: Expression,
96    tokens: Option<Box<TableIndexEntryTokens>>,
97}
98
99impl TableIndexEntry {
100    /// Creates a new table index entry with the given key and value.
101    pub fn new<T: Into<Expression>, U: Into<Expression>>(key: T, value: U) -> Self {
102        Self {
103            key: key.into(),
104            value: value.into(),
105            tokens: None,
106        }
107    }
108
109    /// Attaches tokens to this index entry and returns the modified entry.
110    pub fn with_tokens(mut self, tokens: TableIndexEntryTokens) -> Self {
111        self.tokens = Some(tokens.into());
112        self
113    }
114
115    /// Sets the tokens for this index entry.
116    #[inline]
117    pub fn set_tokens(&mut self, tokens: TableIndexEntryTokens) {
118        self.tokens = Some(tokens.into());
119    }
120
121    /// Returns the tokens associated with this index entry, if any.
122    #[inline]
123    pub fn get_tokens(&self) -> Option<&TableIndexEntryTokens> {
124        self.tokens.as_ref().map(|tokens| tokens.as_ref())
125    }
126
127    /// Returns the key expression.
128    #[inline]
129    pub fn get_key(&self) -> &Expression {
130        &self.key
131    }
132
133    /// Returns a mutable reference to the key expression.
134    #[inline]
135    pub fn mutate_key(&mut self) -> &mut Expression {
136        &mut self.key
137    }
138
139    /// Returns the value expression.
140    #[inline]
141    pub fn get_value(&self) -> &Expression {
142        &self.value
143    }
144
145    /// Returns a mutable reference to the value expression.
146    #[inline]
147    pub fn mutate_value(&mut self) -> &mut Expression {
148        &mut self.value
149    }
150
151    super::impl_token_fns!(iter = [tokens]);
152}
153
154/// Represents a single entry in a table literal.
155#[derive(Clone, Debug, PartialEq, Eq)]
156pub enum TableEntry {
157    /// A named field entry (e.g., `{ field = value }`)
158    Field(Box<TableFieldEntry>),
159    /// A computed index entry (e.g., `{ [expr] = value }`)
160    Index(Box<TableIndexEntry>),
161    /// A value entry for array-like tables (e.g., `{ value }`)
162    Value(Box<Expression>),
163}
164
165impl TableEntry {
166    /// Creates an array-like table entry from a value.
167    pub fn from_value(value: impl Into<Expression>) -> Self {
168        Self::Value(Box::new(value.into()))
169    }
170
171    /// Creates a table entry from a string key and value.
172    ///
173    /// If the key is a valid Lua identifier, a `Field` entry is created.
174    /// Otherwise, an `Index` entry with a string key is created.
175    pub fn from_string_key_and_value(key: impl Into<String>, value: impl Into<Expression>) -> Self {
176        let key = key.into();
177        let value = value.into();
178        if is_valid_identifier(&key) {
179            Self::Field(Box::new(TableFieldEntry {
180                field: Identifier::new(key),
181                value,
182                token: None,
183            }))
184        } else {
185            Self::Index(Box::new(TableIndexEntry {
186                key: Expression::String(StringExpression::from_value(key)),
187                value,
188                tokens: None,
189            }))
190        }
191    }
192
193    /// Clears all comments from the tokens in this node.
194    pub fn clear_comments(&mut self) {
195        match self {
196            TableEntry::Field(entry) => entry.clear_comments(),
197            TableEntry::Index(entry) => entry.clear_comments(),
198            TableEntry::Value(_) => {}
199        }
200    }
201
202    /// Clears all whitespaces information from the tokens in this node.
203    pub fn clear_whitespaces(&mut self) {
204        match self {
205            TableEntry::Field(entry) => entry.clear_whitespaces(),
206            TableEntry::Index(entry) => entry.clear_whitespaces(),
207            TableEntry::Value(_) => {}
208        }
209    }
210
211    pub(crate) fn replace_referenced_tokens(&mut self, code: &str) {
212        match self {
213            TableEntry::Field(entry) => entry.replace_referenced_tokens(code),
214            TableEntry::Index(entry) => entry.replace_referenced_tokens(code),
215            TableEntry::Value(_) => {}
216        }
217    }
218
219    pub(crate) fn shift_token_line(&mut self, amount: isize) {
220        match self {
221            TableEntry::Field(entry) => entry.shift_token_line(amount),
222            TableEntry::Index(entry) => entry.shift_token_line(amount),
223            TableEntry::Value(_) => {}
224        }
225    }
226
227    pub(crate) fn filter_comments(&mut self, filter: impl Fn(&Trivia) -> bool) {
228        match self {
229            TableEntry::Field(entry) => entry.filter_comments(filter),
230            TableEntry::Index(entry) => entry.filter_comments(filter),
231            TableEntry::Value(_) => {}
232        }
233    }
234}
235
236impl From<TableFieldEntry> for TableEntry {
237    fn from(entry: TableFieldEntry) -> Self {
238        Self::Field(Box::new(entry))
239    }
240}
241
242impl From<TableIndexEntry> for TableEntry {
243    fn from(entry: TableIndexEntry) -> Self {
244        Self::Index(Box::new(entry))
245    }
246}
247
248/// Contains tokens for a table expression.
249#[derive(Clone, Debug, PartialEq, Eq)]
250pub struct TableTokens {
251    /// Token for the opening brace `{`
252    pub opening_brace: Token,
253    /// Token for the closing brace `}`
254    pub closing_brace: Token,
255    /// Tokens for the separators between entries (commas and/or semicolons)
256    pub separators: Vec<Token>,
257}
258
259impl TableTokens {
260    super::impl_token_fns!(
261        target = [opening_brace, closing_brace]
262        iter = [separators]
263    );
264}
265
266/// Represents a table expression.
267#[derive(Clone, Debug, PartialEq, Eq)]
268pub struct TableExpression {
269    entries: Vec<TableEntry>,
270    tokens: Option<TableTokens>,
271}
272
273impl TableExpression {
274    /// Creates a new table expression with the given entries.
275    pub fn new(entries: Vec<TableEntry>) -> Self {
276        Self {
277            entries,
278            tokens: None,
279        }
280    }
281
282    /// Attaches tokens to this table expression.
283    pub fn with_tokens(mut self, tokens: TableTokens) -> Self {
284        self.tokens = Some(tokens);
285        self
286    }
287
288    /// Sets the tokens for this table expression.
289    #[inline]
290    pub fn set_tokens(&mut self, tokens: TableTokens) {
291        self.tokens = Some(tokens);
292    }
293
294    /// Returns the tokens associated with this table expression, if any.
295    #[inline]
296    pub fn get_tokens(&self) -> Option<&TableTokens> {
297        self.tokens.as_ref()
298    }
299
300    /// Returns the entries in this table expression.
301    #[inline]
302    pub fn get_entries(&self) -> &Vec<TableEntry> {
303        &self.entries
304    }
305
306    /// Returns an iterator over the entries in this table expression.
307    #[inline]
308    pub fn iter_entries(&self) -> impl Iterator<Item = &TableEntry> {
309        self.entries.iter()
310    }
311
312    /// Returns a mutable iterator over the entries in this table expression.
313    #[inline]
314    pub fn iter_mut_entries(&mut self) -> impl Iterator<Item = &mut TableEntry> {
315        self.entries.iter_mut()
316    }
317
318    /// Returns the number of entries in this table expression.
319    #[inline]
320    pub fn len(&self) -> usize {
321        self.entries.len()
322    }
323
324    /// Returns whether this table expression is empty.
325    #[inline]
326    pub fn is_empty(&self) -> bool {
327        self.entries.is_empty()
328    }
329
330    /// Returns a mutable reference to the entries in this table expression.
331    #[inline]
332    pub fn mutate_entries(&mut self) -> &mut Vec<TableEntry> {
333        &mut self.entries
334    }
335
336    /// Appends a new entry to this table expression.
337    pub fn append_entry<T: Into<TableEntry>>(mut self, entry: T) -> Self {
338        self.entries.push(entry.into());
339        self
340    }
341
342    /// Appends a new field entry to this table expression.
343    pub fn append_field<S: Into<Identifier>, E: Into<Expression>>(
344        mut self,
345        key: S,
346        value: E,
347    ) -> Self {
348        self.entries.push(TableFieldEntry::new(key, value).into());
349        self
350    }
351
352    /// Appends a new index entry to this table expression.
353    pub fn append_index<T: Into<Expression>, U: Into<Expression>>(
354        mut self,
355        key: T,
356        value: U,
357    ) -> Self {
358        self.entries
359            .push(TableIndexEntry::new(key.into(), value.into()).into());
360        self
361    }
362
363    /// Appends a new value entry to this table expression.
364    pub fn append_array_value<E: Into<Expression>>(mut self, value: E) -> Self {
365        self.entries.push(TableEntry::from_value(value));
366        self
367    }
368
369    /// Returns a mutable reference to the first token for this table expression,
370    /// creating it if missing.
371    pub fn mutate_first_token(&mut self) -> &mut Token {
372        self.set_default_tokens();
373        &mut self.tokens.as_mut().unwrap().opening_brace
374    }
375
376    /// Returns a mutable reference to the last token of this table expression,
377    /// creating it if missing.
378    pub fn mutate_last_token(&mut self) -> &mut Token {
379        self.set_default_tokens();
380        &mut self.tokens.as_mut().unwrap().closing_brace
381    }
382
383    fn set_default_tokens(&mut self) {
384        if self.tokens.is_none() {
385            self.set_tokens(TableTokens {
386                opening_brace: Token::from_content("{"),
387                closing_brace: Token::from_content("}"),
388                separators: Vec::new(),
389            });
390        }
391    }
392
393    super::impl_token_fns!(iter = [tokens, entries]);
394}
395
396impl Default for TableExpression {
397    fn default() -> Self {
398        Self::new(Vec::new())
399    }
400}