use std::fs::File; use std::io::Write; use anyhow::{Context, Result}; use string_builder::Builder; use structopt::StructOpt; extern crate pest; #[macro_use] extern crate pest_derive; use pest::iterators::Pair; use pest::Parser; #[derive(Parser)] #[grammar = "grammars/mblf.pest"] struct MblfParser; #[derive(StructOpt)] struct Cli { #[structopt(parse(from_os_str))] input_file: std::path::PathBuf, #[structopt(parse(from_os_str))] output_file: std::path::PathBuf, } fn instruct(statement: Pair, out: &mut Builder) { match statement.as_rule() { Rule::instruction => { for nested_statement in statement.into_inner() { instruct(nested_statement, out); } out.append("\n"); } Rule::operator => { out.append("operator "); } Rule::operand => { out.append("operand "); } Rule::loopBlock => { for nested_statement in statement.into_inner() { instruct(nested_statement, out); } } Rule::loopBlockStart => { out.append("loopBlockStart\n"); } Rule::loopBlockEnd => { out.append("loopBlockEnd\n"); } Rule::EOI => { out.append("\n"); } _ => unreachable!(), } } fn main() -> Result<(), Box> { let args = Cli::from_args(); let content = std::fs::read_to_string(&args.input_file) .with_context(|| format!("could not read source file {:?}", args.input_file))?; let mut builder = Builder::default(); let parsed_file = MblfParser::parse(Rule::file, &content) .expect("Parse Error") .next() .unwrap(); for statement in parsed_file.into_inner() { instruct(statement, &mut builder); } let bf = builder.string().unwrap(); let mut out = File::create(args.output_file)?; out.write(bf.as_bytes())?; out.sync_all()?; Ok(()) }