aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs115
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);
+ }
+}
+