The library provides a framework for defining expression, parsing them and evaluating them. The core offers basic math expression for double math and common operations for long integer types.
The framework supports:
- Parenthesis.
- Operators precedence, both left and right.
- Operators, unary and binary.
- Constants.
- Functions.
- Variables.
- Type safety: type is checked at parse time and allows safely checking mix of boolean conditions and math operations for example.
- Null handling: operations (if designed so) can accept
null
values and providenull
result at output. - Lazy evaluation: allows safe conditional evaluation.
Almost anything can be customized:
- Parser, to reasonable level, though completely new one can be provided.
- Operators.
- Functions.
- Variables.
- Constant parsing (for example, 0b can be added for bit numbers).
The API is made to be parsed once and executed multiple times. The parsing is of course the slowest operation, therefore it should be avoided or cached (it is still very fast though!).
Math expression for double type.
// Creates new instance, initializing with double math operations and functions:
EvaluatorFactory factory = DoubleMathEvaluatorProvider.populateMath(CustomizableEvaluatorFactory.builder());
// Parses the expression:
EvaluatorFactory.Expression<Long> expression = factory.parse("a+b");
// Evaluates expression, based on provided context parameters:
Double result = expression.evaluate(new MapContext<>(ImmutableMap.of("a", 1977L, "b", 3L)));
// Something more complex:
EvaluatorFactory.Expression<Long> expression = factory.parse("sin(pi()/2)*(2+1)");
Double math provider supports common operations and functions:
- Unary
+
,-
- Binary
+
,-
,*
,/
,%
- Constants:
pi
,e
- Conversion functions:
radians
,degrees
- Goniometric functions:
sin
,cos
,tan
,cotan
,asin
,acos
,atan
,acotan
,atan2
- Exponential functions:
ln
,log2
,log10
,exp
,pow
- Other:
abs
Math expressions for double type, in addition allowing comparison boolean operators and appropriate functions.
// Creates new instance, initializing with double math operations and functions:
EvaluatorFactory factory = DoubleEvaluatorProvider.populateBitAndCalc(CustomizableEvaluatorFactory.builder());
// Parses the expression:
EvaluatorFactory.Expression<Long> expression = factory.parse("nullfor(ifelse(a <= b, a, b), 5)");
// Evaluates expression, based on provided context parameters:
Long result = expression.evaluate(new MapContext<>(ImmutableMap.of("a", 1977L, "b", 3L)));
In addition to standard long expression provider, the following are supported:
- Comparison
==
,!=
,>
,>=
,<
,<=
- Functions
isnull
,ifnull
,ifelse
// Creates new instance, initializing with double math operations and functions:
EvaluatorFactory factory = StandardLongEvaluatorProvider.populateBitAndCalc(CustomizableEvaluatorFactory.builder());
// Parses the expression:
EvaluatorFactory.Expression<Long> expression = factory.parse("a+b");
// Evaluates expression, based on provided context parameters:
Long result = expression.evaluate(new MapContext<>(ImmutableMap.of("a", 1977L, "b", 3L)));
// Something more complex:
EvaluatorFactory.Expression<Long> expression = factory.parse("(a+b)*swap32((c<<2)&0xff)");
Long expression provider supports common operations and functions:
- Unary
+
,-
,~
- Binary
+
,-
,*
,/
,%
,*^
- Bit
&
,^
,|
,<<
,>>
,>>>
- Functions
nullfor
,swap16
,swap32
,swap64
Math expressions for long type, in addition allowing comparison boolean operators and appropriate functions.
// Creates new instance, initializing with double math operations and functions:
EvaluatorFactory factory = StandardLongEvaluatorProvider.populateBitAndCalc(CustomizableEvaluatorFactory.builder());
// Parses the expression:
EvaluatorFactory.Expression<Long> expression = factory.parse("nullfor(ifelse(a <= b, a, b), 5)");
// Evaluates expression, based on provided context parameters:
Long result = expression.evaluate(new MapContext<>(ImmutableMap.of("a", 1977L, "b", 3L)));
In addition to standard long expression provider, the following are supported:
- Comparison
==
,!=
,>
,>=
,<
,<=
- Functions
isnull
,ifnull
,ifelse
Both parser and evaluator are fast. Internally, AST is used to represent parsed result and then execute it. Here are some numbers for simple (2*8+10-8/2
) expression and 2022 laptop CPU Intel(R) Core(TM) i7-1185G7 @ 3.00GHz:
Benchmark Mode Cnt Score Error Units
CustomizableEvaluatorFactoryBenchmark.benchmark0_construction avgt 4 41.478 ± 5.981 ns/op
CustomizableEvaluatorFactoryBenchmark.benchmark1_parse avgt 4 493.869 ± 15.879 ns/op
CustomizableEvaluatorFactoryBenchmark.benchmark2_evaluate avgt 4 24.615 ± 3.056 ns/op
The code is released under version 2.0 of the Apache License.
Zbynek Vyskovsky
Feel free to contact me at kvr000@gmail.com and http://github.com/kvr000