use std::collections::HashMap; use bpaf::{Bpaf, Parser}; use bumpalo::Bump; use kuht::{analyze::symbol_table, compile::compile, parse::parse_document, tokenize::tokenize}; #[derive(Debug, Clone, Bpaf)] struct Options { /// Show any errors without compiling #[bpaf(switch)] dry: bool, // The location to place the resulting HTML file #[bpaf(short)] out: String, /// The files to compile to an HTML #[bpaf(positional("FILES"))] files: Vec, } fn main() { let options = options().run(); let sources = options .files .into_iter() .map(|filename| { let source = match std::fs::read_to_string(&filename) { Ok(source) => source, Err(error) => { eprintln!("{error}"); std::process::exit(1); } }; (filename, source) }) .collect::>(); let arena = Bump::new(); let tokens = sources .into_iter() .map(|(filename, source)| (filename, tokenize(&source, &arena))) .collect::>(); let asts = tokens .into_iter() .map(|(filename, tokens)| (filename, parse_document(tokens, &arena))) .collect::>(); let symbol_tables = asts .into_iter() .map(|(filename, document)| (filename, symbol_table(&arena, document))) .collect::>(); if !options.dry { let output = compile(&symbol_tables.into_values().collect::>()); if let Err(e) = std::fs::write(options.out, output.as_bytes()) { eprintln!("{e}"); std::process::exit(1); } } }