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<String>,
}
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::<HashMap<_, _>>();
let arena = Bump::new();
let tokens = sources
.into_iter()
.map(|(filename, source)| (filename, tokenize(&source, &arena)))
.collect::<HashMap<_, _>>();
let asts = tokens
.into_iter()
.map(|(filename, tokens)| (filename, parse_document(tokens, &arena)))
.collect::<HashMap<_, _>>();
let symbol_tables = asts
.into_iter()
.map(|(filename, document)| (filename, symbol_table(&arena, document)))
.collect::<HashMap<_, _>>();
if !options.dry {
let output = compile(&symbol_tables.into_values().collect::<Box<_>>());
if let Err(e) = std::fs::write(options.out, output.as_bytes()) {
eprintln!("{e}");
std::process::exit(1);
}
}
}
|