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#[derive(Clone, Debug, PartialEq, Eq)]
9pub struct TableFieldEntry {
10    field: Identifier,
11    value: Expression,
12    /// The token for the `=` operator symbol.
13    token: Option<Token>,
14}
15
16impl TableFieldEntry {
17    pub fn new<I: Into<Identifier>, E: Into<Expression>>(field: I, value: E) -> Self {
18        Self {
19            field: field.into(),
20            value: value.into(),
21            token: None,
22        }
23    }
24
25    pub fn with_token(mut self, token: Token) -> Self {
26        self.token = Some(token);
27        self
28    }
29
30    #[inline]
31    pub fn set_token(&mut self, token: Token) {
32        self.token = Some(token);
33    }
34
35    #[inline]
36    pub fn get_token(&self) -> Option<&Token> {
37        self.token.as_ref()
38    }
39
40    #[inline]
41    pub fn get_field(&self) -> &Identifier {
42        &self.field
43    }
44
45    #[inline]
46    pub fn mutate_field(&mut self) -> &mut Identifier {
47        &mut self.field
48    }
49
50    #[inline]
51    pub fn get_value(&self) -> &Expression {
52        &self.value
53    }
54
55    #[inline]
56    pub fn mutate_value(&mut self) -> &mut Expression {
57        &mut self.value
58    }
59
60    super::impl_token_fns!(
61        target = [field]
62        iter = [token]
63    );
64}
65
66#[derive(Clone, Debug, PartialEq, Eq)]
67pub struct TableIndexEntryTokens {
68    pub opening_bracket: Token,
69    pub closing_bracket: Token,
70    pub equal: Token,
71}
72
73impl TableIndexEntryTokens {
74    super::impl_token_fns!(target = [opening_bracket, closing_bracket, equal]);
75}
76
77#[derive(Clone, Debug, PartialEq, Eq)]
78pub struct TableIndexEntry {
79    key: Expression,
80    value: Expression,
81    tokens: Option<Box<TableIndexEntryTokens>>,
82}
83
84impl TableIndexEntry {
85    pub fn new<T: Into<Expression>, U: Into<Expression>>(key: T, value: U) -> Self {
86        Self {
87            key: key.into(),
88            value: value.into(),
89            tokens: None,
90        }
91    }
92
93    pub fn with_tokens(mut self, tokens: TableIndexEntryTokens) -> Self {
94        self.tokens = Some(tokens.into());
95        self
96    }
97
98    #[inline]
99    pub fn set_tokens(&mut self, tokens: TableIndexEntryTokens) {
100        self.tokens = Some(tokens.into());
101    }
102
103    #[inline]
104    pub fn get_tokens(&self) -> Option<&TableIndexEntryTokens> {
105        self.tokens.as_ref().map(|tokens| tokens.as_ref())
106    }
107
108    #[inline]
109    pub fn get_key(&self) -> &Expression {
110        &self.key
111    }
112
113    #[inline]
114    pub fn mutate_key(&mut self) -> &mut Expression {
115        &mut self.key
116    }
117
118    #[inline]
119    pub fn get_value(&self) -> &Expression {
120        &self.value
121    }
122
123    #[inline]
124    pub fn mutate_value(&mut self) -> &mut Expression {
125        &mut self.value
126    }
127
128    super::impl_token_fns!(iter = [tokens]);
129}
130
131#[derive(Clone, Debug, PartialEq, Eq)]
132pub enum TableEntry {
133    Field(TableFieldEntry),
134    Index(TableIndexEntry),
135    Value(Expression),
136}
137
138impl TableEntry {
139    /// Creates a field entry if the provided key is a valid identifier, otherwise it
140    /// creates an index entry.
141    pub fn from_string_key_and_value(key: impl Into<String>, value: impl Into<Expression>) -> Self {
142        let key = key.into();
143        let value = value.into();
144        if is_valid_identifier(&key) {
145            Self::Field(TableFieldEntry {
146                field: Identifier::new(key),
147                value,
148                token: None,
149            })
150        } else {
151            Self::Index(TableIndexEntry {
152                key: Expression::String(StringExpression::from_value(key)),
153                value,
154                tokens: None,
155            })
156        }
157    }
158
159    pub fn clear_comments(&mut self) {
160        match self {
161            TableEntry::Field(entry) => entry.clear_comments(),
162            TableEntry::Index(entry) => entry.clear_comments(),
163            TableEntry::Value(_) => {}
164        }
165    }
166
167    pub fn clear_whitespaces(&mut self) {
168        match self {
169            TableEntry::Field(entry) => entry.clear_whitespaces(),
170            TableEntry::Index(entry) => entry.clear_whitespaces(),
171            TableEntry::Value(_) => {}
172        }
173    }
174
175    pub(crate) fn replace_referenced_tokens(&mut self, code: &str) {
176        match self {
177            TableEntry::Field(entry) => entry.replace_referenced_tokens(code),
178            TableEntry::Index(entry) => entry.replace_referenced_tokens(code),
179            TableEntry::Value(_) => {}
180        }
181    }
182
183    pub(crate) fn shift_token_line(&mut self, amount: usize) {
184        match self {
185            TableEntry::Field(entry) => entry.shift_token_line(amount),
186            TableEntry::Index(entry) => entry.shift_token_line(amount),
187            TableEntry::Value(_) => {}
188        }
189    }
190
191    pub(crate) fn filter_comments(&mut self, filter: impl Fn(&Trivia) -> bool) {
192        match self {
193            TableEntry::Field(entry) => entry.filter_comments(filter),
194            TableEntry::Index(entry) => entry.filter_comments(filter),
195            TableEntry::Value(_) => {}
196        }
197    }
198}
199
200impl From<TableFieldEntry> for TableEntry {
201    fn from(entry: TableFieldEntry) -> Self {
202        Self::Field(entry)
203    }
204}
205
206impl From<TableIndexEntry> for TableEntry {
207    fn from(entry: TableIndexEntry) -> Self {
208        Self::Index(entry)
209    }
210}
211
212#[derive(Clone, Debug, PartialEq, Eq)]
213pub struct TableTokens {
214    pub opening_brace: Token,
215    pub closing_brace: Token,
216    pub separators: Vec<Token>,
217}
218
219impl TableTokens {
220    super::impl_token_fns!(
221        target = [opening_brace, closing_brace]
222        iter = [separators]
223    );
224}
225
226#[derive(Clone, Debug, PartialEq, Eq)]
227pub struct TableExpression {
228    entries: Vec<TableEntry>,
229    tokens: Option<TableTokens>,
230}
231
232impl TableExpression {
233    pub fn new(entries: Vec<TableEntry>) -> Self {
234        Self {
235            entries,
236            tokens: None,
237        }
238    }
239
240    pub fn with_tokens(mut self, tokens: TableTokens) -> Self {
241        self.tokens = Some(tokens);
242        self
243    }
244
245    #[inline]
246    pub fn set_tokens(&mut self, tokens: TableTokens) {
247        self.tokens = Some(tokens);
248    }
249
250    #[inline]
251    pub fn get_tokens(&self) -> Option<&TableTokens> {
252        self.tokens.as_ref()
253    }
254
255    #[inline]
256    pub fn get_entries(&self) -> &Vec<TableEntry> {
257        &self.entries
258    }
259
260    #[inline]
261    pub fn iter_entries(&self) -> impl Iterator<Item = &TableEntry> {
262        self.entries.iter()
263    }
264
265    #[inline]
266    pub fn iter_mut_entries(&mut self) -> impl Iterator<Item = &mut TableEntry> {
267        self.entries.iter_mut()
268    }
269
270    #[inline]
271    pub fn len(&self) -> usize {
272        self.entries.len()
273    }
274
275    #[inline]
276    pub fn is_empty(&self) -> bool {
277        self.entries.is_empty()
278    }
279
280    #[inline]
281    pub fn mutate_entries(&mut self) -> &mut Vec<TableEntry> {
282        &mut self.entries
283    }
284
285    pub fn append_entry<T: Into<TableEntry>>(mut self, entry: T) -> Self {
286        self.entries.push(entry.into());
287        self
288    }
289
290    pub fn append_field<S: Into<Identifier>, E: Into<Expression>>(
291        mut self,
292        key: S,
293        value: E,
294    ) -> Self {
295        self.entries.push(TableFieldEntry::new(key, value).into());
296        self
297    }
298
299    pub fn append_index<T: Into<Expression>, U: Into<Expression>>(
300        mut self,
301        key: T,
302        value: U,
303    ) -> Self {
304        self.entries
305            .push(TableIndexEntry::new(key.into(), value.into()).into());
306        self
307    }
308
309    pub fn append_array_value<E: Into<Expression>>(mut self, value: E) -> Self {
310        self.entries.push(TableEntry::Value(value.into()));
311        self
312    }
313
314    super::impl_token_fns!(iter = [tokens, entries]);
315}
316
317impl Default for TableExpression {
318    fn default() -> Self {
319        Self::new(Vec::new())
320    }
321}