feat(main): add args parse and exec process
This commit is contained in:
@@ -255,7 +255,7 @@ impl Parser {
|
||||
}
|
||||
self.advance(1);
|
||||
let mut statements = vec![];
|
||||
println!("parse block stmt");
|
||||
// println!("parse block stmt");
|
||||
loop {
|
||||
if self.peek().is_none() {
|
||||
let span = self.next().unwrap().span;
|
||||
@@ -282,7 +282,7 @@ impl Parser {
|
||||
// parse statement here
|
||||
statements.push(self.parse_stmt()?);
|
||||
}
|
||||
println!("finish parse block stmt");
|
||||
// println!("finish parse block stmt");
|
||||
let end_span = statements.last().map(|s| s.span()).unwrap_or(start_span);
|
||||
Some(BlockStmt {
|
||||
statements,
|
||||
|
||||
+3
-1
@@ -28,7 +28,9 @@ impl Generator {
|
||||
pub fn emit(&mut self, compile_unit: CompileUnit) -> Vec<IRInstr> {
|
||||
self.generate_compile_unit(compile_unit)
|
||||
}
|
||||
|
||||
pub fn get_diagnostics(&self) -> &Diagnositics {
|
||||
&self.diagnostic
|
||||
}
|
||||
fn generate_compile_unit(&mut self, compile_unit: CompileUnit) -> Vec<IRInstr> {
|
||||
let mut instrs = vec![];
|
||||
use GlobalDeclStmt::*;
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
mod generator;
|
||||
pub mod generator;
|
||||
pub mod types;
|
||||
pub mod err;
|
||||
+81
-2
@@ -4,6 +4,85 @@ mod ir;
|
||||
mod utils;
|
||||
mod diagnostic;
|
||||
mod err;
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
|
||||
use std::{fs::File, io::BufRead};
|
||||
|
||||
use clap::Parser as ArgParser;
|
||||
|
||||
use crate::{frontend::{lexer::Lexer, parser::Parser}, ir::generator::Generator};
|
||||
|
||||
/// Simple minic compiler built by Rust
|
||||
#[derive(ArgParser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct Args {
|
||||
/// Output the generated IR code
|
||||
#[arg(short = 'I', long = "ir")]
|
||||
output_ir: bool,
|
||||
/// Use recursive descent parsing
|
||||
#[arg(short = 'D', long = "recursive-descent")]
|
||||
recursive_descent: bool,
|
||||
/// Useless paramter
|
||||
#[arg(short = 'S', long = "symbol")]
|
||||
_useless: bool,
|
||||
/// Output file for the generated code (default: stdout)
|
||||
#[arg(short = 'o', long = "output")]
|
||||
output: Option<String>,
|
||||
/// Source file to compile
|
||||
source: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
if !args.output_ir {
|
||||
eprintln!("Currently only IR generation is supported. Use -I to enable it.");
|
||||
return;
|
||||
}
|
||||
if !args.recursive_descent {
|
||||
eprintln!("Currently only recursive descent parsing is supported. Use -D to enable it.");
|
||||
return;
|
||||
}
|
||||
let source_path = std::path::Path::new(&args.source);
|
||||
let file = match File::open(&args.source) {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to open source file {}: {}", args.source, e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let mut buf_reader = std::io::BufReader::new(file);
|
||||
let mut lexer = Lexer::new();
|
||||
let mut full_text = String::new();
|
||||
loop {
|
||||
let mut line = String::new();
|
||||
let bytes_read = buf_reader.read_line(&mut line).unwrap();
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
}
|
||||
full_text.push_str(&line);
|
||||
lexer.parse_next_str(&line);
|
||||
}
|
||||
let (tokens, diagnostics) = lexer.finish();
|
||||
if !diagnostics.is_empty() {
|
||||
diagnostics.print(&format!("{}", source_path.display()), &full_text);
|
||||
}
|
||||
let mut parser = Parser::new(tokens, diagnostics);
|
||||
let compile_unit = parser.parse();
|
||||
if !parser.diagnostics.is_empty() {
|
||||
parser.diagnostics.print(&format!("{}", source_path.display()), &full_text);
|
||||
}
|
||||
let mut generator = Generator::new();
|
||||
let ir = generator.emit(compile_unit);
|
||||
if !generator.get_diagnostics().is_empty() {
|
||||
generator.get_diagnostics().print(&format!("{}", source_path.display()), &full_text);
|
||||
}
|
||||
if let Some(output_path) = args.output {
|
||||
match std::fs::write(&output_path, ir.iter().map(|instr| instr.to_string()).collect::<Vec<_>>().join("\n")) {
|
||||
Ok(_) => println!("IR code written to {}", output_path),
|
||||
Err(e) => eprintln!("Failed to write IR code to {}: {}", output_path, e),
|
||||
}
|
||||
} else {
|
||||
for instr in ir {
|
||||
println!("{}", instr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user