Clean up main.rs some, add preprocessor
* Preprocessor uses an LRPAR generated lexer and a custom parser to filter comments and set defines. Includes and conditional compilation will come next. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
81
src/main.rs
81
src/main.rs
@@ -5,7 +5,7 @@ mod vm;
|
||||
|
||||
use structopt::StructOpt;
|
||||
use snafu::Snafu;
|
||||
use std::{fs, io::{stdin, stdout, Write, Read}, process, path::PathBuf};
|
||||
use std::{fs, io::{stdin, stdout, Write, Read}, path::{Path, PathBuf}, process};
|
||||
|
||||
const DEFAULT_MAX_MEM: usize = 64 * 1024 * 1024;
|
||||
|
||||
@@ -69,39 +69,77 @@ struct Options {
|
||||
#[structopt(long, parse(try_from_str = from_bytes_size))]
|
||||
max_mem: Option<usize>,
|
||||
|
||||
/// Whether to compile the input file to an object.
|
||||
#[structopt(short, long)]
|
||||
compile: bool,
|
||||
|
||||
/// The output file for compiled files.
|
||||
/// The output file for generated files (preprocessed, compiled, etc).
|
||||
///
|
||||
/// If not supplied, a name will be inferred from the input file. Supplying - for the path will
|
||||
/// output to STDOUT.
|
||||
#[structopt(short = "o", long)]
|
||||
compile_out: Option<PathBuf>
|
||||
out: Option<PathBuf>,
|
||||
|
||||
/// Only run the preprocessor.
|
||||
#[structopt(short = "E", long)]
|
||||
preprocess_only: bool,
|
||||
|
||||
/// Only compile the input file to an object.
|
||||
#[structopt(short = "c", long)]
|
||||
compile_only: bool,
|
||||
|
||||
}
|
||||
|
||||
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||
|
||||
fn get_reader(path: impl AsRef<Path>) -> Result<Box<dyn Read>> {
|
||||
if let Some("-") = path.as_ref().to_str() {
|
||||
Ok(Box::new(stdin()))
|
||||
} else {
|
||||
Ok(Box::new(fs::File::open(path.as_ref())?))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_writer(path: impl AsRef<Path>) -> Result<Box<dyn Write>> {
|
||||
if let Some("-") = path.as_ref().to_str() {
|
||||
Ok(Box::new(stdout()))
|
||||
} else {
|
||||
Ok(Box::new(fs::File::create(path.as_ref())?))
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
use vm::{
|
||||
state::State,
|
||||
obj::{
|
||||
assemble::{Asm, Assemble},
|
||||
syn::{lexer, parser},
|
||||
syn::{lexer, parser, preprocessor},
|
||||
}
|
||||
};
|
||||
|
||||
// get the object either from reading it, or from parsing an assembly file
|
||||
let opt = Options::from_args();
|
||||
let text = if Some("-") == opt.input.to_str() {
|
||||
|
||||
// Load assembler
|
||||
let text = {
|
||||
let mut reader = get_reader(&opt.input)?;
|
||||
let mut text = String::new();
|
||||
let stdin = stdin();
|
||||
stdin.lock().read_to_string(&mut text)?;
|
||||
reader.read_to_string(&mut text)?;
|
||||
text
|
||||
} else {
|
||||
fs::read_to_string(&opt.input)?
|
||||
};
|
||||
|
||||
// Preprocess
|
||||
let text = {
|
||||
preprocessor::preprocess(&text)?
|
||||
};
|
||||
|
||||
// Preprocess only - exit early
|
||||
if opt.preprocess_only {
|
||||
let outfile = opt.out.clone().unwrap_or_else(|| {
|
||||
let mut outfile = opt.input.clone();
|
||||
assert!(outfile.set_extension("pasm"));
|
||||
outfile
|
||||
});
|
||||
let mut writer = get_writer(&outfile)?;
|
||||
writer.write(&text.as_bytes())?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let lexerdef = lexer::lexerdef();
|
||||
let lexer = lexerdef.lexer(&text);
|
||||
let (res, errors) = parser::parse(&lexer);
|
||||
@@ -113,23 +151,20 @@ fn main() -> Result<()> {
|
||||
if !errors.is_empty() {
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let res = res.unwrap();
|
||||
let mut asm = Asm::default();
|
||||
let object = res.assemble(&mut asm)?;
|
||||
if opt.compile {
|
||||
let outfile = opt.compile_out.clone().unwrap_or_else(|| {
|
||||
|
||||
if opt.compile_only {
|
||||
let outfile = opt.out.clone().unwrap_or_else(|| {
|
||||
let mut outfile = opt.input.clone();
|
||||
assert!(outfile.set_extension("obj"));
|
||||
outfile
|
||||
});
|
||||
let bytes = object.to_bytes();
|
||||
if Some("-") == outfile.to_str() {
|
||||
let stdout = stdout();
|
||||
stdout.lock().write(&bytes)?;
|
||||
} else {
|
||||
// write compiled file here
|
||||
fs::write(outfile, &bytes)?;
|
||||
}
|
||||
let mut writer = get_writer(&outfile)?;
|
||||
writer.write(&bytes)?;
|
||||
Ok(())
|
||||
} else {
|
||||
let mut state = State::new();
|
||||
|
||||
Reference in New Issue
Block a user