use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::{env, fs};
fn main() -> Result<(), Box<dyn Error>> {
let cwd = env::current_dir().unwrap();
let grammars = vec!["Hamelin", "TrinoType"];
let antlr_path = cwd.join("bin").join("antlr4-4.8-2-SNAPSHOT-complete.jar");
for grammar in grammars.into_iter() {
let _ = gen_for_grammar(grammar, &antlr_path)?;
}
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed={}", antlr_path.display());
Ok(())
}
fn gen_for_grammar(grammar_file_name: &str, antlr_path: &PathBuf) -> Result<(), Box<dyn Error>> {
let out_dir = env::var("OUT_DIR")?;
let dest_path = Path::new(&out_dir);
let input = env::current_dir()?.join("grammars");
let file_name = grammar_file_name.to_owned() + ".g4";
let grammar_source = input.join(&file_name);
let grammar_content = fs::read_to_string(&grammar_source)?;
let transformed_content = grammar_content.replace("-> channel(HIDDEN)", "-> skip");
let temp_grammar = dest_path.join(&file_name);
fs::write(&temp_grammar, transformed_content)?;
let out_files = vec![
dest_path.join(grammar_file_name.to_lowercase() + "lexer.rs"),
dest_path.join(grammar_file_name.to_lowercase() + "parser.rs"),
dest_path.join(grammar_file_name.to_lowercase() + "visitor.rs"),
dest_path.join(grammar_file_name.to_lowercase() + "listener.rs"),
];
let mut c = Command::new("java");
c.current_dir(dest_path)
.arg("-jar")
.arg(antlr_path)
.arg("-Dlanguage=Rust")
.arg("-o")
.arg(dest_path)
.arg(&file_name)
.arg("-visitor");
eprintln!("Running command: {:?}", c);
c.spawn()?.wait_with_output()?;
for file in out_files {
eprintln!("reading {}", file.display());
let content = fs::read_to_string(file.clone())?;
eprintln!("opening for write {}", file.display());
let mut out = File::create(file)?;
for line in content.lines() {
if !line.starts_with("#![allow") {
writeln!(out, "{}", line)?;
}
}
}
println!("cargo:rerun-if-changed=grammars/{}", file_name);
Ok(())
}