2

如何评估在运行时输入的“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 为真,则不应执行其他动词)似乎不存在。

4

2 回答 2

1

如果您可以使用||and&&代替ANDand OR,您可以使用 groovy 缺少的属性方法和GroovyShell 基类设置,如下所示:

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
于 2012-07-04T09:06:42.153 回答
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) {
}

这并没有考虑到您提前返回的要求,但我相信您可以弄清楚如何做到这一点。

这可能不是做事的最佳方式,但它是我过去让它为我工作的方式。希望这可以帮助。

于 2012-07-04T02:17:17.160 回答