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
#[cfg(test)]
mod test;
mod diagnostics;
use diagnostics::emit_slide_diagnostics;
use libslide::diagnostics::Diagnostic;
use libslide::scanner::ScanResult;
use libslide::{
evaluate, parse_expression, parse_expression_pattern, scan, EvaluatorContext, Grammar,
};
pub struct Opts {
pub program: String,
pub output_form: OutputForm,
pub parse_only: bool,
pub expr_pat: bool,
pub no_emit: bool,
}
#[derive(Copy, Clone)]
pub enum OutputForm {
Pretty,
SExpression,
Debug,
}
pub fn run_slide(opts: Opts) -> i32 {
let output_form = opts.output_form;
let file = None;
let program = opts.program;
let emit = !opts.no_emit;
let emit_diagnostics = |diagnostics: Vec<Diagnostic>| {
if emit {
emit_slide_diagnostics(file, program.clone(), diagnostics);
}
1
};
let emit_tree = move |obj: &dyn Grammar| {
if emit {
println!("{}", print(obj, output_form));
}
0
};
let ScanResult {
tokens,
diagnostics,
} = scan(&*program);
if !diagnostics.is_empty() {
return emit_diagnostics(diagnostics);
}
if opts.expr_pat {
let (parse_tree, diagnostics) = parse_expression_pattern(tokens);
if !diagnostics.is_empty() {
return emit_diagnostics(diagnostics);
}
if opts.parse_only {
return emit_tree(&parse_tree);
}
unreachable!();
}
let (parse_tree, diagnostics) = parse_expression(tokens);
if !diagnostics.is_empty() {
return emit_diagnostics(diagnostics);
}
if opts.parse_only {
return emit_tree(&parse_tree);
}
let simplified = evaluate(parse_tree, EvaluatorContext::default()).unwrap();
emit_tree(&simplified)
}
fn print(obj: &dyn Grammar, output_form: OutputForm) -> String {
match output_form {
OutputForm::Pretty => obj.to_string(),
OutputForm::SExpression => obj.s_form(),
OutputForm::Debug => format!("{:#?}", obj),
}
}