feat: 重构main函数,添加run_file和run_repl函数以支持从文件和REPL读取输入
This commit is contained in:
+73
-32
@@ -9,45 +9,86 @@ use parser::Parser;
|
|||||||
use interpreter::Interpreter;
|
use interpreter::Interpreter;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::{self, Read};
|
use std::io::Write;
|
||||||
|
use std::io::stdin;
|
||||||
fn main() {
|
use std::io::stdout;
|
||||||
let src = match env::args().len() {
|
|
||||||
1 => {
|
|
||||||
// 无参数:从 stdin 读取
|
|
||||||
let mut buf = String::new();
|
|
||||||
if let Err(e) = io::stdin().read_to_string(&mut buf) {
|
|
||||||
eprintln!("Failed to read stdin: {}", e);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
2 => {
|
|
||||||
// 一个参数:作为文件路径
|
|
||||||
let path = env::args().nth(1).unwrap();
|
|
||||||
match fs::read_to_string(&path) {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Failed to read file '{}': {}", path, e);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
eprintln!("Usage: aster [script_file]");
|
|
||||||
eprintln!(" aster - run from stdin");
|
|
||||||
eprintln!(" aster <file> - run script file");
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
fn run_file(src: String) {
|
||||||
let tokens = Lexer::new(&src).tokenize();
|
let tokens = Lexer::new(&src).tokenize();
|
||||||
let mut parser = Parser::new(tokens);
|
let mut parser = Parser::new(tokens);
|
||||||
let stmts = parser.parse();
|
let stmts = parser.parse();
|
||||||
|
|
||||||
let mut interpreter = Interpreter::new();
|
let mut interpreter = Interpreter::new();
|
||||||
if let Err(e) = interpreter.interpret(stmts) {
|
if let Err(e) = interpreter.interpret(stmts) {
|
||||||
eprintln!("{}", e);
|
eprintln!("Error: {}", e);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run_repl() {
|
||||||
|
println!("Welcome to Aster REPL!");
|
||||||
|
println!("Type ':exit' to quit.");
|
||||||
|
println!("Type ':reset' to reset the interpreter state.");
|
||||||
|
|
||||||
|
let mut interpreter = Interpreter::new();
|
||||||
|
let mut line = String::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
print!(">>> ");
|
||||||
|
stdout().flush().unwrap();
|
||||||
|
|
||||||
|
line.clear();
|
||||||
|
if let Err(e) = stdin().read_line(&mut line) {
|
||||||
|
eprintln!("Error reading input: {}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let line = line.trim();
|
||||||
|
if line.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match line {
|
||||||
|
":exit" => {
|
||||||
|
println!("Goodbye!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
":reset" => {
|
||||||
|
interpreter = Interpreter::new();
|
||||||
|
println!("Interpreter reset.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let tokens = Lexer::new(line).tokenize();
|
||||||
|
let mut parser = Parser::new(tokens);
|
||||||
|
let stmts = parser.parse();
|
||||||
|
|
||||||
|
if let Err(e) = interpreter.interpret(stmts) {
|
||||||
|
eprintln!("Error: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
|
||||||
|
match args.len() {
|
||||||
|
1 => run_repl(),
|
||||||
|
2 => {
|
||||||
|
let filename = &args[1];
|
||||||
|
match fs::read_to_string(filename) {
|
||||||
|
Ok(src) => run_file(src),
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error reading file '{}': {}", filename, e);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
eprintln!("Usage: aster [script]");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user