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), ¯o_group), derives)
59}