#expression #calculator #jit #evaluator #math-expressions

cruncher

jit-compiled mathematical expression calculator

3 unstable releases

0.2.1 Jan 28, 2020
0.2.0 Jan 28, 2020
0.1.0 Aug 12, 2019

#37 in #evaluator

MIT license

54KB
954 lines

Cruncher

This library takes a string such as "x + 2 / 3 * ( z ^ 4 )" and allows you to pass in a dictionary with values defined for each variable used and get the result.

Right now the tests do the best job of providing examples of how to interact with the library.

It is a work in progress but the main functionality is there. The lexer/parser needs to be improved as it is sensitive to spacing.


lib.rs:

Cruncher, a crate for dynamic evaluation of mathematical expressions.

This crate provide run-time evaluation of mathematical expressions, embedded in strings. The easiest way to use this crate is with the eval function:

assert_eq!(cruncher::eval("3 + 5 * 2", None), Ok(13.0));

The second argument to eval is a HashMap, that can define variables:

use hashbrown::HashMap;

let mut context :HashMap<String,f64> = HashMap::new();
context.insert("a".into(), 3.5);
assert_eq!(cruncher::eval("2 * a", &context), Ok(7.0));

It is also possible to separate the parsing from the evaluation of an expression with the Expr type. This allow to reuse the same expression with different values for variables.

use hashbrown::HashMap;
use cruncher::{Expr};

let expr = Expr::parse("3 + 5 * 2").unwrap();
assert_eq!(expr.eval(None), Ok(13.0));

let expr = Expr::parse("3 / c + b").unwrap();
let mut context :HashMap<String,f64> = HashMap::new();
context.insert("c".into(), 1.0);
context.insert("b".into(), 5.0);
assert_eq!(expr.eval(&context), Ok(8.0));

context.insert("b".into(), 10.0);
assert_eq!(expr.eval(&context), Ok(13.0));

Language definition

The language implemented by cruncher can contain the following elements:

  • float literal values: -12.456, +0.0045e78, ...;
  • left and right parenthesis;
  • mathematical operators: + for addition, - for subtraction, * for multiplication, / for division and ^ for exponentiation (std::f64::powf);
  • variables. Variables names are ASCII only, and can start by a letter or _, and can contain letters, digits, ., _, [ or ].
  • function call: sin(a), atan(22.0). The following function are accessible, with the same meaning as the corresponding std::f64 function: sqrt, cbrt, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, floor, ceil, abs, exp, ln, log2, log10.

Any other symbol is forbidden in the input.

The mathematical operators obey the usual relations of associativity and precedence, but still carry the floating point properties: addition is not commutative, NaN and infinities exist, ...

Technical details

cruncher is based on an AST interpreter, and uses a simple Shuntting-Yard algorithm for parsing the expressions. It works only with f64 data, and perform a simple constant propagation to optimize the expressions.

Dependencies

~8MB
~176K SLoC