1

以下は、私が取り組んできた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;}
  ;

これらの評価ルールの1つのサンプルを次に示します。

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個以上の結果を評価する方法を理解してくれることを望んでいました。

4

2 に答える 2

1

値をセットに格納する必要はありません。

単純に次のようなことをしてみませんか。

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

于 2012-11-13T20:25:24.333 に答える
0

これが私がそれをした方法です。セットをメンバーとして作成し、各ステートメントの@initで、セットを再初期化しました。ステートメントが評価されると、セットにデータが入力されました。セットの正当な値はtrueまたはfalseのみであるため、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評価は、evalResultがfalseに設定されるelseステートメントでのみ異なります。これまでのところ、これは私が投げることができるユニットテストに合格しています。

最終的にはツリーとビジタークラスを使用する可能性がありますが、コードは現在機能しています。

于 2012-11-12T15:15:05.483 に答える