From 7dcee06e99439f14b9916acc85c872ed5480f937 Mon Sep 17 00:00:00 2001 From: Phodal Huang Date: Mon, 7 Nov 2022 22:31:36 +0800 Subject: [PATCH] feat: try compare with exprtk #13 --- extensions/ext-computing/Cargo.toml | 1 + .../ext-computing/src/expr/grammar.pest | 2 +- extensions/ext-computing/src/expr/parser.rs | 22 ++++++++++++++++--- extensions/ext-computing/src/expr/token.rs | 3 +++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/extensions/ext-computing/Cargo.toml b/extensions/ext-computing/Cargo.toml index eed7e94..1d77c6d 100644 --- a/extensions/ext-computing/Cargo.toml +++ b/extensions/ext-computing/Cargo.toml @@ -22,3 +22,4 @@ lazy_static = "1.4.0" actix-web = "4" tokio = { version = "1", features = ["full"] } futures = "0.3.18" +exprtk_rs="0.1.0" diff --git a/extensions/ext-computing/src/expr/grammar.pest b/extensions/ext-computing/src/expr/grammar.pest index 1108fcb..c02d9b1 100644 --- a/extensions/ext-computing/src/expr/grammar.pest +++ b/extensions/ext-computing/src/expr/grammar.pest @@ -3,7 +3,7 @@ program = _{ SOI ~ expr ~ EOI } stmt = _{ assign | expr } assign = { ident ~ "=" ~ expr } expr = { prefix* ~ primary ~ postfix* ~ (infix ~ prefix* ~ primary ~ postfix* )* } -primary = _{ constants | function | variable | num | "(" ~ expr ~ ")" } +primary = _{ (num ~ constants) | constants | function | variable | num | "(" ~ expr ~ ")" } infix = _{ sub | add | mul | div | pow | percentOf | percentOn | rightShift | leftShift | modulus } prefix = _{ neg } postfix = _{ fac } diff --git a/extensions/ext-computing/src/expr/parser.rs b/extensions/ext-computing/src/expr/parser.rs index ce1797b..a982d49 100644 --- a/extensions/ext-computing/src/expr/parser.rs +++ b/extensions/ext-computing/src/expr/parser.rs @@ -18,6 +18,7 @@ lazy_static! { .op(Op::infix(Rule::mul, Assoc::Left) | Op::infix(Rule::div, Assoc::Left)) .op(Op::infix(Rule::pow, Assoc::Right)) .op(Op::postfix(Rule::fac)) + .op(Op::postfix(Rule::e)) .op(Op::prefix(Rule::neg)) }; } @@ -27,6 +28,7 @@ pub fn parse(input: &str, vars: &BTreeMap) -> f64 { match Calculator::parse(Rule::program, input) { Ok(mut pairs) => { let expr = parse_expr(pairs.next().unwrap().into_inner()); + println!("expr: {:?}", expr); namespace.eval(expr) } Err(err) => { @@ -102,6 +104,11 @@ fn parse_expr(pairs: Pairs) -> Instruction { Rule::pow => Instruction::Pow { lhs: Box::from(lhs), rhs: Box::from(rhs) }, _ => panic!("unimplemented: {:?}", op), }) + .map_postfix(|lhs, op: Pair| match op.as_rule() { + Rule::fac => Instruction::Fac { val: Box::from(lhs) }, + Rule::e => Instruction::Mul { lhs: Box::from(lhs), rhs: Box::from(Instruction::Const(std::f64::consts::E)) }, + _ => panic!("unimplemented: {:?}", op), + }) .parse(pairs) } @@ -154,13 +161,22 @@ mod tests { } #[test] - fn function_sqrt() { + fn function_demo() { assert_eq!(parse("sqrt(4)", &Default::default()), 2.0); let vars = BTreeMap::from_iter(vec![("x".to_string(), Instruction::Const(2.0))]); assert_eq!(parse("sqrt(1 - (3 / x^2))", &vars), 0.5); assert_eq!(parse("sqrt(1 - (3 / 3^2))", &vars), 0.816496580927726); + } + + #[test] + fn const_e() { + let vars2 = BTreeMap::from_iter(vec![("x".to_string(), Instruction::Const(2.0))]); + assert_eq!(parse("sin(2.34e-3 * x)", &vars2), 0.004679982916146709); + + let mut symbol_table = exprtk_rs::SymbolTable::new(); + symbol_table.add_variable("x", 2.0).unwrap().unwrap(); + let mut expr = exprtk_rs::Expression::new("sin(2.34e-3 * x)", symbol_table).unwrap(); - let vars2 = BTreeMap::from_iter(vec![("x".to_string(), Instruction::Const(3.0))]); - assert_eq!(parse("sin(2.34e-x *2)", &vars2), 0.00467998291); + assert_eq!(expr.value(), 0.004679982916146709); } } diff --git a/extensions/ext-computing/src/expr/token.rs b/extensions/ext-computing/src/expr/token.rs index f6e93e9..380c335 100644 --- a/extensions/ext-computing/src/expr/token.rs +++ b/extensions/ext-computing/src/expr/token.rs @@ -96,6 +96,9 @@ pub enum Instruction { // Functions FuncSin, FuncCos, + Fac { + val: Box, + }, // Others // with Builtin Types?