ANTLR评估复合规则

时间:2012-11-12 13:15:00

标签: java antlr

以下是我一直在研究的ANTLR语法的片段:

compoundEvaluation returns [boolean evalResult]
  : singleEvaluation (('AND'|'OR') singleEvaluation)*
;

//overall rule to evaluate a single expression
singleEvaluation returns [boolean evalResult]
  : simpleStringEvaluation {$evalResult = $simpleStringEvaluation.evalResult;} 
  | stringEvaluation {$evalResult = $stringEvaluation.evalResult;}
  | simpleDateEvaluation {$evalResult = $simpleDateEvaluation.evalResult;}
  | dateEvaluatorWithModifier1 {$evalResult = $dateEvaluatorWithModifier1.evalResult;}
  | dateEvaluatorWithoutModifier1 {$evalResult = $dateEvaluatorWithoutModifier1.evalResult;}
  | simpleIntegerEvaluator {$evalResult = $simpleIntegerEvaluator.evalResult;}
  | integerEvaluator {$evalResult = $integerEvaluator.evalResult;}
  | integerEvaluatorWithModifier {$evalResult = $integerEvaluatorWithModifier.evalResult;}
  ;

以下是其中一个评估规则的示例:

simpleStringEvaluation returns [boolean evalResult]
: op1=STR_FIELD_IDENTIFIER operator=(EQ|NE) '"'? op2=(SINGLE_VALUE|INTEGER) '"'?
{
  // I don't want these to be equal by default
  String op1Value = op1.getText();
  String op2Value = op2.getText();
  try {
    // get the values of the bean property specified by the value of op1 and op2
    op1Value = BeanUtils.getProperty(policy,op1.getText());
  } catch (NoSuchMethodException e) {
    e.printStackTrace();
  } catch (InvocationTargetException e) {
    e.printStackTrace();
  } catch (IllegalAccessException e) {
    e.printStackTrace();
  }

String strOperator = operator.getText();
if (strOperator.equals("=")) {
  evalResult = op1Value.equals(op2Value);
} 
if (strOperator.equals("<>")) {
  evalResult = !op1Value.equals(op2Value);
}
}
;

显然我是新手,因为我没有建造一棵树,但代码有效,所以我对它很满意。但是,下一步是对多个singleEvaluation语句执行逻辑评估。由于我将代码嵌入语法中,我希望有人能指出我正确的方向来弄清楚如何评估0或更多结果。

2 个答案:

答案 0 :(得分:1)

无需将值存储在集合中。

为什么不简单地做这样的事情:

compoundOrEvaluation returns [boolean evalResult]
  :          a=singleEvaluation { $evalResult   = $a.evalResult; } 
    ( ('OR') b=singleEvaluation { $evalResult ||= $b.evalResult; } )*
  ;

答案 1 :(得分:0)

我是这样做的。我创建了一个Set作为成员,然后在每个语句的@init中,我重新初始化了Set。在评估语句时,它填充了该集合。由于集合的唯一合法值是真或假,我最终得到一个包含0,1或2个成员的集合。

OR评估如下:

compoundOrEvaluation returns [boolean evalResult]
  @init {evaluationResults = new HashSet<Boolean>();}
  : a=singleEvaluation {evaluationResults.add($a.evalResult);} (('OR') b=singleEvaluation {evaluationResults.add($b.evalResult);})+
  {
    if (evaluationResults.size()==1) {
      evalResult = evaluationResults.contains(true);
    } else {
      evalResult = true;
    }
  }
  ;

AND评估仅在else语句中有所不同,其中evalResult将设置为false。到目前为止,这通过了我可以投入的单元测试。

最终我可能会使用树和访客类,但代码目前有效。