use clap::Parser; use crftng_intrprtrs::{exec, lex, parse}; use std::path::PathBuf; use std::{fs, io}; use tracing::Level; use tracing_subscriber::{EnvFilter, FmtSubscriber}; #[derive(Parser, Debug)] struct Args { #[clap(parse(from_os_str))] file: Option, #[clap(short)] dump_ast: bool, #[clap(short)] no_run: bool, } fn run(code: &str, args: &Args) { let src_file = args.file.as_ref().map(|f| f.to_string_lossy().to_string()); let tokens = match lex(code, src_file.as_deref()) { Ok(v) => v, Err(e) => { for error in e { println!("{}", error); } return; } }; let ast = match parse(tokens) { Ok(v) => v, Err(e) => { for error in e { println!("{}", error); } return; } }; if args.dump_ast { for node in &ast { println!("{:?}", node); } } if !args.no_run { println!("{:?}", exec(ast)); } } fn run_file(args: &Args) -> Result<(), io::Error> { let src = fs::read_to_string(args.file.as_ref().unwrap())?; run(&src, args); Ok(()) } fn run_repl(args: &Args) { assert!(args.file.is_none()); let mut line_buf = String::new(); loop { match io::stdin().read_line(&mut line_buf) { Ok(n) => { // Check for EOF if n == 0 { break; } let line = line_buf.trim(); if !line.is_empty() { run(&line_buf, args); line_buf.clear(); } } Err(e) => panic!("{:?}", e), } } } fn main() { dotenv::dotenv().ok(); color_eyre::install().expect("Failed to install color-eyre"); let subscriber = FmtSubscriber::builder() .with_max_level(Level::TRACE) .with_env_filter(EnvFilter::from_env("LOG")) .finish(); tracing::subscriber::set_global_default(subscriber).unwrap(); let args = Args::parse(); if args.file.is_some() { run_file(&args).unwrap(); } else { run_repl(&args) } }