mod grammar; use debug2::dbg; #[derive(Debug, debug2::Debug, PartialEq)] pub enum Tree { Val(f64), Add(Vec), Sub(Vec), Mul(Vec), Div(Vec), } 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 { 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::(), Tree::Div(vs) => eval(&vs[0]) / vs[1..].iter().map(eval).product::(), } } #[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), ]) ]) ); } }