forked from pku-minic/koopa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.rs
85 lines (78 loc) · 2.24 KB
/
main.rs
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
mod ext_funcs;
mod interpreter;
use interpreter::Interpreter;
use koopa::back::Generator;
use koopa::front::Driver;
use std::io::{sink, stdin, Error};
use std::{env, fmt, process, result};
fn main() {
process::exit(try_main().unwrap_or_else(|e| {
eprintln!("{}", e);
-1
}));
}
fn try_main() -> result::Result<i32, MainError> {
// parse command line arguments
let CommandLineArgs { input, libs } = parse_cmd_args()?;
// parse the input file
let program = if let Some(file) = input {
Driver::from_path(file)
.map_err(MainError::InvalidFile)?
.generate_program()
} else {
Driver::from(stdin()).generate_program()
}
.map_err(|_| MainError::ParseError)?;
// interpret the program
let interpreter = Interpreter::new(libs);
Generator::with_visitor(sink(), interpreter)
.generate_on(&program)
.map_err(MainError::OtherError)
}
enum MainError {
InvalidArgs,
InvalidFile(Error),
ParseError,
OtherError(Error),
}
impl fmt::Display for MainError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
MainError::InvalidArgs => write!(
f,
r#"Usage: interpreter [FILE] [-l DYN_LIB ...]
Options:
FILE use FILE as input instead of stdin
-l DYN_LIB load dynamic library DYN_LIB"#
),
MainError::InvalidFile(error) => write!(f, "invalid file operation: {}", error),
MainError::ParseError => write!(f, "error occurred when parsing the input"),
MainError::OtherError(error) => write!(f, "{}", error),
}
}
}
#[derive(Default)]
struct CommandLineArgs {
input: Option<String>,
libs: Vec<String>,
}
fn parse_cmd_args() -> result::Result<CommandLineArgs, MainError> {
let mut cmd_args = CommandLineArgs::default();
let mut args = env::args();
args.next();
loop {
match (args.next(), args.next()) {
(Some(file), Some(o)) if file != "-l" && o == "-l" => {
cmd_args.input = Some(file);
cmd_args
.libs
.push(args.next().ok_or(MainError::InvalidArgs)?);
}
(Some(file), _) if file != "-l" => cmd_args.input = Some(file),
(Some(o), Some(lib)) if o == "-l" => cmd_args.libs.push(lib),
(None, None) => break,
_ => return Err(MainError::InvalidArgs),
}
}
Ok(cmd_args)
}