简体   繁体   中英

ANTLR Evaluation of a Compound Rule

The following is a snippet from an ANTLR grammar I have been working on:

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

Here's a sample of one of those evaluation rules:

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

Obviously I'm a newbie since I'm not building a tree, but the code works so I'm reasonably happy with it. However, the next step is to perform logical evaluations on multiple singleEvaluation statements. Since I'm embedding the code in the grammar, I was hoping someone could point me in the right direction to figure out how to evaluate 0 or more results.

There is no need to store the values in a set.

Why not simply do something like this:

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

?

Here's how I did it. I created a Set as a member, then in each statement's @init, I reinitialized the Set. As the statement was evaluated, it populated the set. Since the only legal values of the set are true or false, I end up having a set with 0, 1, or two members.

The OR evaluation looks like this:

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

The AND evaluation only differs in the else statement, where evalResult will be set to false. So far, this passes the unit tests I can throw at it.

Eventually I may use a tree and a visitor class, but the code currently works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM