Skip to main content

rbx_rsml/parser/
mod.rs

1use crate::{macros::{MacroGroup, MacroTokenIterator}, string_clip::StringClip};
2use crate::lexer::Token;
3use guarded::guarded_unwrap;
4use indexmap::IndexSet;
5use num_traits::Num;
6use palette::Srgb;
7use tree_node_group::{AnyTreeNode, AnyTreeNodeMut, TreeNodeType};
8use std::{fmt::Debug, ops::Deref, str::FromStr, sync::LazyLock};
9use phf_macros::phf_map;
10use rbx_types::{Color3uint8, Content, EnumItem, UDim, Variant};
11use regex::Regex;
12
13mod tree_node_group;
14pub use tree_node_group::{TreeNodeGroup, TreeNode};
15
16mod tuple;
17use tuple::Tuple;
18
19mod selector;
20use selector::Selector;
21
22mod datatype_group;
23use datatype_group::DatatypeGroup;
24pub use datatype_group::Datatype;
25
26mod variants;
27pub use variants::EnumItemFromNameAndValueName;
28
29mod operator;
30use operator::Operator;
31
32mod colors {
33    include!(concat!(env!("OUT_DIR"), "/colors.rs"));
34}
35use colors::{TAILWIND_COLORS, BRICK_COLORS, CSS_COLORS, SKIN_COLORS};
36
37const MULTI_LINE_STRING_STRIP_LEFT_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^[ \t\f]*\n+").unwrap());
38
39type TokenWithResult<'a, R> = (Option<Token>, R);
40
41fn parse_number_string<D>(num_str: &str) -> Result<D, <D as FromStr>::Err>
42where
43    D: Num + FromStr,
44    <D as FromStr>::Err: Debug 
45{   
46    let mut num_str = num_str.to_string();
47    num_str.retain(|c| !r#"_"#.contains(c));
48    num_str.parse::<D>()
49}
50
51struct Parser<'a> {
52    lexer: &'a mut logos::Lexer<'a, Token>,
53
54    /// The names of the macros that the parser is currently inside of.
55    /// Used to prevent infinite recursion.
56    current_macros: IndexSet<(String, usize)>,
57
58    macros: &'a MacroGroup,
59    injected_macro_tokens: Vec<MacroTokenIterator<'a>>,
60
61    tree_nodes: TreeNodeGroup,
62    current_tree_node_idx: TreeNodeType,
63
64    tuples: Vec<Tuple>,
65
66    did_advance: bool,
67}
68
69impl<'a> Parser<'a> {
70    fn new(lexer: &'a mut logos::Lexer<'a, Token>, macros: &'a MacroGroup) -> Self {
71        Self {
72            lexer,
73
74            current_macros: IndexSet::new(),
75            macros,
76
77            injected_macro_tokens: vec![],
78
79            tree_nodes: TreeNodeGroup::new(),
80            current_tree_node_idx: TreeNodeType::Root,
81
82            tuples: vec![],
83
84            did_advance: false,
85        }
86    }
87
88    fn inject_tokens(&mut self, injected_macro_tokens: MacroTokenIterator<'a>) {
89        self.injected_macro_tokens.push(injected_macro_tokens);
90    }
91
92    fn core_next(&mut self) -> Option<Result<Token, ()>> {
93        if let Some(last_injected_macro_tokens) = self.injected_macro_tokens.last_mut() {
94            let next_injected = last_injected_macro_tokens.next();
95
96            if next_injected.is_some() {
97                next_injected
98
99            } else {
100                self.injected_macro_tokens.pop();
101                self.current_macros.pop();
102                self.core_next()
103            }
104
105        } else {
106            self.lexer.next()
107        }
108    }
109
110    fn slice(&self) -> &'a str {
111        if let Some(injected_macro_tokens) = self.injected_macro_tokens.last() {
112            injected_macro_tokens.slice()
113        } else {
114            self.lexer.slice()
115        }
116    }
117
118    // The `advance` method performs work which would be redundant for:
119    // `parse_comment_multi`, `parse_comment_single`, `parse_string_multi_end`.
120    // So this core method serves to strip all of it away.
121    fn core_advance(&mut self) -> Option<Token> {
122        self.did_advance = true;
123
124        loop {
125            match self.core_next() {
126                Some(Ok(token)) => break Some(token),
127                None => return None,
128                _ => ()
129            }
130        }
131    }
132
133    fn advance(self: &mut Parser<'a>) -> Option<Token> {
134        let token = guarded_unwrap!(self.core_advance(), return None);
135
136        let token = parse_comment_multi(self, token).unwrap_or(token);
137
138        let token = parse_comment_single(self, token).unwrap_or(token);
139
140        parse_macro_call(self, token)
141    }
142
143    // create remove tuple for when a tuple is coerced into a datatype and thusly
144    // never used again.
145    fn push_tuple(self: &mut Parser<'a>, tuple: Tuple) -> usize {
146        let tuples = &mut self.tuples;
147
148        let new_tuple_idx = tuples.len();
149        tuples.push(tuple);
150
151        new_tuple_idx
152    }
153
154    fn get_tuple(self: &mut Parser<'a>, tuple_idx: usize) -> Option<&Tuple> {
155        self.tuples.get(tuple_idx)
156    }
157
158    fn get_tuple_mut<'b>(self: &'b mut Parser<'a>, tuple_idx: usize) -> Option<&'b mut Tuple> {
159        self.tuples.get_mut(tuple_idx)
160    }
161}
162
163fn parse_macro_call<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
164    if !matches!(token, Token::MacroCall) { return Some(token) }
165
166    let macro_name_with_suffix = parser.slice();
167    let macro_name: String = macro_name_with_suffix.chars().take(macro_name_with_suffix.chars().count() - 1).collect();
168
169    let next_token = parser.advance();
170    if !matches!(next_token, Some(Token::ParensOpen)) { return next_token }
171
172    let mut scope_nestedness = 0usize;
173    let mut parens_nestedness = 0usize;
174    let mut parens_nestedness_is_zero = true;
175
176    let mut args_tokens: Vec<Vec<(Token, &'a str)>> = vec![];
177    let mut current_args_tokens: Vec<(Token, &'a str)> = vec![];
178    
179    let mut next_token = parser.advance()?;
180    loop {
181        match next_token {
182            Token::ScopeOpen => scope_nestedness += 1,
183            Token::ScopeClose => scope_nestedness -= 1,
184
185            Token::ParensOpen => {
186                parens_nestedness += 1;
187                parens_nestedness_is_zero = false;
188            },
189            Token::ParensClose => {
190                if parens_nestedness_is_zero {
191                    if current_args_tokens.len() != 0 {
192                        args_tokens.push(current_args_tokens);
193                    }
194                    break
195
196                } else {
197                    parens_nestedness -= 1;
198                    parens_nestedness_is_zero = parens_nestedness == 0;
199                }
200            }
201
202            Token::Comma => {
203                if scope_nestedness == 0 && parens_nestedness_is_zero && current_args_tokens.len() != 0 {
204                    args_tokens.push(current_args_tokens);
205                    current_args_tokens = vec![];
206
207                    next_token = parser.advance()?;
208                    continue;
209                }
210            }
211
212            _ => ()
213        }
214        
215        current_args_tokens.push((next_token, parser.slice()));
216        next_token = parser.advance()?;
217    }
218
219    let args_len = args_tokens.len();
220
221    let macro_data = guarded_unwrap!(parser.macros.get(&macro_name, args_len), return parser.advance());
222
223    let current_macro = (macro_name, args_len);
224
225    // Prevents infinite recursion.
226    if parser.current_macros.contains(&current_macro) {
227        return parser.advance()
228    }
229
230    parser.inject_tokens(macro_data.iter(Some(args_tokens)));
231
232    parser.current_macros.insert(current_macro);
233
234    parser.advance()
235}
236
237fn parse_comment_multi_end<'a>(
238    parser: &mut Parser<'a>, start_equals_amount: usize
239) -> Option<Token> {
240    // We keep advancing tokens until we find a closing multiline string
241    // token with the same amount of equals signs as the start token.
242    loop {
243        let token = parser.core_advance()?;
244
245        if let Token::StringMultiEnd = token {
246            let end_token_value = parser.slice();
247            let end_equals_amount = end_token_value.clip(1, 1).len();
248
249            if start_equals_amount == end_equals_amount {
250                return parser.core_advance()
251            }
252        }
253    }
254}
255
256fn parse_comment_multi<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
257    if let Token::CommentMultiStart = token {
258        let token_value = parser.slice();
259        let start_equals_amount = token_value.clip(3, 1).len();
260
261        return parse_comment_multi_end(parser, start_equals_amount);
262    };
263
264    None
265}
266
267fn parse_comment_single<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
268    if !matches!(token, Token::CommentSingle) { return None }
269
270    parser.core_advance()
271}
272
273fn parse_scope_open<'a>(parser: &mut Parser<'a>, token: Token, selector: Option<String>) -> Option<Token> {
274    if !matches!(token, Token::ScopeOpen) { return Some(token) }
275 
276    let new_tree_node_idx = parser.tree_nodes.nodes_len();
277    let new_tree_node_idx_as_parent = TreeNodeType::Node(new_tree_node_idx);
278
279    let previous_tree_node = parser.tree_nodes.get_node_mut(parser.current_tree_node_idx);
280    match previous_tree_node {
281        AnyTreeNodeMut::Root(node) => node.unwrap().child_rules.push(new_tree_node_idx),
282        AnyTreeNodeMut::Node(node) => node.unwrap().child_rules.push(new_tree_node_idx)
283    }
284
285    let current_tree_node = TreeNode::new(parser.current_tree_node_idx, selector);
286    parser.tree_nodes.add_node(current_tree_node);
287
288    parser.current_tree_node_idx = new_tree_node_idx_as_parent;
289
290    parser.advance()
291}
292
293fn parse_scope_delimiter<'a>(
294    parser: &mut Parser<'a>,
295    token: Token,
296    delim_token: Option<Token>
297) -> TokenWithResult<'a, Option<Token>> {
298    if matches!(token, Token::Comma) {
299        let next_token = guarded_unwrap!(parser.advance(), return (None, delim_token));
300        return parse_scope_delimiter(parser, next_token, Some(token))
301
302    } else {
303        return (Some(token), delim_token)
304    }
305}
306
307fn parse_scope_selector_start<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
308    // The `Token::Text` case is handled in `parse_property`.
309    if !matches!(token, 
310        Token::NameIdentifier | Token::PsuedoIdentifier | Token::StateOrEnumIdentifier |
311        Token::TagOrEnumIdentifier | Token::ScopeToDescendants | Token::ScopeToChildren
312    ) { return Some(token) }
313
314    let selector = Selector::new(parser.slice(), token);
315
316    let token = parser.advance()?;
317    return parse_scope_selector(parser, token, selector);
318}
319
320fn parse_scope_selector<'a>(
321    parser: &mut Parser<'a>, mut token: Token, mut selector: Selector
322) -> Option<Token> {
323    loop {
324        // Advances the parser until no delimiter token is found.
325        let parsed_delimiter = parse_scope_delimiter(parser, token, None);
326        token = guarded_unwrap!(parsed_delimiter.0, return None);
327
328        if matches!(token, 
329            Token::NameIdentifier | Token::PsuedoIdentifier | Token::StateOrEnumIdentifier |
330            Token::TagOrEnumIdentifier | Token::ScopeToDescendants | Token::ScopeToChildren |
331            Token::Text
332        ) {
333            // Appending the comma token here ensures selectors can't end with delimiters.
334            if let Some(delim_token) = parsed_delimiter.1 {
335                selector.append(",", delim_token);
336            }
337            
338            selector.append(parser.slice(), token);
339
340            token = parser.advance()?;
341
342        } else { break }
343    };
344
345    return parse_scope_open(parser, token, Some(selector.content))
346}
347
348
349fn parse_scope_close<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
350    if !matches!(token, Token::ScopeClose) { return Some(token) }
351
352    let current_tree_node = parser.tree_nodes.get(parser.current_tree_node_idx);
353    match current_tree_node {
354        AnyTreeNode::Node(node) => parser.current_tree_node_idx = node.unwrap().parent,
355        _ => ()
356    }
357
358    return parser.advance()
359}
360
361fn parse_string_multi_end<'a>(
362    parser: &mut Parser<'a>, start_equals_amount: usize
363) -> TokenWithResult<'a, String> {
364    let mut string_data = String::new();
365
366    // We keep advancing tokens until we find a closing multiline string
367    // token with the same amount of equals signs as the start token.
368    loop {
369        match parser.lexer.next() {
370            Some(Ok(token)) => {
371                if let Token::StringMultiEnd = token {
372                    let end_token_value = parser.slice();
373                    let end_equals_amount = end_token_value.clip(1, 1).len();
374        
375                    if start_equals_amount == end_equals_amount {
376                        return (parser.core_advance(), string_data)
377                    }
378                }
379
380                string_data += parser.slice();
381            },
382
383            Some(Err(_)) => {
384                string_data += parser.slice();
385            },
386
387            None => return (None, string_data)
388        };
389    }
390}
391
392fn parse_string_multi_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
393    if let Token::StringMultiStart = token {
394        let token_value = parser.slice();
395        let start_equals_amount = token_value.clip(1, 1).len();
396
397        let (token, string_data) = parse_string_multi_end(parser, start_equals_amount);
398
399        // Luau strips multiline strings up until the first occurance of a newline character.
400        // So we will mimic this behaviour.
401        let string_data = MULTI_LINE_STRING_STRIP_LEFT_REGEX.replace(&string_data, "").to_string();
402        return (token, Some(Datatype::Variant(Variant::String(string_data))))
403    };
404
405    (Some(token), None)
406}
407
408fn parse_content_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
409    if let Token::RobloxContent = token {
410        let content = parser.slice();
411        return (parser.advance(), Some(Datatype::Variant(Variant::Content(Content::from(content)))))
412    }
413
414    (Some(token), None)
415}
416
417fn parse_string_single_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
418    match token {
419        Token::StringSingle => {
420            let str = parser.slice();
421            let datatype = Some(Datatype::Variant(Variant::String(str.clip(1, 1).to_string())));
422            return (parser.advance(), datatype)
423        },
424
425        Token::RobloxAsset => {
426            let str = parser.slice();
427            let datatype = Some(Datatype::Variant(Variant::String(str.to_string())));
428            return (parser.advance(), datatype)
429        },
430
431        _ => (Some(token), None)
432    }
433}
434
435fn parse_string_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
436    let parsed = parse_string_single_datatype(parser, token);
437    if parsed.1.is_some() { return parsed }
438
439    let parsed = parse_string_multi_datatype(parser, token);
440    if parsed.1.is_some() { return parsed }
441
442    (Some(token), None)
443}
444
445fn parse_number_offset<'a>(parser: &mut Parser<'a>, token: Token, num_str: &str) -> TokenWithResult<'a, Option<Datatype>> {
446    if !matches!(token, Token::Offset) { return (Some(token), None) }
447
448    let datatype = Some(Datatype::Variant(Variant::UDim(UDim::new(
449        0.0, 
450        match parse_number_string::<i32>(num_str) {
451            Ok(int32) => int32,
452            Err(_) => parse_number_string::<f32>(num_str).unwrap() as i32
453        }
454    ))));
455
456    return (parser.advance(), datatype)
457}
458
459fn parse_number_scale<'a>(parser: &mut Parser<'a>, token: Token, num_str: &str) -> TokenWithResult<'a, Option<Datatype>> {
460    if !matches!(token, Token::ScaleOrOpMod) { return (Some(token), None) }
461
462    let datatype = Some(Datatype::Variant(Variant::UDim(UDim::new(parse_number_string::<f32>(num_str).unwrap() / 100.0, 0))));
463
464    return (parser.advance(), datatype)
465}
466
467fn parse_number_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
468    if let Token::Number = token {
469        let token_value = parser.slice();
470        let token = parser.advance();
471
472        if let Some(token) = token {
473            let parsed = parse_number_offset(parser, token, token_value);
474            if parsed.1.is_some() { return parsed }
475
476            let parsed = parse_number_scale(parser, token, token_value);
477            if parsed.1.is_some() { return parsed }
478        }
479
480        let datatype = Some(Datatype::Variant(Variant::Float32(parse_number_string::<f32>(token_value).unwrap())));
481
482        return (token, datatype)
483    }
484
485    (Some(token), None)
486}
487
488fn parse_operator_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
489    match Operator::from_token(token) {
490        Some(operator) => (parser.advance(), Some(Datatype::Operator(operator.clone()))),
491        None => (Some(token), None)
492    }
493}
494
495fn parse_enum_tokens<'a>(parser: &mut Parser<'a>, token_history: &mut Vec<Token>) -> Option<Datatype> {
496    let token_history_len = token_history.len();
497    let mut first_stop_idx = 0;
498
499    let mut enum_name = None;
500    for idx in 0..=token_history_len {
501        let token = &token_history[idx];
502        
503        if let Token::Text = token {
504            let text = parser.slice();
505            enum_name = Some(text);
506            
507            first_stop_idx = idx;
508            break
509        }
510    };
511    let enum_name = guarded_unwrap!(enum_name, return None);
512
513    let mut enum_value_name = None;
514    for idx in (first_stop_idx + 1)..=token_history_len {
515        let token = &token_history[idx];
516
517        if let Token::Text = token {
518            let text = parser.slice();
519            enum_value_name = Some(text);
520            break
521        }
522    };
523    let enum_value_name = guarded_unwrap!(enum_value_name, return None);
524
525    let enum_item = guarded_unwrap!(EnumItem::from_name_and_value_name(enum_name, enum_value_name), return Some(Datatype::None));
526    return Some(Datatype::Variant(Variant::EnumItem(enum_item)))
527}
528
529fn parse_full_enum<'a>(
530    parser: &mut Parser<'a>, token: Token, token_history: &mut Vec<Token>
531) -> TokenWithResult<'a, Option<Datatype>> {
532    if matches!(token, 
533        Token::TagOrEnumIdentifier | Token::StateOrEnumIdentifier | Token::Text
534    ) {
535        let token = parser.advance();
536
537        if let Some(token) = token {
538            token_history.push(token);
539
540            let parsed = parse_full_enum(parser, token, token_history);
541            if parsed.1.is_some() { return parsed }
542        }
543    }
544
545    if token_history.len() == 0 { return (Some(token), None) }
546
547    return (Some(token), parse_enum_tokens(parser, token_history))
548}
549
550
551fn parse_enum_keyword<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
552    if !matches!(token, Token::EnumKeyword) { return (Some(token), None) }
553
554    let token = guarded_unwrap!(parser.advance(), return (None, None) );
555
556    let mut token_history = vec![];
557    parse_full_enum(parser, token, &mut token_history)
558}
559
560const SHORTHAND_REBINDS: phf::Map<&'static str, &'static str> = phf_map! {
561    "FlexMode" => "UIFlexMode",
562    "HorizontalFlex" => "UIFlexAlignment",
563    "VerticalFlex" => "UIFlexAlignment"
564};
565
566fn parse_enum_shorthand<'a>(parser: &mut Parser<'a>, token: Token, key: Option<&str>) -> TokenWithResult<'a, Option<Datatype>> {
567    if !matches!(token, Token::StateOrEnumIdentifier) { return (Some(token), None) }
568
569    let token = guarded_unwrap!(parser.advance(), return (None, None));
570
571    let enum_value_name = if let Token::Text = token { parser.slice() } else { return (Some(token), None) };
572
573    if let Some(key) = key {
574        let enum_name = SHORTHAND_REBINDS.get(key).unwrap_or(&key);
575
576        let enum_item = guarded_unwrap!(
577            EnumItem::from_name_and_value_name(enum_name, enum_value_name), return (parser.advance(), Some(Datatype::None))
578        );
579        return (parser.advance(), Some(Datatype::Variant(Variant::EnumItem(enum_item))))
580
581    } else {
582        let datatype = Datatype::IncompleteEnumShorthand(enum_value_name.into());
583        return (parser.advance(), Some(datatype))
584    }
585
586    
587}
588
589fn parse_enum_datatype<'a>(parser: &mut Parser<'a>, token: Token, key: Option<&str>) -> TokenWithResult<'a, Option<Datatype>> {
590    let parsed = parse_enum_keyword(parser, token);
591    if parsed.1.is_some() { return parsed }
592
593    let parsed = parse_enum_shorthand(parser, token, key);
594    if parsed.1.is_some() { return parsed }
595
596    (Some(token), None)
597}
598
599fn parse_nil_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
600    if !matches!(token, Token::Nil) { return (Some(token), None) }
601
602    (parser.advance(), Some(Datatype::None))
603}
604
605fn parse_boolean_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
606    match token {
607        Token::BoolTrue => {
608            (parser.advance(), Some(Datatype::Variant(Variant::Bool(true))))
609        },
610        Token::BoolFalse => {
611            (parser.advance(), Some(Datatype::Variant(Variant::Bool(false))))
612        },
613        _ => (Some(token), None)
614    }
615}
616
617#[allow(warnings)]
618fn parse_preset_tailwind_color<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
619    if let Token::ColorTailwind = token {
620        let color_name = parser.slice();
621        let datatype = TAILWIND_COLORS.get(&color_name.to_lowercase())
622            .and_then(|color| Some(Datatype::Oklab(**color.deref())));
623
624        return (parser.advance(), datatype)
625    }
626
627    (Some(token), None)
628}
629
630#[allow(warnings)]
631fn parse_preset_skin_color<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
632    if let Token::ColorSkin = token {
633        let color_name = parser.slice();
634        let datatype = SKIN_COLORS.get(&color_name.to_lowercase())
635            .and_then(|color| Some(Datatype::Oklab(**color.deref())));
636
637        return (parser.advance(), datatype)
638    }
639
640    (Some(token), None)
641}
642
643#[allow(warnings)]
644fn parse_preset_css_color<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
645    if let Token::ColorCss = token {
646        let color_name = parser.slice();
647        let datatype = CSS_COLORS.get(&color_name.to_lowercase())
648            .and_then(|color| Some(Datatype::Oklab(**color.deref())));
649
650        return (parser.advance(), datatype)
651    }
652
653    (Some(token), None)
654}
655
656#[allow(warnings)]
657fn parse_preset_brick_color<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
658    if let Token::ColorBrick = token {
659        let color_name = parser.slice();
660        let datatype = BRICK_COLORS.get(&color_name.to_lowercase())
661            .and_then(|color| Some(Datatype::Oklab(**color.deref())));
662
663        return (parser.advance(), datatype)
664    }
665
666    (Some(token), None)
667}
668
669fn parse_preset_color_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
670    let parsed = parse_preset_tailwind_color(parser, token);
671    if parsed.1.is_some() { return parsed }
672
673    let parsed = parse_preset_skin_color(parser, token);
674    if parsed.1.is_some() { return parsed }
675
676    let parsed = parse_preset_css_color(parser, token);
677    if parsed.1.is_some() { return parsed }
678
679    let parsed = parse_preset_brick_color(parser, token);
680    if parsed.1.is_some() { return parsed }
681
682    return (Some(token), None)
683}
684
685fn normalize_hex(hex: &str) -> String {
686    let hex = hex.trim_start_matches('#');
687
688    match hex.len() {
689        3 | 6 => hex.into(),
690        1..=5 => format!("{:0<6}", hex),
691        _ => hex.into(),
692    }
693}
694
695fn parse_hex_color_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
696    if let Token::ColorHex = token {
697        let hex = parser.slice();
698
699        let color: Srgb<u8> = normalize_hex(hex).parse().unwrap();
700        let datatype = Datatype::Variant(Variant::Color3(
701            Color3uint8::new(color.red, color.green, color.blue).into(),
702        ));
703
704        return (parser.advance(), Some(datatype))
705    }
706
707    return (None, None)
708}
709
710fn parse_color_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
711    let parsed = parse_preset_color_datatype(parser, token);
712    if parsed.1.is_some() { return parsed }
713
714    let parsed = parse_hex_color_datatype(parser, token);
715    if parsed.1.is_some() { return parsed }
716
717    return (Some(token), None)
718}
719
720fn parse_attribute_reference_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
721    if !matches!(token, Token::AttributeIdentifier) { return (Some(token), None) }
722
723    let token = guarded_unwrap!(parser.advance(), return (None, None));
724
725    if let Token::Text = token {
726        let attribute_name = parser.slice();
727        return (parser.advance(), Some(Datatype::Variant(Variant::String(format!("${}", attribute_name)))))
728    }
729
730    (Some(token), None)
731}
732
733fn resolve_static_attribute_reference<'a>(parser: &mut Parser<'a>, static_name: &str, tree_node_idx: TreeNodeType) -> Datatype {
734    let tree_node = parser.tree_nodes.get(tree_node_idx);
735
736    match tree_node {
737        AnyTreeNode::Root(node) => {
738            let resolved = node.unwrap().static_attributes.get(static_name);
739
740            match resolved {
741                Some(datatype) => datatype.clone(),
742        
743                None => Datatype::None
744            }
745        },
746
747        AnyTreeNode::Node(node) => {
748            let node = node.unwrap();
749            let resolved = node.static_attributes.get(static_name);
750
751            match resolved {
752                Some(datatype) => datatype.clone(),
753        
754                None => resolve_static_attribute_reference(parser, static_name, node.parent)
755            }
756        }
757    }
758}
759
760fn parse_static_attribute_reference_datatype<'a>(parser: &mut Parser<'a>, token: Token) -> TokenWithResult<'a, Option<Datatype>> {
761    if !matches!(token, Token::StaticAttributeIdentifier) { return (Some(token), None) }
762
763    let token = guarded_unwrap!(parser.advance(), return (None, None));
764
765    if let Token::Text = token {
766        let static_name = parser.slice();
767
768        let resolved_datatype = resolve_static_attribute_reference(parser, static_name, parser.current_tree_node_idx);
769
770        return (parser.advance(), Some(resolved_datatype))
771    }
772
773    (Some(token), None)
774}
775
776fn parse_datatype<'a>(
777    parser: &mut Parser<'a>, mut token: Token, key: Option<&str>
778) -> TokenWithResult<'a, Option<Datatype>> {
779    if let (Some(tuple_token), current_tuple_idx) = parse_tuple_name(parser, token, None, None) {
780        // Checking for a tuple can lead to a new token,
781        // even if cases where a tuple isn't found.
782        token = tuple_token;
783
784        if let Some(current_tuple_idx) = current_tuple_idx {
785            let current_tuple = parser.get_tuple(current_tuple_idx).unwrap();
786
787            return (Some(token), Some(current_tuple.coerce_to_datatype()))
788        }
789    };
790  
791    let parsed = parse_string_datatype(parser, token);
792    if parsed.1.is_some() { return parsed }
793
794    let parsed = parse_content_datatype(parser, token);
795    if parsed.1.is_some() { return parsed }
796
797    let parsed = parse_number_datatype(parser, token);
798    if parsed.1.is_some() { return parsed }
799
800    let parsed = parse_operator_datatype(parser, token);
801    if parsed.1.is_some() { return parsed }
802
803    let parsed = parse_enum_datatype(parser, token, key);
804    if parsed.1.is_some() { return parsed }
805
806    let parsed = parse_color_datatype(parser, token);
807    if parsed.1.is_some() { return parsed }
808
809    let parsed = parse_attribute_reference_datatype(parser, token);
810    if parsed.1.is_some() { return parsed }
811
812    let parsed = parse_static_attribute_reference_datatype(parser, token);
813    if parsed.1.is_some() { return parsed }
814
815    let parsed = parse_boolean_datatype(parser, token);
816    if parsed.1.is_some() { return parsed }
817
818    let parsed = parse_nil_datatype(parser, token);
819    if parsed.1.is_some() { return parsed }
820
821    (Some(token), None)
822}
823
824fn parse_datatype_group<'a>(
825    parser: &mut Parser<'a>, token: Token, key: Option<&str>,
826    mut datatype_group: Option<DatatypeGroup>, mut pending_operator: Option<Operator>
827) -> TokenWithResult<'a, Option<Datatype>> {
828    let (token, datatype) = parse_datatype(parser, token, key);
829
830    if let Some(datatype) = datatype {
831        // If the datatype is an operator then we need to postpone adding it
832        // to the datatypes group so we can atomise it with the next datatype
833        // if it is an operator.
834        if !matches!(datatype, Datatype::Operator(_)) {
835             if let Some(some_pending_operator) = pending_operator {
836                // We can add our pending operator to the datatypes table
837                // since it has no other operator to atomise with.
838                let mut datatypes_exists = DatatypeGroup::ensure_then_insert(
839                    datatype_group, 
840                    Datatype::Operator(some_pending_operator)
841                );
842                pending_operator = None;
843                datatypes_exists.push(datatype.clone());
844                datatype_group = Some(datatypes_exists);
845                
846            } else {
847                datatype_group = Some(DatatypeGroup::ensure_then_insert(datatype_group, datatype.clone()))
848            }
849        }
850
851        if let Some(some_token) = token {
852            if matches!(some_token, Token::ParensClose | Token::ScopeClose | Token::Comma | Token::SemiColon) {
853                return (token, datatype_group.and_then(|mut x| Some(x.coerce_to_datatype())));
854
855            } else {
856                if let Datatype::Operator(operator) = datatype {
857                    // Since our datatype was an operator we need to mark it as pending,
858                    // atomising with the existing pending operator if it exists.
859
860                    if let Some(some_pending_operator) = pending_operator {
861                        if some_pending_operator.can_merge_with(&operator) {
862                            pending_operator = Some(some_pending_operator.merge_with(&operator))
863                        } else {
864                            datatype_group = Some(DatatypeGroup::ensure_then_insert(datatype_group, Datatype::Operator(some_pending_operator)));
865                            pending_operator = Some(operator)
866                        }
867                    } else {
868                        pending_operator = Some(operator)
869                    }
870                }
871
872                return parse_datatype_group(parser, some_token, key, datatype_group, pending_operator);
873            }
874        } else {
875            return (token, datatype_group.and_then(|mut x| Some(x.coerce_to_datatype())));
876        }
877
878    } else {
879        return (token, datatype_group.and_then(|mut x| Some(x.coerce_to_datatype())))
880    }
881}
882
883fn parse_tuple_close<'a>(
884    parser: &mut Parser<'a>, token: Token,
885    current_tuple_idx: usize, root_tuple_idx: usize
886) -> Option<Token> {
887    if !matches!(token, Token::ParensClose) { return None }
888
889    let token = parser.advance();
890
891    let current_tuple = parser.get_tuple(current_tuple_idx).unwrap();
892    let parent_tuple_idx = current_tuple.parent;
893
894    if let Some(some_parent_tuple_idx) = parent_tuple_idx {
895        let datatype = current_tuple.coerce_to_datatype();
896        parser.get_tuple_mut(some_parent_tuple_idx).unwrap().push(datatype);
897
898        let token = guarded_unwrap!(token, return None);
899        
900        let parsed = parse_tuple_delimiter(parser, token, some_parent_tuple_idx, root_tuple_idx);
901        if parsed.is_some() { return parsed }
902
903        let parsed = parse_tuple_close(parser, token, some_parent_tuple_idx, root_tuple_idx);
904        if parsed.is_some() { return parsed }
905
906        let parsed = parse_tuple_name(
907            parser, token, parent_tuple_idx, Some(root_tuple_idx)
908        );
909        if parsed.1.is_some() { return parsed.0 }
910    };
911
912    token
913}
914
915fn parse_tuple_datatype<'a>(
916    parser: &mut Parser<'a>, token: Token,
917    current_tuple_idx: usize, root_tuple_idx: usize
918) -> Option<Token> {
919    let (token, datatype) = parse_datatype_group(
920        parser, token, None, None, None
921    );
922
923    let datatype = guarded_unwrap!(datatype, return None);
924
925    let current_tuple = parser.get_tuple_mut(current_tuple_idx).unwrap();
926    current_tuple.push(datatype);
927
928    if let Some(token) = token {
929        let parsed = parse_tuple_delimiter(parser, token, current_tuple_idx, root_tuple_idx);
930        if parsed.is_some() { return parsed }
931
932        let parsed = parse_tuple_close(parser, token, current_tuple_idx, root_tuple_idx);
933        if parsed.is_some() { return parsed }
934        
935        let parsed = parse_tuple_name(
936            parser, token, Some(current_tuple_idx), Some(root_tuple_idx)
937        );
938        if parsed.1.is_some() { return parsed.0 }
939    }
940
941    token
942}
943
944fn parse_tuple_delimiter<'a>(
945    parser: &mut Parser<'a>, token: Token,
946    current_tuple_idx: usize, root_tuple_idx: usize
947) -> Option<Token> {
948    if !matches!(token, Token::SemiColon | Token::Comma) { return None }
949
950    let token = parser.advance();
951
952    if let Some(token) = token {
953        // Handles cases of multiple delimiter tokens next to each other.
954        let parsed = parse_tuple_delimiter(parser, token, current_tuple_idx, root_tuple_idx);
955        if parsed.is_some() { return parsed }
956        
957        let parsed = parse_tuple_close(parser, token, current_tuple_idx, root_tuple_idx);
958        if parsed.is_some() { return parsed }
959
960        let parsed = parse_tuple_name(
961            parser, token, Some(current_tuple_idx), Some(root_tuple_idx)
962        );
963        if parsed.1.is_some() { return parsed.0 }
964
965        let parsed = parse_tuple_datatype(parser, token, current_tuple_idx, root_tuple_idx);
966        if parsed.is_some() { return parsed }
967    }
968
969    token
970}
971
972fn parse_tuple_open<'a>(
973    parser: &mut Parser<'a>, token: Token, tuple_name: Option<String>,
974    parent_tuple_idx: Option<usize>, root_tuple_idx: Option<usize>
975) -> TokenWithResult<'a, Option<usize>> {
976    if !matches!(token, Token::ParensOpen) { return (None, None) };
977
978    let current_tuple_idx = parser.push_tuple(
979        Tuple::new(tuple_name, parent_tuple_idx)
980    );
981
982    let token = guarded_unwrap!(parser.advance(), return (None, Some(current_tuple_idx)));
983
984    let root_tuple_idx = root_tuple_idx.unwrap_or(current_tuple_idx);
985
986    let parsed = parse_tuple_delimiter(parser, token, current_tuple_idx, root_tuple_idx);
987    if parsed.is_some() { return (parsed, Some(current_tuple_idx)) }
988
989    let parsed = parse_tuple_close(parser, token, current_tuple_idx, root_tuple_idx);
990    if parsed.is_some() { return (parsed, Some(current_tuple_idx)) }
991
992    let parsed = parse_tuple_name(
993        parser, token, Some(current_tuple_idx), Some(root_tuple_idx)
994    );
995    if parsed.0.is_some() { return (parsed.0, Some(current_tuple_idx)) }
996
997    let parsed = parse_tuple_datatype(parser, token, current_tuple_idx, root_tuple_idx);
998    if parsed.is_some() { return (parsed, Some(current_tuple_idx)) }
999
1000    (Some(token), Some(current_tuple_idx))
1001}
1002
1003fn parse_tuple_name<'a>(
1004    parser: &mut Parser<'a>, token: Token,
1005    parent_tuple_idx: Option<usize>, root_tuple_idx: Option<usize>
1006) -> TokenWithResult<'a, Option<usize>> {
1007    if let Token::Text = token {
1008        let tuple_name = parser.slice();
1009        let token = guarded_unwrap!(parser.advance(), return (None, None));
1010
1011        return parse_tuple_open(parser, token, Some(tuple_name.to_string()), parent_tuple_idx, root_tuple_idx)
1012
1013    } else {
1014        return parse_tuple_open(parser, token, None, parent_tuple_idx, root_tuple_idx)
1015    }
1016}
1017
1018fn parse_delimiters<'a>(parser: &mut Parser<'a>, token: Token)  -> Option<Token> {
1019    if matches!(token, Token::SemiColon | Token::Comma) {
1020        let token = parser.advance()?;
1021        return parse_delimiters(parser, token);
1022    }
1023
1024    return Some(token)
1025}
1026
1027fn parse_property<'a>(parser: &mut Parser<'a>, mut token: Token) -> Option<Token> {
1028    if let Token::Text = token {
1029        let property_name = parser.slice();
1030        let selector_token = token;
1031
1032        token = parser.advance()?;
1033
1034        if !matches!(token, Token::Equals) {
1035            return parse_scope_selector(parser, token, Selector::new(property_name, selector_token))
1036        };
1037
1038        // We only want to parse the property if the current node is not the root.
1039        if let TreeNodeType::Node(node_idx) = parser.current_tree_node_idx {
1040            token = parser.advance()?;
1041
1042            let (token, datatype) = parse_datatype_group(
1043                parser, token, Some(property_name), None, None
1044            );
1045            let variant = datatype.and_then(|d| d.coerce_to_variant(Some(property_name)));
1046    
1047            if let Some(variant) = variant {
1048                let current_tree_node = parser.tree_nodes[node_idx].as_mut().unwrap();
1049                current_tree_node.properties.insert(property_name.to_string(), variant);
1050            }
1051    
1052            let token = guarded_unwrap!(token, return None);
1053            return parse_delimiters(parser, token);
1054
1055        } else {
1056            return Some(token)
1057        }
1058    }
1059
1060    Some(token)
1061}
1062
1063fn parse_static_attribute<'a>(parser: &mut Parser<'a>, mut token: Token) -> Option<Token> {
1064    if !matches!(token, Token::StaticAttributeIdentifier) { return Some(token) };
1065
1066    token = parser.advance()?;
1067
1068    if let Token::Text = token {
1069        let static_name = parser.slice();
1070        let next_token = parser.advance()?;
1071        
1072        if !matches!(next_token, Token::Equals) { return Some(next_token) }
1073
1074        token = parser.advance()?;
1075
1076        let (token, datatype) = parse_datatype_group(
1077            parser, token, Some(static_name), None, None
1078        );
1079        let datatype = datatype.and_then(|d| d.coerce_to_static(Some(static_name)));
1080
1081        if let Some(datatype) = datatype {
1082            let current_tree_node = parser.tree_nodes.get_node_mut(parser.current_tree_node_idx);
1083            match current_tree_node {
1084                AnyTreeNodeMut::Root(node) => {
1085                    node.unwrap().static_attributes.insert(static_name.to_string(), datatype)
1086                },
1087                AnyTreeNodeMut::Node(node) => {
1088                    node.unwrap().static_attributes.insert(static_name.to_string(), datatype)
1089                }
1090            };
1091        }
1092
1093        let token = guarded_unwrap!(token, return None);
1094        return parse_delimiters(parser, token)
1095    }
1096
1097    Some(token)
1098}
1099
1100fn parse_attribute<'a>(parser: &mut Parser<'a>, mut token: Token) -> Option<Token> {
1101    if !matches!(token, Token::AttributeIdentifier) { return Some(token) };
1102
1103    token = parser.advance()?;
1104
1105    if let Token::Text = token {
1106        let attribute_name = parser.slice();
1107        let next_token = parser.advance()?;
1108        
1109        if !matches!(next_token, Token::Equals) { return Some(next_token) }
1110
1111        token = parser.advance()?;
1112
1113        let (token, datatype) = parse_datatype_group(
1114            parser, token, Some(attribute_name), None, None
1115        );
1116        let variant = datatype.and_then(|d| d.coerce_to_variant(Some(attribute_name)));
1117
1118        if let Some(variant) = variant {
1119            let current_tree_node = parser.tree_nodes.get_node_mut(parser.current_tree_node_idx);
1120            match current_tree_node {
1121                AnyTreeNodeMut::Root(node) => {
1122                    node.unwrap().attributes.insert(attribute_name.to_string(), variant)
1123                },
1124                AnyTreeNodeMut::Node(node) => {
1125                    node.unwrap().attributes.insert(attribute_name.to_string(), variant)
1126                }
1127            };
1128        }
1129
1130        let token = guarded_unwrap!(token, return None);
1131        return parse_delimiters(parser, token)
1132    }
1133
1134    Some(token)
1135}
1136
1137fn parse_priority_declaration<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
1138    if !matches!(token, Token::PriorityDeclaration) { return Some(token) }
1139
1140    let token = parser.advance()?;
1141
1142    // We only want to parse the priority if the current node is not the root.
1143    if let TreeNodeType::Node(node_idx) = parser.current_tree_node_idx {
1144        let (token, datatype) = parse_datatype_group(parser, token, None, None, None);
1145
1146        if let Some(Datatype::Variant(Variant::Float32(float32))) = datatype {
1147            let current_tree_node = parser.tree_nodes[node_idx].as_mut().unwrap();
1148            current_tree_node.priority = Some(float32 as i32);
1149        }
1150    
1151        let token = guarded_unwrap!(token, return None);
1152        parse_delimiters(parser, token)
1153
1154    } else {
1155        Some(token)
1156    }
1157}
1158
1159fn parse_name_declaration<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
1160    if !matches!(token, Token::NameDeclaration) { return Some(token) }
1161
1162    let token = parser.advance()?;
1163
1164    // We only want to parse the name if the current node is not the root.
1165    if let TreeNodeType::Node(node_idx) = parser.current_tree_node_idx {
1166        let (token, datatype) = parse_datatype_group(
1167            parser, token, None, None, None
1168        );
1169    
1170        if let Some(Datatype::Variant(Variant::String(name))) = datatype {
1171            let current_tree_node = parser.tree_nodes[node_idx].as_mut().unwrap();
1172            current_tree_node.name = Some(name);
1173        }
1174    
1175        let token = guarded_unwrap!(token, return None);
1176        parse_delimiters(parser, token)
1177
1178    } else {
1179        Some(token)
1180    }
1181}
1182
1183fn parse_tween_declaration<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
1184    if !matches!(token, Token::TweenDeclaration) { return Some(token) }
1185
1186    let token = parser.advance()?;
1187
1188    // The next token should be a Text token (the property name to tween).
1189    if !matches!(token, Token::Text) { return Some(token) }
1190    let tween_name = parser.slice();
1191
1192    let token = parser.advance()?;
1193
1194    // We only want to parse the tween if the current node is not the root.
1195    if let TreeNodeType::Node(node_idx) = parser.current_tree_node_idx {
1196        let (token, datatype) = parse_datatype_group(parser, token, None, None, None);
1197
1198        if let Some(datatype) = datatype {
1199            let current_tree_node = parser.tree_nodes[node_idx].as_mut().unwrap();
1200            current_tree_node.tweens.insert(tween_name.to_string(), datatype);
1201        }
1202
1203        let token = guarded_unwrap!(token, return None);
1204        parse_delimiters(parser, token)
1205    } else {
1206        Some(token)
1207    }
1208}
1209
1210fn parse_ignore_derive_declaration<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
1211    if !matches!(token, Token::DeriveDeclaration) { return Some(token) }
1212
1213    let token = parser.core_advance()?;
1214    if !matches!(token, Token::Text) { return Some(token) }
1215
1216    let token = parser.core_advance()?;
1217
1218    parse_ignore_tuple_open(parser, token)
1219}
1220
1221// Util and Macro declarations are ignored in the main parser.
1222fn parse_ignore_scope_open<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
1223    if !matches!(token, Token::ScopeOpen) { return Some(token) }
1224
1225    let mut nestedness = 0usize;
1226
1227    loop {
1228        match parser.core_advance()? {
1229            Token::ScopeOpen => nestedness += 1,
1230            Token::ScopeClose => match nestedness {
1231                // End of parsing.
1232                0 => return parser.advance(),
1233                _ => nestedness -= 1
1234            },
1235            _ => ()
1236        }
1237    }
1238}
1239
1240// Util declarations are ignored in the main parser.
1241fn parse_util_declaration<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
1242    if !matches!(token, Token::UtilDeclaration) { return Some(token) }
1243
1244    let token = parser.core_advance()?;
1245    if !matches!(token, Token::Text) { return Some(token) }
1246
1247    let token = parser.core_advance()?;
1248    parse_ignore_scope_open(parser, token)
1249}
1250
1251// Macro declarations are ignored in the main parser.
1252fn parse_ignore_tuple_open<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
1253    if !matches!(token, Token::ParensOpen) { return Some(token) }
1254
1255    let mut nestedness = 0usize;
1256
1257    loop {
1258        match parser.core_advance()? {
1259            Token::ParensOpen => nestedness += 1,
1260            Token::ParensClose => match nestedness {
1261                // End of parsing.
1262                0 => return parser.advance(),
1263                _ => nestedness -= 1
1264            },
1265            _ => ()
1266        }
1267    }
1268}
1269
1270// Macro declarations are ignored in the main parser.
1271fn parse_macro_declaration<'a>(parser: &mut Parser<'a>, token: Token) -> Option<Token> {
1272    if !matches!(token, Token::MacroDeclaration) { return Some(token) }
1273
1274    let token = parser.core_advance()?;
1275    if !matches!(token, Token::Text) { return Some(token) }
1276
1277    let token = parser.core_advance()?;
1278
1279    let token = parse_ignore_tuple_open(parser, token)?;
1280
1281    parse_ignore_scope_open(parser, token)
1282}
1283
1284fn main_loop<'a>(parser: &mut Parser<'a>) -> Option<()> {
1285    let mut token = parser.advance()?;
1286
1287    loop {
1288        parser.did_advance = false;
1289
1290        token = parse_attribute(parser, token)?;
1291        token = parse_static_attribute(parser, token)?;
1292        token = parse_property(parser, token)?;
1293        token = parse_scope_selector_start(parser, token)?;
1294        token = parse_scope_open(parser, token, None)?;
1295        token = parse_scope_close(parser, token)?;
1296        token = parse_priority_declaration(parser, token)?;
1297        token = parse_name_declaration(parser, token)?;
1298        token = parse_tween_declaration(parser, token)?;
1299        token = parse_ignore_derive_declaration(parser, token)?;
1300        token = parse_util_declaration(parser, token)?;
1301        token = parse_macro_declaration(parser, token)?;
1302
1303        // Ensures the parser is advanced at least one time per iteration.
1304        // This prevents infinite loops.
1305        if !parser.did_advance {
1306            token = guarded_unwrap!(parser.advance(), break)
1307        }
1308    }
1309
1310    None
1311}
1312
1313pub fn parse_rsml<'a>(lexer: &'a mut logos::Lexer<'a, Token>, macros: &'a MacroGroup) -> TreeNodeGroup {
1314    let mut parser = Parser::<'a>::new(lexer, macros);
1315
1316    main_loop(&mut parser);
1317
1318    return parser.tree_nodes;
1319}