handball/src/main.rs

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