107 lines
2.6 KiB
Rust
107 lines
2.6 KiB
Rust
mod grammar;
|
|
|
|
use debug2::dbg;
|
|
|
|
#[derive(Debug, debug2::Debug, PartialEq)]
|
|
pub enum Tree {
|
|
Val(f64),
|
|
Add(Vec<Tree>),
|
|
Sub(Vec<Tree>),
|
|
Mul(Vec<Tree>),
|
|
Div(Vec<Tree>),
|
|
}
|
|
|
|
use rustyline::validate::{
|
|
MatchingBracketValidator, ValidationContext, ValidationResult, Validator,
|
|
};
|
|
use rustyline::{Editor, Result};
|
|
use rustyline_derive::{Completer, Helper, Highlighter, Hinter};
|
|
|
|
#[derive(Completer, Helper, Highlighter, Hinter)]
|
|
struct InputValidator {
|
|
brackets: MatchingBracketValidator,
|
|
}
|
|
|
|
impl Validator for InputValidator {
|
|
fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
|
|
self.brackets.validate(ctx)
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
// let src = std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap();
|
|
|
|
// let tree = grammar::TreeParser::new().parse(&src);
|
|
|
|
// let t = dbg!(tree.unwrap());
|
|
|
|
// println!("{}", eval(&t));
|
|
|
|
let mut rl = Editor::new();
|
|
rl.set_helper(Some(InputValidator {
|
|
brackets: MatchingBracketValidator::new(),
|
|
}));
|
|
while let Ok(line) = rl.readline("> ") {
|
|
rl.add_history_entry(&line);
|
|
|
|
let tree = grammar::TreeParser::new().parse(&line).unwrap();
|
|
dbg!(&tree);
|
|
println!("< {}", eval(&tree))
|
|
}
|
|
}
|
|
|
|
fn eval(t: &Tree) -> f64 {
|
|
match t {
|
|
Tree::Val(v) => *v,
|
|
Tree::Add(vs) => vs.iter().map(eval).sum(),
|
|
Tree::Mul(vs) => vs.iter().map(eval).product(),
|
|
Tree::Sub(vs) => eval(&vs[0]) - vs[1..].iter().map(eval).sum::<f64>(),
|
|
Tree::Div(vs) => eval(&vs[0]) / vs[1..].iter().map(eval).product::<f64>(),
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn simple_math_space() {
|
|
let t = grammar::TreeParser::new()
|
|
.parse("( + 1 2 ( / 2 3 4 5) )")
|
|
.unwrap();
|
|
assert_eq!(
|
|
t,
|
|
Tree::Add(vec![
|
|
Tree::Val(1.0),
|
|
Tree::Val(2.0),
|
|
Tree::Div(vec![
|
|
Tree::Val(2.0),
|
|
Tree::Val(3.0),
|
|
Tree::Val(4.0),
|
|
Tree::Val(5.0),
|
|
])
|
|
])
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn simple_math_dence() {
|
|
let t = grammar::TreeParser::new()
|
|
.parse("(+ 1 2 (/ 2 3 4 5))")
|
|
.unwrap();
|
|
assert_eq!(
|
|
t,
|
|
Tree::Add(vec![
|
|
Tree::Val(1.0),
|
|
Tree::Val(2.0),
|
|
Tree::Div(vec![
|
|
Tree::Val(2.0),
|
|
Tree::Val(3.0),
|
|
Tree::Val(4.0),
|
|
Tree::Val(5.0),
|
|
])
|
|
])
|
|
);
|
|
}
|
|
}
|