2

How do I go about evaluating logical expression like "VERB1 OR (VERB2 AND VERB3) OR (VERB4)" entered at runtime. VERB* are placeholder to evaluate certain conditions. For example, VERB1 might mean check for the existence of a record in database.

In expression "VERB1 OR (VERB2 AND VERB3) OR (VERB4)", other verbs should not be executed if VERB1 is true

EDIT: Example described at http://www.alittlemadness.com/2006/06/05/antlr-by-example-part-1-the-language/ seems very similar to what I am trying to do. However, the optimization step (other verbs should not be executed if VERB1 is true) doesn't seem to be there.

dsatish
  • 1,041
  • 15
  • 27
  • Have you tried rules engines like Drools, http://openrules.com/ etc? Or another alternative is leveraging Ognl or MVEL or Spring EL (http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/expressions.html) – Aravind Yarram Jul 04 '12 at 03:14
  • We briefly looked at Drools but not the others. We felt Drools might be overkill to introduce on our project and were not clear if it will solve this problem. – dsatish Jul 04 '12 at 04:49

2 Answers2

1

If you can use || and && in place of AND and OR, you can just use groovy's missing property methods and the GroovyShell base class setting like so:

import org.codehaus.groovy.control.CompilerConfiguration

// The command to be executes
def command = "VERB1 || (VERB2 && VERB3) || (VERB4)"

// Set a base class for the GroovyShell
new CompilerConfiguration().with { compiler ->
  compiler.scriptBaseClass = 'VerbHandlingBaseClass'
  new GroovyShell( this.class.classLoader, new Binding(), compiler ).with { shell ->
    // and evaluate the command
    shell.evaluate( command )
  }
}

abstract class VerbHandlingBaseClass extends Script {
  boolean VERB1() {
    System.out.println( 'CHECK THE DATABASE, RETURN FALSE' )
    false
  }

  boolean VERB2() {
    System.out.println( 'WRITE A LOG ENTRY RETURN TRUE' )
    true
  }

  boolean VERB3() {
    System.out.println( 'VALIDATE SOMETHING, RETURN TRUE' )
    true
  }

  boolean VERB4() {
    System.out.println( 'THIS WONT BE REACHED, AS VERB2 && VERB3 == true' )
    true
  }

  def propertyMissing( String name ) {
    "$name"()
  }
}

That should print:

CHECK THE DATABASE, RETURN FALSE
WRITE A LOG ENTRY RETURN TRUE
VALIDATE SOMETHING, RETURN TRUE
tim_yates
  • 167,322
  • 27
  • 342
  • 338
0

You mentioned ANTLR in your tags: have you given this a go? You can create a full boolean grammar in ANTLR but it gets much harder when you get down to the level of how to evaluate the verbs.

If there is a small, fixed set of verbs which may be queried you can easily create a mapping between the verbs and the functions.

If there is a larger list of verbs, you may be able to use reflection to call specific methods to evaluate them.

If your verbs can include mathematical comparisons, this all gets a bit harder as you create a mathematical lexer and parser as well.

Without a more specific question and knowledge of what you have tried in ANTLR I'm not sure I can give you much more advice.

EDIT: Based on your comments, I'll add some more. You can add parsing rules to your grammar:

boolean_or returns [boolean b]
    : b1=boolean_and {$b = $b1.b;}
      (OR b2=boolean_and {$b = $b || $b2.b;})* 
    ;

boolean_atom returns [boolean b]
    :
    ((numeric_comparison)=> b1=numeric_comparison {$b = $b1.b;}
    | TRUE {$b = true;} | FALSE {$b = false;}
    | s1=VERB {$b = evalVerb($s1.s);}
    | LPAREN b1=boolean_expr RPAREN {$b = $b1.b;}
    )

;

Thats a small part of a boolean parser I'm currently using. You can fill in the blanks.

And then call the parser using something like

ANTLRStringStream in = new ANTLRStringStream(booleanString);
ActionLexer lexer = new  ActionLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
BooleanParser parser = new  BooleanParser(tokens);
try {
    return parser.eval();
} catch (Exception e) {
}

This doesn't account for your requirement of returning early, but I'm sure you can figure out how to do that.

This might not be the best way to do things, but its the way that I've gotten it to work for me in the past. Hope this helps.

Trasvi
  • 1,207
  • 1
  • 15
  • 23
  • I just started exploring ANTLR. From my understanding, by defining grammar, ANTLR will generate a tree (similar to the expression tree shown in http://stackoverflow.com/questions/4589951/parsing-an-arithmetic-expression-and-building-a-tree-from-it-in-java). The tree still needs to be evaluated -- evaluator is not supplied by ANTLR. – dsatish Jul 04 '12 at 02:27
  • It seems the "evaluator" I'm referring to is known as "Tree Parser" in ANLTR lingo – dsatish Jul 04 '12 at 02:35