Reputation: 4145
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.
Upvotes: 1
Views: 212
Reputation: 170227
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; } )*
;
?
Upvotes: 1
Reputation: 4145
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.
Upvotes: 0