Added batch processing mode
This commit is contained in:
parent
554a83a63c
commit
c62039dfdf
5 changed files with 155 additions and 42 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -737,6 +737,7 @@ dependencies = [
|
|||
"tokio",
|
||||
"tower-lsp",
|
||||
"unicode-segmentation",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -36,3 +36,4 @@ tokio = { version = "1.38.1", features = ["macros", "rt-multi-thread", "io-std"]
|
|||
|
||||
tower-lsp = "0.20.0"
|
||||
unicode-segmentation = "1.11.0"
|
||||
walkdir = "2.5.0"
|
||||
|
|
|
@ -18,6 +18,7 @@ pub enum Target {
|
|||
pub struct Compiler {
|
||||
target: Target,
|
||||
cache: Option<RefCell<Connection>>,
|
||||
// TODO:
|
||||
reference_count: RefCell<HashMap<String, HashMap<String, usize>>>,
|
||||
}
|
||||
|
||||
|
|
192
src/main.rs
192
src/main.rs
|
@ -7,18 +7,20 @@ mod lua;
|
|||
mod parser;
|
||||
|
||||
use std::env;
|
||||
use std::process::ExitCode;
|
||||
use std::rc::Rc;
|
||||
|
||||
use compiler::compiler::Compiler;
|
||||
use getopts::Options;
|
||||
use parser::langparser::LangParser;
|
||||
use parser::parser::Parser;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use crate::parser::source::SourceFile;
|
||||
extern crate getopts;
|
||||
|
||||
fn print_usage(program: &str, opts: Options) {
|
||||
let brief = format!("Usage: {} -i FILE [options]", program);
|
||||
let brief = format!("Usage: {} -i PATH -o PATH [options]", program);
|
||||
print!("{}", opts.usage(&brief));
|
||||
}
|
||||
|
||||
|
@ -36,42 +38,15 @@ NML version: 0.4\n"
|
|||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let program = args[0].clone();
|
||||
|
||||
let mut opts = Options::new();
|
||||
opts.optopt("i", "", "Input file", "FILE");
|
||||
opts.optopt("d", "database", "Cache database location", "PATH");
|
||||
opts.optmulti("z", "debug", "Debug options", "OPTS");
|
||||
opts.optflag("h", "help", "Print this help menu");
|
||||
opts.optflag("v", "version", "Print program version and licenses");
|
||||
|
||||
let matches = match opts.parse(&args[1..]) {
|
||||
Ok(m) => m,
|
||||
Err(f) => {
|
||||
panic!("{}", f.to_string())
|
||||
}
|
||||
};
|
||||
if matches.opt_present("v") {
|
||||
print_version();
|
||||
return;
|
||||
}
|
||||
if matches.opt_present("h") {
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
if !matches.opt_present("i") {
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
|
||||
let input = matches.opt_str("i").unwrap();
|
||||
let debug_opts = matches.opt_strs("z");
|
||||
let db_path = matches.opt_str("d");
|
||||
|
||||
let parser = LangParser::default();
|
||||
|
||||
fn process(
|
||||
parser: &LangParser,
|
||||
db_path: &Option<String>,
|
||||
input: &String,
|
||||
output: &String,
|
||||
debug_opts: &Vec<String>,
|
||||
multi_mode: bool,
|
||||
) -> bool {
|
||||
println!("Processing {input}...");
|
||||
// Parse
|
||||
let source = SourceFile::new(input.to_string(), None).unwrap();
|
||||
let doc = parser.parse(Rc::new(source), None);
|
||||
|
@ -104,11 +79,146 @@ fn main() {
|
|||
|
||||
if parser.has_error() {
|
||||
println!("Compilation aborted due to errors while parsing");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
let compiler = Compiler::new(compiler::compiler::Target::HTML, db_path);
|
||||
let out = compiler.compile(doc.as_ref());
|
||||
let compiler = Compiler::new(compiler::compiler::Target::HTML, db_path.clone());
|
||||
|
||||
std::fs::write("a.html", out).unwrap();
|
||||
// Get output from file
|
||||
if multi_mode {
|
||||
let out_file = match doc.get_variable("compiler.output") {
|
||||
None => {
|
||||
eprintln!("Missing required variable `compiler.output` for multifile mode");
|
||||
return false;
|
||||
}
|
||||
Some(var) => output.clone() + "/" + var.to_string().as_str(),
|
||||
};
|
||||
|
||||
let out = compiler.compile(doc.as_ref());
|
||||
std::fs::write(out_file, out).is_ok()
|
||||
} else {
|
||||
let out = compiler.compile(doc.as_ref());
|
||||
std::fs::write(output, out).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> ExitCode {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let program = args[0].clone();
|
||||
|
||||
let mut opts = Options::new();
|
||||
opts.optopt("i", "input", "Input path", "PATH");
|
||||
opts.optopt("o", "output", "Output path", "PATH");
|
||||
opts.optopt("d", "database", "Cache database location", "PATH");
|
||||
opts.optmulti("z", "debug", "Debug options", "OPTS");
|
||||
opts.optflag("h", "help", "Print this help menu");
|
||||
opts.optflag("v", "version", "Print program version and licenses");
|
||||
|
||||
let matches = match opts.parse(&args[1..]) {
|
||||
Ok(m) => m,
|
||||
Err(f) => {
|
||||
panic!("{}", f.to_string())
|
||||
}
|
||||
};
|
||||
if matches.opt_present("v") {
|
||||
print_version();
|
||||
return ExitCode::SUCCESS;
|
||||
}
|
||||
if matches.opt_present("h") {
|
||||
print_usage(&program, opts);
|
||||
return ExitCode::SUCCESS;
|
||||
}
|
||||
if !matches.opt_present("i") || !matches.opt_present("o") {
|
||||
print_usage(&program, opts);
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
|
||||
let input = matches.opt_str("i").unwrap();
|
||||
let input_meta = match std::fs::metadata(&input) {
|
||||
Ok(meta) => meta,
|
||||
Err(e) => {
|
||||
eprintln!("Unable to get metadata for input: `{input}`");
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
};
|
||||
let output = matches.opt_str("o").unwrap();
|
||||
if input_meta.is_dir() {
|
||||
// Create ouput directories
|
||||
if !std::fs::exists(&output).unwrap_or(false) {
|
||||
match std::fs::create_dir_all(&output) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
eprintln!("Unable to create output directory `{output}`: {err}");
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
match std::fs::metadata(&output) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
eprintln!("Unable to get metadata for output: `{output}`");
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let debug_opts = matches.opt_strs("z");
|
||||
let db_path = matches.opt_str("d");
|
||||
let parser = LangParser::default();
|
||||
|
||||
if input_meta.is_dir() {
|
||||
if db_path.is_none() {
|
||||
eprintln!("Please specify a database (-d) for directory mode.");
|
||||
}
|
||||
|
||||
let input_it = match std::fs::read_dir(&input) {
|
||||
Ok(it) => it,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to read input directory `{input}`: {e}");
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
};
|
||||
|
||||
for entry in WalkDir::new(&input) {
|
||||
if let Err(err) = entry {
|
||||
eprintln!("Failed to recursively walk over input directory: {err}");
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
match entry.as_ref().unwrap().metadata() {
|
||||
Ok(meta) => {
|
||||
if !meta.is_file() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Faield to get metadata for `{entry:#?}`");
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
let path = match entry.as_ref().unwrap().path().to_str() {
|
||||
Some(path) => path.to_string(),
|
||||
None => {
|
||||
eprintln!("Faield to convert input file `{entry:#?}` to UTF-8");
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
};
|
||||
if !path.ends_with(".nml") {
|
||||
println!("Skipping '{path}'");
|
||||
continue;
|
||||
}
|
||||
|
||||
if !process(&parser, &db_path, &path, &output, &debug_opts, true) {
|
||||
eprintln!("Processing aborted");
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !process(&parser, &db_path, &input, &output, &debug_opts, false) {
|
||||
eprintln!("Processing aborted");
|
||||
return ExitCode::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return ExitCode::SUCCESS;
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ impl Parser for LangParser {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
paragraph.push(elem);
|
||||
paragraph.push(elem).unwrap();
|
||||
} else {
|
||||
// Process paragraph events
|
||||
if doc.last_element::<Paragraph>().is_some_and(|_| true) {
|
||||
|
|
Loading…
Reference in a new issue