JAVA - Expression parsing & evaluating library
Asked Answered
D

4

14

I'm looking for a JAVA library to parse & evaluate expression. I searched and tried some libraries like Apache's JEXL and Jeval, but they are not exactly what I need.

My requirements:

  1. Support all value types (i.e. int,double,boolean,String, etc.)
  2. Support all known mathematical & logical operators (+,-,*,<,<=,etc.)
  3. Support variables (without any special notation - for example in Jeval variable a should be written like #{a} - not good enough for me)
  4. Support custom functions - with type enforcement and validation

Any recommendations?

Demodulate answered 14/8, 2012 at 7:21 Comment(1)
Have you considered the built-in Java Script engine?Inspissate
D
8

Try Janino. It's a runtime in-memory compiler that can be used as an expression evaluator. Maybe it is the right thing for you.

Disincline answered 14/8, 2012 at 7:33 Comment(1)
That is really an impressive library, at least from what they claim to be able to doArtemas
F
4

Like suggested, you can use JavaScript. But also you could take a look at Spring EL which has support for your requirements.

Factitive answered 14/8, 2012 at 7:30 Comment(0)
P
3

You can try mXparser - it supports significant part of your requirements:

  1. It is based on double, so int is supported, additionally boolean is supported as true = 1 and false = 0. Unfortunately strings are not supported.

Boolean example:

import org.mariuszgromada.math.mxparser.*;
...
...
Constant T = new Constant("T = 1");
Constant F = new Constant("F = 0");
Expression e = new Expression("T && (F || (F && T))", T, F);
System.out.println(e.getExpressionString() + " = " + e.calculate());

Result:

T && (F || (F && T)) = 0.0
  1. mXparser has broad support for operators, functions, etc.. Check mXparser math collection. What is nice you can use help functionality inside the library.

Example:

import org.mariuszgromada.math.mxparser.*;
...
...
mXparser.consolePrintHelp("operator");

Result:

Help content: 

    2. +                   <Operator>              addition
    3. -                   <Operator>              subtraction
    4. *                   <Operator>              multiplication
    5. /                   <Operator>              division
    6. ^                   <Operator>              exponentiation
    7. !                   <Operator>              factorial
    8. #                   <Operator>              modulo function
    9. &                   <Boolean Operator>      logical conjunction (AND)
   10. &&                  <Boolean Operator>      logical conjunction (AND)
   11. /\                  <Boolean Operator>      logical conjunction (AND)
   12. ~&                  <Boolean Operator>      NAND - Sheffer stroke
   13. ~&&                 <Boolean Operator>      NAND - Sheffer stroke
   14. ~/\                 <Boolean Operator>      NAND - Sheffer stroke
   15. |                   <Boolean Operator>      logical disjunction (OR)
   16. ||                  <Boolean Operator>      logical disjunction (OR)
   17. \/                  <Boolean Operator>      logical disjunction (OR)
   18. ~|                  <Boolean Operator>      logical NOR
   19. ~||                 <Boolean Operator>      logical NOR
   20. ~\/                 <Boolean Operator>      logical NOR
   21. (+)                 <Boolean Operator>      exclusive or (XOR)
   22. -->                 <Boolean Operator>      implication (IMP)
   23. <--                 <Boolean Operator>      converse implication (CIMP)
   24. -/>                 <Boolean Operator>      material nonimplication (NIMP)
   25. </-                 <Boolean Operator>      converse nonimplication (CNIMP)
   26. <->                 <Boolean Operator>      logical biconditional (EQV)
   27. ~                   <Boolean Operator>      negation
   28. ¬                   <Boolean Operator>      negation
  162. add                 <Variadic Function>     (2.4) Summation operator add(a1,a2,a3,...,an)
  168. sum                 <Calculus Operator>     summation operator (SIGMA) sum(i, from, to, f(i,...))
  169. prod                <Calculus Operator>     product operator (PI) prod(i, from, to, f(i,...))
  170. int                 <Calculus Operator>     definite integral operator ( int(f(x,...), x, a, b) )
  171. der                 <Calculus Operator>     derivative operator ( der(f(x,...), x) ) 
  172. der-                <Calculus Operator>     left derivative operator ( der-(f(x,...), x) ) 
  173. der+                <Calculus Operator>     right derivative operator ( der+(f(x,...), x) ) 
  174. dern                <Calculus Operator>     n-th derivative operator ( dern(f(x,...), x) ) 
  175. diff                <Calculus Operator>     forward difference operator
  176. difb                <Calculus Operator>     backward difference operator
  177. avg                 <Calculus Operator>     (2.4) Average operator avg(i, from, to, f(i,...))
  178. vari                <Calculus Operator>     (2.4) Bias-corrected sample variance operator vari(i, from, to, f(i,...))
  179. stdi                <Calculus Operator>     (2.4) Bias-corrected sample standard deviation operator stdi(i, from, to, f(i,...))
  180. mini                <Calculus Operator>     (2.4) Minimum value mini(i, from, to, f(i,...))
  181. maxi                <Calculus Operator>     (2.4) Maximum value maxi(i, from, to, f(i,...))
  182. solve               <Calculus Operator>     (4.0) f(x) = 0 equation solving, function root finding: solve( f(x,...), x, a, b )
  301. @~                  <Bitwise Operator>      (4.0) Bitwise unary complement
  302. @&                  <Bitwise Operator>      (4.0) Bitwise AND
  303. @^                  <Bitwise Operator>      (4.0) Bitwise exclusive OR
  304. @|                  <Bitwise Operator>      (4.0) Bitwise inclusive OR
  305. @<<                 <Bitwise Operator>      (4.0) Signed left shift
  306. @>>                 <Bitwise Operator>      (4.0) Signed right shift
  1. User defined variables and user defined constants are created without any special form.

Example:

import org.mariuszgromada.math.mxparser.*;
...
...
Argument x = new Argument("x = 10");
Constant y = new Constant("y = 2");
Expression e = new Expression("x/y", x, y);
System.out.println(e.getExpressionString() + " = " + e.calculate());

Result:

x/y = 5.0

Additionally please check: a) Tutorial - User defined arguments, b) Tutorial - User defined constants.

  1. User defined functions are fully supported.

Example 1 - body defined in run-time:

import org.mariuszgromada.math.mxparser.*;
...
...
Function f = new Function("f(x,y) = x*y");
Expression e = new Expression("20-f(2,5)",f);
System.out.println(e.getExpressionString() + " = " + e.calculate());

Result 1

20-f(2,5) = 10.0

Example 2 - body extended via your own implementation:

import org.mariuszgromada.math.mxparser.*;
...
...
/*
 * Implementing FunctionExtension interface
 */
public class Addition implements FunctionExtension {
   double x;
   double y;
   public Addition() {
      x = Double.NaN;
      y = Double.NaN;
   }
   public Addition(double x, double y) {
      this.x = x;
      this.y = y;
   }
   public int getParametersNumber() {
      return 2;
   }
   public void setParameterValue(int argumentIndex, double argumentValue) {
      if (argumentIndex == 0) x = argumentValue;
      if (argumentIndex == 1) y = argumentValue;
   }
   public double calculate(double... params) {
      return x+y;
   }
   public FunctionExtension clone() {
      return new Addition(x, y);
   }   
}

/*
* Creating extended function
*/
Function f = new Function("f", new Addition());
mXparser.consolePrintln("f.calculate(1,2) = " + f.calculate(1,2) );
/*
* Using extended function in expression
*/
Expression e = new Expression("f(2,3)", f);
System.out.println(e.getExpressionString() + " = " + e.calculate() );

Result 2:

f.calculate(1,2) = 3.0
f(2,3) = 5.0

Additionally it is worth to follow the whole mXparser Tutorial.

Found recently - in case you would like to try the syntax (and see the advanced use case) you can download the Scalar Calculator app that is powered by mXparser.

Best regards

People answered 16/4, 2017 at 18:22 Comment(2)
Sadly, pow is not supported by it.Chivalrous
@ShoaibChikate You can simply write x^y - this is the same as pow(x,y)People
A
0

Here would be a couple of workaround solutions that you could choose from, if you don't find an actual Java expression evaluation library:

  • Evaluate your expressions using XPath.
    • Pros: XPath knows logical operators, and you can implement variables and custom functions using Xalan's extensions
    • Cons: XPath has fewer types than Java
  • Evaluate your expressions using JavaScript.
    • Pros: Javascript is very flexible and will still be suitable when your requirements tighten. You can implement variables and custom functions using Javascript as well
    • Cons: Javascript has fewer types than Java
  • Evaluate your expressions using JSP's expression language (e.g. with JUEL)
Artemas answered 14/8, 2012 at 7:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.