24

I'm looking for an evaluator for simple condition expressions. Expressions should include variables (read only), strings, numbers and some basic operators.

E.g. expressions something like this:

${a} == "Peter" && ( ${b} == null || ${c} > 10 )

So far i implemented a rather "magical" parser that returns an AST that i can evaluate, but i can't believe that i'm the first one to solve that problem.

What existing code could i use instead?

Stroboskop
  • 4,327
  • 5
  • 35
  • 52
  • What language/grammar are you looking to evaluate? Is it something you've made up? What does Java have to do with this? – Matt Ball Oct 24 '10 at 22:01
  • 2
    I guess the OP wants something that runs on the JVM. – Fred Foo Oct 24 '10 at 22:09
  • We've used JEP on a project (http://www.singularsys.com/jep/) but I'd really like a small, adaptable equivalent that could actually produce bytecode for a function for performance reasons. We abandoned JEP for this reason, and ended up handcoding a huge number of Java classes. Maybe an enterprising soul with ANTLR and BCEL could do this? – andersoj Oct 24 '10 at 23:12
  • @Matt Ball: The example is a made up syntax that i'm using right now. But when i find a parser that's meets my demands i can go with whatever syntax it accepts. My main aim syntax-wise is to keep it as minimalistic as possible, because we may have many (think up to 200) of these tiny conditions in a single set. So, readability and performance are an issue. – Stroboskop Oct 27 '10 at 16:24

7 Answers7

16

Have you looked at MVEL? They provide a getting started guide and performance analysis.

Here's one of their simple examples:

// The compiled expression is serializable and can be cached for re-use.
CompiledExpression compiled = MVEL.compileExpression("x * y"); 

Map vars = new HashMap();
vars.put("x", new Integer(5));
vars.put("y", new Integer(10));

// Executes the compiled expression
Integer result = (Integer) MVEL.executeExpression(compiled, vars); 
assert result.intValue() == 50; 

Also (answering my own question) MVEL seems to provide some support for bytecode generation.

Other alternatives, culling from the above answers and my own:

andersoj
  • 22,406
  • 7
  • 62
  • 73
  • 2
    MVEL project documentation has been moved from codehaus. The link location is http://mvel.documentnode.com/. github location is - https://github.com/mvel/mvel. – Swapnil Apr 08 '19 at 19:07
  • But MVEL has a problem with the string like this @{'11412Test'} or @{'Test11412'} it wont be able to parse the above text and throws an error Caused by: [Error: invalid number literal: 11412Test] – moh Jul 26 '23 at 05:16
8

Sounds like JEXL might work well for you. Check out its syntax reference.

Mike Daniels
  • 8,582
  • 2
  • 31
  • 44
7

What about SPEL (Spring Expression Lang); http://static.springsource.org/spring/docs/3.0.x/reference/expressions.html

NightWolf
  • 7,694
  • 9
  • 74
  • 121
  • 1
    It's too late now, but that looks pretty much what i was looking for. It is focused on evaluating, but you have a getAST method that returns the expression structure. – Stroboskop Nov 07 '13 at 10:45
6

Why don't you use Rhino? It's a JavaScript engine already present inside the JDK.

It can evaluate whatever you like to write in JS.. take a look here

Jack
  • 131,802
  • 30
  • 241
  • 343
  • In fact we're using Rhino for larger custom scripts already. But i don't want to give these small expressions the full power of a scripting language. – Stroboskop Oct 27 '10 at 18:02
3

This simple recursive descent parser evaluates constants as named functions having no parameters.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • 4
    When i'll replace magic with science i'll go that way. But right now i'm looking for an existing solution. – Stroboskop Oct 27 '10 at 17:54
2

A very simple and easy to use alternative with a lot of built in excel functions for string, date and number formatting.

The library also allows easy addition of custom functions. A lot of examples available on the git page. A simple example using variables

  ExpressionsEvaluator evalExpr = ExpressionsFactory.create("LEFT(City, 3)");
  Map<String, Object> variables = new HashMap<String, Object>();
  variables.put("City", "New York");
  assertEquals("New", evalExpr.eval(variables));
Scorpion
  • 3,938
  • 24
  • 37
  • That looks really promising for an out of the box solution. But i eventually went for Antlr and built my own expression language. – Stroboskop Jan 13 '16 at 12:01
0

Here is a little library I've worked on that supports expression evaluation (including variables, strings, boolean, etc...).

A little example :

String expression = "EXP(var)";
ExpressionEvaluator evaluator = new ExpressionEvaluator();
evaluator.putVariable(new Variable("var", VariableType.NUMBER, new BigDecimal(20)));

System.out.println("Value of exp(var) : " + evaluator.evaluate(expression).getValue());
Skyost
  • 1,429
  • 1
  • 16
  • 31