rbx_rsml/
lib.rs

1mod lexer;
2use std::{fs, path::Path, sync::LazyLock};
3
4use indexmap::IndexSet;
5pub use lexer::{lex_rsml, Token};
6
7mod parser;
8pub use parser::{parse_rsml, TreeNode, TreeNodeGroup, Datatype};
9
10mod macros;
11pub use macros::{lex_rsml_macros, parse_rsml_macros, MacroGroup};
12
13mod derives;
14pub use derives::{lex_rsml_derives, parse_rsml_derives};
15
16mod utils;
17
18mod string_clip {
19    pub trait StringClip {
20        fn clip<'a>(&'a self, start: usize, end: usize) -> &'a str;
21    }
22    
23    impl StringClip for str {
24        fn clip<'a>(&'a self, start: usize, end: usize) -> &'a str {
25            &self[start..self.len() - end]
26        }
27    }
28}
29
30const BUILTINS_CONTENT: &str = include_str!("../builtins.rsml");
31
32static BUILTIN_MACROS: LazyLock<MacroGroup> = LazyLock::new(|| {
33    let mut macro_group = MacroGroup::new();
34    parse_rsml_macros(&mut macro_group, &mut lex_rsml_macros(&BUILTINS_CONTENT));
35    macro_group
36});
37
38pub fn file_to_rsml(path: &Path) -> (TreeNodeGroup, IndexSet<String>) {
39    let content = fs::read_to_string(path)
40        .expect("Could not read the file");
41
42    let mut macro_group = (*BUILTIN_MACROS).clone();
43
44    let parent_path = path.parent().unwrap();
45
46    let derives = parse_rsml_derives(&mut lex_rsml_derives(&content));
47    for derive in &derives {
48        let derive = if !derive.ends_with(".rsml") { &format!("{}.rsml", derive) } else { derive };
49        let derive_path = parent_path.join(derive);
50
51        if let Ok(derive_content) = fs::read_to_string(derive_path) {
52            parse_rsml_macros(&mut macro_group, &mut lex_rsml_macros(&derive_content));
53        }
54    }
55    
56    parse_rsml_macros(&mut macro_group, &mut lex_rsml_macros(&content));
57
58    (parse_rsml(&mut lex_rsml(&content), &macro_group), derives)
59}