aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.rs
blob: 9a025b9811221f821f26e0fcd7655a95e7acd84d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

use std::io;
use std::env;
use std::io::Write;
use std::path::Path;

mod sexpr;
mod cexpr;

use cexpr::CExpr;

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;
        }
        let expr = match CExpr::from_str(&raw_input) {
            Ok(expr) => expr,
            Err(e) => {
                println!("error: {}", e);
                continue;
            }
        };
        println!("{}", expr);
    }
}

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);
    }
}