在运行时评估逻辑表达式

时间:2012-07-04 02:00:52

标签: java groovy antlr antlr3 abstract-syntax-tree

如何评估在运行时输入的“VERB1 OR(VERB2 AND VERB3)OR(VERB4)”等逻辑表达式。 VERB *是占位符来评估某些条件。例如,VERB1可能意味着检查数据库中是否存在记录。

在表达式“VERB1 OR(VERB2 AND VERB3)OR(VERB4)”中,如果VERB1为真,则不应执行其他动词

编辑:http://www.alittlemadness.com/2006/06/05/antlr-by-example-part-1-the-language/中描述的示例与我正在尝试的内容非常相似。但是,优化步骤(如果VERB1为真,则不应执行其他动词)似乎不存在。

2 个答案:

答案 0 :(得分:1)

如果您可以使用||&&代替ANDOR,则可以使用groovy缺少的属性方法和the GroovyShell base class setting,如下所示:

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"()
  }
}

那应该打印:

CHECK THE DATABASE, RETURN FALSE
WRITE A LOG ENTRY RETURN TRUE
VALIDATE SOMETHING, RETURN TRUE

答案 1 :(得分:0)

你在你的标签中提到过ANTLR:你有这个去过吗?你可以在ANTLR中创建一个完整的布尔语法,但是当你达到评估动词的水平时,它会变得更加困难。

如果有一小组固定的动词可以查询,你可以轻松地在动词和函数之间创建一个映射。

如果有更大的动词列表,您可以使用反射来调用特定方法来评估它们。

如果你的动词可以包含数学比较,那么当你创建一个数学词法分析器和解析器时,这一切都会变得更加困难。

如果没有更具体的问题和你在ANTLR中尝试过的知识,我不确定我能给你更多的建议。

编辑:根据您的评论,我会再添加一些内容。 您可以在语法中添加解析规则:

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;}
    )

;

这是我正在使用的布尔解析器的一小部分。你可以填空。

然后使用

之类的东西调用解析器
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) {
}

这并不能解释您提前返回的要求,但我相信您可以弄清楚如何做到这一点。

这可能不是最好的做事方式,但它是我过去为我工作的方式。希望这会有所帮助。