use clap::{Arg, Command};
use mortar_compiler::{FileHandler, Language, ParseHandler, Serializer};
use std::process;
mod i18n;
use i18n::{Language as CliLanguage, get_text};
fn cli_language_to_compiler_language(lang: CliLanguage) -> Language {
match lang {
CliLanguage::English => Language::English,
CliLanguage::Chinese => Language::Chinese,
}
}
fn build_command(language: CliLanguage) -> Command {
Command::new("mortar")
.version("0.1.0")
.author("Bli-AIk <haikun2333@gmail.com>")
.about(get_text("app_about", language))
.arg(
Arg::new("input")
.help(get_text("input_help", language))
.required(true)
.index(1),
)
.arg(
Arg::new("output")
.short('o')
.long("output")
.value_name("FILE")
.help(get_text("output_help", language)),
)
.arg(
Arg::new("pretty")
.short('p')
.long("pretty")
.action(clap::ArgAction::SetTrue)
.help(get_text("pretty_help", language)),
)
.arg(
Arg::new("verbose-lexer")
.short('v')
.long("verbose-lexer")
.action(clap::ArgAction::SetTrue)
.help(get_text("verbose_lexer_help", language)),
)
.arg(
Arg::new("show-source")
.short('s')
.long("show-source")
.action(clap::ArgAction::SetTrue)
.help(get_text("show_source_help", language)),
)
.arg(
Arg::new("check-only")
.short('c')
.long("check")
.action(clap::ArgAction::SetTrue)
.help(get_text("check_only_help", language)),
)
.arg(
Arg::new("lang")
.short('L')
.long("lang")
.value_name("LANGUAGE")
.help(get_text("language_help", language)),
)
}
fn main() {
let args: Vec<String> = std::env::args().collect();
let language = if let Some(pos) = args.iter().position(|arg| arg == "--lang" || arg == "-L") {
if let Some(lang_str) = args.get(pos + 1) {
CliLanguage::from_str(lang_str).unwrap_or(CliLanguage::from_env())
} else {
CliLanguage::from_env()
}
} else {
CliLanguage::from_env()
};
let matches = build_command(language).get_matches();
let input_path = matches.get_one::<String>("input").unwrap();
let pretty = matches.get_flag("pretty");
let verbose_lexer = matches.get_flag("verbose-lexer");
let show_source = matches.get_flag("show-source");
let check_only = matches.get_flag("check-only");
let content = match FileHandler::read_source_file(input_path) {
Ok(content) => content,
Err(err) => {
eprintln!("{} {}", get_text("error_reading_file", language), err);
process::exit(1);
}
};
if show_source {
println!("{}", get_text("original_source", language));
println!("{}", content);
println!("{}", get_text("end_source", language));
println!();
}
let compiler_language = cli_language_to_compiler_language(language);
let (parse_result, diagnostics) = ParseHandler::parse_source_code_with_diagnostics_and_language(
&content,
input_path.clone(),
verbose_lexer,
compiler_language,
);
diagnostics.print_diagnostics(&content);
if diagnostics.has_errors() {
eprintln!("\n{}", get_text("compilation_failed", language));
process::exit(1);
}
let program = match parse_result {
Ok(program) => program,
Err(_) => {
process::exit(1);
}
};
println!("{}", get_text("parsed_successfully", language));
if !check_only {
let output_path = matches
.get_one::<String>("output")
.map(|s| s.as_str())
.unwrap_or(input_path);
match Serializer::save_to_file_with_language(
&program,
output_path,
pretty,
compiler_language,
) {
Ok(()) => println!("{}", get_text("generated_successfully", language)),
Err(err) => {
eprintln!("{} {}", get_text("failed_to_generate", language), err);
process::exit(1);
}
}
}
}
#[cfg(test)]
mod main_tests;