diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..6b2bc57 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,115 @@ + +use std::io; +use std::env; +use std::io::Write; +use std::path::Path; + +mod sexpr; + +fn repl(verbose: bool) { + + let stdin = io::stdin(); + let mut stdout = io::stdout(); + + loop { + let raw_input = &mut String::new(); + stdout.write(b"\ncasual> ").unwrap(); + stdout.flush().unwrap(); + stdin.read_line(raw_input).unwrap(); + let raw_input = raw_input; // mutable to immutable reference + if raw_input.len() == 0 { + // end-of-line, aka Ctrl-D. Blank line will still have newline char + stdout.write(b"\nCiao!\n").unwrap(); + return; + } + // TODO: use debug or something instead of "verbose"? + let tokens = match sexpr::sexpr_tokenize(&raw_input) { + Ok(tokens) => { + if verbose { println!("Tokens: {}", tokens.join(", ")); }; + tokens + }, + Err(e) => { + println!("couldn't tokenize: {}", e); + continue; + } + }; + let ast = match sexpr::sexpr_parse(&tokens, 0) { + Ok((mut ast_list, _)) => { + if verbose { + for ast in &ast_list { + println!("AST: {}", sexpr::sexpr_repr(ast).unwrap()); + }; + }; + // We're a REPL, so only one expression at a time + if ast_list.len() > 1 { + println!("one expression at a time on the REPL, please!"); + continue; + } else if ast_list.len() == 0 { + sexpr::SExpr::SNull + } else { + let ast = ast_list.pop().unwrap(); + ast + } + }, + Err(e) => { + println!("couldn't parse: {}", e); + continue; + } + }; + println!("{}", sexpr::sexpr_repr(&ast).unwrap()); + } +} + +fn usage() { + println!("usage:\tcasual [-h] [-v] [--no-repl] [<files>]"); + println!(""); + println!("Files will be loaded in order, then drop to REPL (unless \"--no-repl\" is passed)."); + println!("Verbose flag (\"-v\") will result in lexed tokens and parsed AST \ + being dumped to stdout (when on REPL)."); +} + +fn main() { + + let mut verbose: bool = false; + let mut no_repl: bool = false; + + let mut file_list = Vec::<String>::new(); + + for arg in env::args().skip(1) { + match &*arg { + "-v" | "--verbose" => { verbose = true; }, + "--no-repl" => { no_repl = true; }, + "-h" | "--help" => { usage(); return; }, + _ if arg.starts_with("-") => { + println!("Unknown option: {}", arg); + println!(""); + usage(); + return; + }, + _ => { + file_list.push(arg.clone()); + } + } + } + + for fname in file_list { + let fpath = Path::new(&fname); + if !fpath.is_file() { + println!("File not found (or not file): {}", fname); + return; + } + println!("Loading {}...", fname); + match sexpr::sexpr_parse_file(&fpath) { + Err(e) => { + println!("Error loading file: {}\n {}", fname, e); + return; + }, + Ok(_) => () + } + } + + if !no_repl { + repl(verbose); + } +} + |