use abol_codegen::Generator;
use abol_parser::{FileOpener, dictionary::Dictionary};
use anyhow::{Context, Result};
use clap::Parser;
use std::{fs, path::PathBuf};
#[derive(Parser)]
struct Args {
#[arg(short, long, required = true)]
inputs: Vec<PathBuf>,
#[arg(short, long)]
output: PathBuf,
#[arg(short, long)]
name: String,
#[arg(long, default_value_t = false)]
ignore_identical_attributes: bool,
}
fn main() -> Result<()> {
let args = Args::parse();
let mut final_dict = Dictionary::default();
for input_path in &args.inputs {
let root = input_path.parent().context(format!(
"Could not determine parent directory of {:?}",
input_path
))?;
let file_name = input_path
.file_name()
.context(format!("Could not determine filename of {:?}", input_path))?;
let file_opener = FileOpener::new(root);
let parser = abol_parser::Parser::new(file_opener, args.ignore_identical_attributes);
println!("Parsing {:?}...", input_path);
let next_dict = parser
.parse_dictionary(file_name)
.with_context(|| format!("Failed to parse dictionary file {:?}", input_path))?;
final_dict = Dictionary::merge(&final_dict, &next_dict)
.map_err(|e| anyhow::anyhow!("Merge conflict in {:?}: {}", input_path, e))?;
}
let generator = Generator::new(&args.name);
let code = generator
.generate(&final_dict)
.map_err(|e| anyhow::anyhow!("Code generation failed: {}", e))?;
let mut final_output_path = args.output;
if final_output_path.is_dir() {
let final_name = format!("{}.rs", args.name.to_lowercase());
final_output_path.push(final_name);
}
if let Some(parent) = final_output_path.parent() {
fs::create_dir_all(parent).with_context(|| {
format!(
"Failed to create directories for output file {:?}",
final_output_path
)
})?;
}
fs::write(&final_output_path, code)
.with_context(|| format!("Failed to write output file {:?}", final_output_path))?;
println!(
"Successfully merged {} files and generated Rust code at {:?}",
args.inputs.len(),
final_output_path
);
Ok(())
}