use itertools::Itertools; use std::{fs, path::PathBuf, str::FromStr}; include!("./src/models.rs"); fn build(in_tokmap: &'static str, out_grammar: &'static str) { let map: TokenMap = serde_json::from_str(&fs::read_to_string(in_tokmap).unwrap()).unwrap(); let grammar_path = PathBuf::from_str(out_grammar).unwrap(); if grammar_path.exists() { fs::remove_file(&grammar_path).unwrap(); } let keys = map .keys() .sorted_by(|a, b| { Ord::cmp( &map.get(*b).unwrap().text.len(), &map.get(*a).unwrap().text.len(), ) }) .join(" | "); let rules = map .iter() .map(|(k, v)| { format!( "{k} = @{{ \"{}\" }}", v.text.replace('\"', "\\\"").replace("@@NEWLINE", "\\n") ) }) .join("\n"); let contents = format!("// GENERATED FILE\n\nWHITESPACE = {{ \"\\t\" }}\nprogram = {{ SOI ~ token* ~ EOI }}\ntoken = _{{ {keys} }}\n\n// -- //\n\n{rules}"); fs::write(grammar_path, contents).unwrap(); } fn main() { println!("cargo:rerun-if-changed=toks.json"); build("./toks.json", "./grammar.peg"); }