mod lexer;
use std::{fs, path::Path, sync::LazyLock};
use indexmap::IndexSet;
pub use lexer::{lex_rsml, Token};
mod parser;
pub use parser::{parse_rsml, TreeNode, TreeNodeGroup, Datatype};
mod macros;
pub use macros::{lex_rsml_macros, parse_rsml_macros, MacroGroup};
mod derives;
pub use derives::{lex_rsml_derives, parse_rsml_derives};
mod utils;
mod string_clip {
pub trait StringClip {
fn clip<'a>(&'a self, start: usize, end: usize) -> &'a str;
}
impl StringClip for str {
fn clip<'a>(&'a self, start: usize, end: usize) -> &'a str {
&self[start..self.len() - end]
}
}
}
const BUILTINS_CONTENT: &str = include_str!("../builtins.rsml");
pub static BUILTIN_MACROS: LazyLock<MacroGroup> = LazyLock::new(|| {
let mut macro_group = MacroGroup::new();
parse_rsml_macros(&mut macro_group, &mut lex_rsml_macros(&BUILTINS_CONTENT));
macro_group
});
pub fn file_to_rsml(path: &Path) -> (TreeNodeGroup, IndexSet<String>) {
let content = fs::read_to_string(path)
.expect("Could not read the file");
let mut macro_group = (*BUILTIN_MACROS).clone();
let parent_path = path.parent().unwrap();
let derives = parse_rsml_derives(&mut lex_rsml_derives(&content));
for derive in &derives {
let derive = if !derive.ends_with(".rsml") { &format!("{}.rsml", derive) } else { derive };
let derive_path = parent_path.join(derive);
if let Ok(derive_content) = fs::read_to_string(derive_path) {
parse_rsml_macros(&mut macro_group, &mut lex_rsml_macros(&derive_content));
}
}
parse_rsml_macros(&mut macro_group, &mut lex_rsml_macros(&content));
(parse_rsml(&mut lex_rsml(&content), ¯o_group), derives)
}