This is an automated email from the ASF dual-hosted git repository.
tkobayas pushed a commit to branch dev-new-parser
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git
The following commit(s) were added to refs/heads/dev-new-parser by this push:
new 4784201b5e [incubator-kie-drools-5716] [new-parser] mismatched input
'if'/'do' (… (#5831)
4784201b5e is described below
commit 4784201b5e19b1b4082962ccbebc4bfef11e2b3a
Author: Toshiya Kobayashi <[email protected]>
AuthorDate: Thu Apr 11 10:56:46 2024 +0900
[incubator-kie-drools-5716] [new-parser] mismatched input 'if'/'do' (…
(#5831)
* [incubator-kie-drools-5716] [new-parser] mismatched input 'if'/'do'
(support named consequences)
* Update
drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRLLexer.g4
Co-authored-by: Jiří Locker <[email protected]>
* Update
drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DRLVisitorImpl.java
Co-authored-by: Jiří Locker <[email protected]>
* resolve duplicate difinition
---------
Co-authored-by: Jiří Locker <[email protected]>
---
.../drl/parser/antlr4/MiscDRLParserTest.java | 171 +++++++++++++++++++++
.../org/drools/drl/parser/antlr4/DRLLexer.g4 | 2 +
.../org/drools/drl/parser/antlr4/DRLParser.g4 | 49 ++++--
.../drl/parser/antlr4/Antlr4ParserStringUtils.java | 10 +-
.../drools/drl/parser/antlr4/DRLVisitorImpl.java | 94 ++++++++++-
5 files changed, 302 insertions(+), 24 deletions(-)
diff --git
a/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java
b/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java
index 2d21323828..5e3cf7c6af 100644
---
a/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java
+++
b/drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java
@@ -19,6 +19,7 @@ import org.drools.drl.ast.descr.AttributeDescr;
import org.drools.drl.ast.descr.BaseDescr;
import org.drools.drl.ast.descr.BehaviorDescr;
import org.drools.drl.ast.descr.CollectDescr;
+import org.drools.drl.ast.descr.ConditionalBranchDescr;
import org.drools.drl.ast.descr.EntryPointDeclarationDescr;
import org.drools.drl.ast.descr.EntryPointDescr;
import org.drools.drl.ast.descr.EvalDescr;
@@ -30,6 +31,7 @@ import org.drools.drl.ast.descr.FunctionDescr;
import org.drools.drl.ast.descr.GlobalDescr;
import org.drools.drl.ast.descr.ImportDescr;
import org.drools.drl.ast.descr.MVELExprDescr;
+import org.drools.drl.ast.descr.NamedConsequenceDescr;
import org.drools.drl.ast.descr.NotDescr;
import org.drools.drl.ast.descr.OrDescr;
import org.drools.drl.ast.descr.PackageDescr;
@@ -3997,4 +3999,173 @@ class MiscDRLParserTest {
.map(QualifiedName::getFullName)
.containsExactlyInAnyOrder("com.sample.ParentTrait",
"UncleTrait", "org.test.GrandParentTrait");
}
+
+ @Test
+ void namedConsequenceDo() {
+ final String text =
+ "rule R when\n" +
+ " $r : Result()\n" +
+ " $p1 : Person(name == \"Mark\")\n" +
+ " do[FoundMark]\n" +
+ " $p2 : Person(name != \"Mark\", age > $p1.age)\n" +
+ "then\n" +
+ " $r.addValue($p2.getName() + \" is older than \" +
$p1.getName());\n" +
+ "then[FoundMark]\n" +
+ " $r.addValue(\"Found \" + $p1.getName());\n" +
+ "end";
+ PackageDescr packageDescr = parser.parse(text);
+ RuleDescr ruleDescr = packageDescr.getRules().get(0);
+ NamedConsequenceDescr namedConsequenceDescr = (NamedConsequenceDescr)
ruleDescr.getLhs().getDescrs().get(2);
+ assertThat(namedConsequenceDescr.getName()).isEqualTo("FoundMark");
+
+
assertThat(ruleDescr.getConsequence().toString()).isEqualTo("$r.addValue($p2.getName()
+ \" is older than \" + $p1.getName());");
+
assertThat(ruleDescr.getNamedConsequences().get("FoundMark").toString()).isEqualTo("$r.addValue(\"Found
\" + $p1.getName());");
+ }
+
+ @Test
+ void namedConsequenceIfElse() {
+ final String text =
+ "rule R1 dialect \"mvel\" when\n" +
+ " $a: Cheese ( type == \"stilton\" )\n" +
+ " if ( $a.price > Cheese.BASE_PRICE ) do[t1] else
do[t2]\n" +
+ " $b: Cheese ( type == \"cheddar\" )\n" +
+ "then\n" +
+ " results.add( $b.getType() );\n" +
+ "then[t1]\n" +
+ " results.add( $a.getType() );\n" +
+ "then[t2]\n" +
+ " results.add( $a.getType().toUpperCase() );\n" +
+ "end\n";
+ PackageDescr packageDescr = parser.parse(text);
+ RuleDescr ruleDescr = packageDescr.getRules().get(0);
+ ConditionalBranchDescr conditionalBranchDescr =
(ConditionalBranchDescr) ruleDescr.getLhs().getDescrs().get(1);
+
assertThat(conditionalBranchDescr.getCondition().getContent().toString()).isEqualTo("$a.price
> Cheese.BASE_PRICE");
+
assertThat(conditionalBranchDescr.getConsequence().getName()).isEqualTo("t1");
+
assertThat(conditionalBranchDescr.getElseBranch().getConsequence().getName()).isEqualTo("t2");
+ }
+
+ @Test
+ void namedConsequenceIfElseBreak() {
+ final String text =
+ "rule R1 dialect \"mvel\" when\n" +
+ " $a: Cheese ( type == \"stilton\" )\n" +
+ " if ( $a.price > Cheese.BASE_PRICE ) break[t1]
else break[t2]\n" +
+ " $b: Cheese ( type == \"cheddar\" )\n" +
+ "then\n" +
+ " results.add( $b.getType() );\n" +
+ "then[t1]\n" +
+ " results.add( $a.getType() );\n" +
+ "then[t2]\n" +
+ " results.add( $a.getType().toUpperCase() );\n" +
+ "end\n";
+ PackageDescr packageDescr = parser.parse(text);
+ RuleDescr ruleDescr = packageDescr.getRules().get(0);
+ ConditionalBranchDescr conditionalBranchDescr =
(ConditionalBranchDescr) ruleDescr.getLhs().getDescrs().get(1);
+
assertThat(conditionalBranchDescr.getCondition().getContent().toString()).isEqualTo("$a.price
> Cheese.BASE_PRICE");
+
assertThat(conditionalBranchDescr.getConsequence().getName()).isEqualTo("t1");
+
assertThat(conditionalBranchDescr.getElseBranch().getConsequence().getName()).isEqualTo("t2");
+ }
+
+ @Test
+ void namedConsequenceNestedIf() {
+ final String text =
+ "rule R1 dialect \"mvel\" when\n" +
+ " $a: Cheese ( type == \"stilton\" )\n" +
+ " if ( $a.price > Cheese.BASE_PRICE ) do[t1] else
if ($a.price == Cheese.BASE_PRICE ) do[t2]\n" +
+ " $b: Cheese ( type == \"cheddar\" )\n" +
+ "then\n" +
+ " results.add( $b.getType() );\n" +
+ "then[t1]\n" +
+ " results.add( $a.getType() );\n" +
+ "then[t2]\n" +
+ " results.add( $a.getType().toUpperCase() );\n" +
+ "end\n";
+ PackageDescr packageDescr = parser.parse(text);
+ RuleDescr ruleDescr = packageDescr.getRules().get(0);
+ ConditionalBranchDescr conditionalBranchDescr =
(ConditionalBranchDescr) ruleDescr.getLhs().getDescrs().get(1);
+
assertThat(conditionalBranchDescr.getCondition().getContent().toString()).isEqualTo("$a.price
> Cheese.BASE_PRICE");
+
assertThat(conditionalBranchDescr.getConsequence().getName()).isEqualTo("t1");
+ ConditionalBranchDescr elseBranch =
conditionalBranchDescr.getElseBranch();
+
assertThat(elseBranch.getCondition().getContent().toString()).isEqualTo("$a.price
== Cheese.BASE_PRICE");
+ assertThat(elseBranch.getConsequence().getName()).isEqualTo("t2");
+ }
+
+ @Test
+ void namedConsequenceAfterExists() {
+ final String text =
+ "rule R when\n" +
+ " $r : Result()\n" +
+ " exists( Person(name == \"Mark\") )\n" +
+ " do[FoundMark]\n" +
+ " $p2 : Person(name != \"Mark\", age > $p1.age)\n" +
+ "then\n" +
+ " $r.addValue($p2.getName() + \" is older than \" +
$p1.getName());\n" +
+ "then[FoundMark]\n" +
+ " $r.addValue(\"Found \" + $p1.getName());\n" +
+ "end";
+ PackageDescr packageDescr = parser.parse(text);
+ RuleDescr ruleDescr = packageDescr.getRules().get(0);
+ NamedConsequenceDescr namedConsequenceDescr = (NamedConsequenceDescr)
ruleDescr.getLhs().getDescrs().get(2);
+ assertThat(namedConsequenceDescr.getName()).isEqualTo("FoundMark");
+ }
+
+ @Test
+ void namedConsequenceAfterNot() {
+ final String text =
+ "rule R when\n" +
+ " $r : Result()\n" +
+ " not( Person(name == \"Mark\") )\n" +
+ " do[NotFoundMark]\n" +
+ " $p2 : Person(name != \"Mark\", age > $p1.age)\n" +
+ "then\n" +
+ " $r.addValue($p2.getName() + \" is older than \" +
$p1.getName());\n" +
+ "then[FoundMark]\n" +
+ " $r.addValue(\"NotFound \" + $p1.getName());\n" +
+ "end";
+ PackageDescr packageDescr = parser.parse(text);
+ RuleDescr ruleDescr = packageDescr.getRules().get(0);
+ NamedConsequenceDescr namedConsequenceDescr = (NamedConsequenceDescr)
ruleDescr.getLhs().getDescrs().get(2);
+ assertThat(namedConsequenceDescr.getName()).isEqualTo("NotFoundMark");
+ }
+
+ @Test
+ void namedConsequenceIfElseAfterEval() {
+ final String text =
+ "rule R1 dialect \"mvel\" when\n" +
+ " $a: Cheese ( type == \"stilton\" )\n" +
+ " eval($a.price > 0) if ( $a.price >
Cheese.BASE_PRICE ) do[t1] else do[t2]\n" +
+ " $b: Cheese ( type == \"cheddar\" )\n" +
+ "then\n" +
+ " results.add( $b.getType() );\n" +
+ "then[t1]\n" +
+ " results.add( $a.getType() );\n" +
+ "then[t2]\n" +
+ " results.add( $a.getType().toUpperCase() );\n" +
+ "end\n";
+ PackageDescr packageDescr = parser.parse(text);
+ RuleDescr ruleDescr = packageDescr.getRules().get(0);
+ ConditionalBranchDescr conditionalBranchDescr =
(ConditionalBranchDescr) ruleDescr.getLhs().getDescrs().get(2);
+
assertThat(conditionalBranchDescr.getCondition().getContent().toString()).isEqualTo("$a.price
> Cheese.BASE_PRICE");
+
assertThat(conditionalBranchDescr.getConsequence().getName()).isEqualTo("t1");
+
assertThat(conditionalBranchDescr.getElseBranch().getConsequence().getName()).isEqualTo("t2");
+ }
+
+ @Test
+ void namedConsequenceAfterEnclosed() {
+ final String text =
+ "rule R when\n" +
+ " $r : Result()\n" +
+ " ( Person(name == \"Mark\") or Person(name ==
\"Mario\") )\n" +
+ " do[FoundMarkOrMario]\n" +
+ " $p2 : Person(name != \"Mark\", age > $p1.age)\n" +
+ "then\n" +
+ " $r.addValue($p2.getName() + \" is older than \" +
$p1.getName());\n" +
+ "then[FoundMark]\n" +
+ " $r.addValue(\"Found \" + $p1.getName());\n" +
+ "end";
+ PackageDescr packageDescr = parser.parse(text);
+ RuleDescr ruleDescr = packageDescr.getRules().get(0);
+ NamedConsequenceDescr namedConsequenceDescr = (NamedConsequenceDescr)
ruleDescr.getLhs().getDescrs().get(2);
+
assertThat(namedConsequenceDescr.getName()).isEqualTo("FoundMarkOrMario");
+ }
}
diff --git
a/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRLLexer.g4
b/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRLLexer.g4
index dc974ecac8..631d2a49a1 100644
---
a/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRLLexer.g4
+++
b/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRLLexer.g4
@@ -172,6 +172,8 @@ RHS_STRING_LITERAL
| ('\'' ( DrlEscapeSequence | ~('\\'|'\'') )* '\'') { setText(
normalizeString( getText() ) ); }
;
+RHS_NAMED_CONSEQUENCE_THEN : DRL_THEN LBRACK IDENTIFIER RBRACK ;
+
RHS_CHUNK
: ~[ ()[\]{},;\t\r\n\u000C]+ // ;}) could be a delimitter proceding 'end'.
()[]{},; are delimiters to match RHS_STRING_LITERAL
| LPAREN
diff --git
a/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRLParser.g4
b/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRLParser.g4
index 6e975bc3fe..e5cfc957cc 100644
---
a/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRLParser.g4
+++
b/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRLParser.g4
@@ -90,12 +90,12 @@ parameter : type? drlIdentifier ; // type is optional.
Removed (LEFT_SQUARE RIGH
lhs : DRL_WHEN lhsExpression* ;
-lhsExpression : LPAREN lhsExpression RPAREN #lhsExpressionEnclosed
- | lhsUnary #lhsUnarySingle
- | LPAREN DRL_AND lhsExpression+ RPAREN #lhsAnd
- | lhsExpression (DRL_AND lhsExpression)+ #lhsAnd
- | LPAREN DRL_OR lhsExpression+ RPAREN #lhsOr
- | lhsExpression (DRL_OR lhsExpression)+ #lhsOr
+lhsExpression : LPAREN lhsExpression RPAREN namedConsequenceInvocation?
#lhsExpressionEnclosed
+ | lhsUnary
#lhsUnarySingle
+ | LPAREN DRL_AND lhsExpression+ RPAREN #lhsAnd
+ | lhsExpression (DRL_AND lhsExpression)+ #lhsAnd
+ | LPAREN DRL_OR lhsExpression+ RPAREN #lhsOr
+ | lhsExpression (DRL_OR lhsExpression)+ #lhsOr
;
// lhsAnd is used as a label in lhsExpression rule. But some other rules
explicitly use the def, so lhsAndDef is declared.
@@ -110,18 +110,19 @@ lhsUnary : ( lhsExists namedConsequence?
| lhsEval consequenceInvocation*
| lhsForall
| lhsAccumulate
- | LPAREN lhsOr RPAREN namedConsequence?
+ | LPAREN lhsOr RPAREN namedConsequence? // this part is handled by
#lhsExpressionEnclosed
| lhsPatternBind consequenceInvocation*
) SEMI? ;
*/
lhsUnary : (
- lhsExists
- | lhsNot
- | lhsEval
+ lhsExists namedConsequenceInvocation?
+ | lhsNot namedConsequenceInvocation?
+ | lhsEval consequenceInvocation*
| lhsForall
| lhsAccumulate
- | lhsPatternBind
+ | conditionalBranch // not in the above old parser definition, but
actually implemented in the old parser
+ | lhsPatternBind consequenceInvocation*
) SEMI? ;
lhsPatternBind : (label|unif)? ( LPAREN lhsPattern (DRL_OR lhsPattern)* RPAREN
| lhsPattern ) ;
@@ -157,6 +158,25 @@ xpathPrimary : label? xpathChunk+ ;
xpathChunk : xpathSeparator drlIdentifier (DOT drlIdentifier)* (HASH
drlIdentifier)? (LBRACK xpathExpressionList RBRACK)? ;
xpathExpressionList : label? drlExpression (COMMA label? drlExpression)* ;
+// named consequence
+
+// consequenceInvocation := conditionalBranch | namedConsequence
+consequenceInvocation : conditionalBranch | namedConsequenceInvocation ;
+
+// conditionalBranch := IF LEFT_PAREN conditionalExpression RIGHT_PAREN
+// ( namedConsequence | breakingNamedConsequence )
+// ( ELSE ( namedConsequence | breakingNamedConsequence |
conditionalBranch ) )?
+conditionalBranch : IF LPAREN conditionalOrExpression RPAREN
+ ( do1=namedConsequenceInvocation |
break1=breakingNamedConsequenceInvocation )
+ ( ELSE ( do2=namedConsequenceInvocation |
break2=breakingNamedConsequenceInvocation | conditionalBranch ) )? ;
+
+// namedConsequence := DO LEFT_SQUARE ID RIGHT_SQUARE BREAK?
+namedConsequenceInvocation : DO LBRACK drlIdentifier RBRACK ; // BREAK? is not
actually implmented in the old parser
+
+// breakingNamedConsequence := BREAK LEFT_SQUARE ID RIGHT_SQUARE
+breakingNamedConsequenceInvocation : BREAK LBRACK drlIdentifier RBRACK ;
+
+
relationalOperator
: EQUAL
| NOTEQUAL
@@ -488,9 +508,12 @@ lhsAccumulate : (DRL_ACCUMULATE|DRL_ACC) LPAREN lhsAndDef
(COMMA|SEMI)
RPAREN (SEMI)?
;
-rhs : DRL_THEN consequence ;
+rhs : DRL_THEN consequenceBody namedConsequence* ;
+
+consequenceBody : ( RHS_STRING_LITERAL | RHS_CHUNK )* ;
-consequence : ( RHS_STRING_LITERAL | RHS_CHUNK )* ;
+// THEN LEFT_SQUARE ID RIGHT_SQUARE chunk
+namedConsequence : RHS_NAMED_CONSEQUENCE_THEN consequenceBody ;
stringId : ( IDENTIFIER | DRL_STRING_LITERAL ) ;
diff --git
a/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/Antlr4ParserStringUtils.java
b/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/Antlr4ParserStringUtils.java
index 86e841cc12..a33eb143dd 100644
---
a/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/Antlr4ParserStringUtils.java
+++
b/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/Antlr4ParserStringUtils.java
@@ -66,13 +66,13 @@ public class Antlr4ParserStringUtils {
}
/**
- * Just remove leading "then"
+ * Extract name from "then[name]" of RHS_NAMED_CONSEQUENCE_THEN
*/
- public static String trimThen(String rhs) {
- if (rhs.startsWith("then")) {
- return rhs.substring("then".length());
+ public static String extractNamedConsequenceName(String
namedConsequenceThen) {
+ if (namedConsequenceThen.toLowerCase().startsWith("then[") &&
namedConsequenceThen.endsWith("]")) {
+ return namedConsequenceThen.substring("then[".length(),
namedConsequenceThen.length() - 1);
} else {
- throw new DRLParserException("rhs has to start with 'then' : rhs =
" + rhs);
+ throw new DRLParserException("namedConsequenceThen has to be
surrounded by 'then[', ']' : " + namedConsequenceThen);
}
}
diff --git
a/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DRLVisitorImpl.java
b/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DRLVisitorImpl.java
index 846a9bff9e..ba9157897e 100644
---
a/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DRLVisitorImpl.java
+++
b/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/DRLVisitorImpl.java
@@ -35,6 +35,7 @@ import org.drools.drl.ast.descr.AttributeDescr;
import org.drools.drl.ast.descr.BaseDescr;
import org.drools.drl.ast.descr.BehaviorDescr;
import org.drools.drl.ast.descr.CollectDescr;
+import org.drools.drl.ast.descr.ConditionalBranchDescr;
import org.drools.drl.ast.descr.EntryPointDeclarationDescr;
import org.drools.drl.ast.descr.EntryPointDescr;
import org.drools.drl.ast.descr.EvalDescr;
@@ -47,6 +48,7 @@ import org.drools.drl.ast.descr.FunctionImportDescr;
import org.drools.drl.ast.descr.GlobalDescr;
import org.drools.drl.ast.descr.ImportDescr;
import org.drools.drl.ast.descr.MVELExprDescr;
+import org.drools.drl.ast.descr.NamedConsequenceDescr;
import org.drools.drl.ast.descr.NotDescr;
import org.drools.drl.ast.descr.OrDescr;
import org.drools.drl.ast.descr.PackageDescr;
@@ -60,9 +62,9 @@ import org.drools.drl.ast.descr.UnitDescr;
import org.drools.drl.ast.descr.WindowDeclarationDescr;
import org.drools.drl.ast.descr.WindowReferenceDescr;
+import static
org.drools.drl.parser.antlr4.Antlr4ParserStringUtils.extractNamedConsequenceName;
import static
org.drools.drl.parser.antlr4.Antlr4ParserStringUtils.getTextPreservingWhitespace;
import static
org.drools.drl.parser.antlr4.Antlr4ParserStringUtils.getTokenTextPreservingWhitespace;
-import static org.drools.drl.parser.antlr4.Antlr4ParserStringUtils.trimThen;
import static
org.drools.drl.parser.antlr4.DRLParserHelper.getTextWithoutErrorNode;
import static org.drools.drl.parser.util.ParserStringUtils.appendPrefix;
import static
org.drools.drl.parser.util.ParserStringUtils.safeStripStringDelimiters;
@@ -292,8 +294,17 @@ public class DRLVisitorImpl extends
DRLParserBaseVisitor<Object> {
}
if (ctx.rhs() != null) {
+ // default consequence
ruleDescr.setConsequenceLocation(ctx.rhs().getStart().getLine(),
ctx.rhs().getStart().getCharPositionInLine()); // location of "then"
-
ruleDescr.setConsequence(trimThen(getTokenTextPreservingWhitespace(ctx.rhs(),
tokenStream))); // RHS is just a text
+
ruleDescr.setConsequence(getTokenTextPreservingWhitespace(ctx.rhs().consequenceBody(),
tokenStream)); // RHS is just a text
+
+ // named consequences
+ ctx.rhs().namedConsequence()
+ .forEach(namedConsequenceCtx -> {
+ String name =
extractNamedConsequenceName(namedConsequenceCtx.RHS_NAMED_CONSEQUENCE_THEN().getText());
+ String body =
getTokenTextPreservingWhitespace(namedConsequenceCtx.consequenceBody(),
tokenStream);
+ ruleDescr.addNamedConsequences(name, body);
+ } );
}
return ruleDescr;
@@ -558,6 +569,74 @@ public class DRLVisitorImpl extends
DRLParserBaseVisitor<Object> {
patternDescr.addConstraint(exprConstraintDescr);
}
+ @Override
+ public NamedConsequenceDescr
visitNamedConsequenceInvocation(DRLParser.NamedConsequenceInvocationContext
ctx) {
+ NamedConsequenceDescr namedConsequenceDescr =
BaseDescrFactory.builder(new
NamedConsequenceDescr(ctx.drlIdentifier().getText()))
+ .withParserRuleContext(ctx)
+ .build();
+ return namedConsequenceDescr;
+ }
+
+ @Override
+ public NamedConsequenceDescr
visitBreakingNamedConsequenceInvocation(DRLParser.BreakingNamedConsequenceInvocationContext
ctx) {
+ NamedConsequenceDescr namedConsequenceDescr =
BaseDescrFactory.builder(new
NamedConsequenceDescr(ctx.drlIdentifier().getText()))
+ .withParserRuleContext(ctx)
+ .build();
+ namedConsequenceDescr.setBreaking(true);
+ return namedConsequenceDescr;
+ }
+
+ /**
+ * process
+ *
+ * if (condition) do[namedConsequence1] else do[namedConsequence2]
+ *
+ * into a ConditionalBranchDescr
+ */
+ @Override
+ public ConditionalBranchDescr
visitConditionalBranch(DRLParser.ConditionalBranchContext ctx) {
+ ConditionalBranchDescr conditionalBranchDescr =
BaseDescrFactory.builder(new ConditionalBranchDescr())
+ .withParserRuleContext(ctx)
+ .build();
+ EvalDescr evalDescr = BaseDescrFactory.builder(new EvalDescr())
+ .withParserRuleContext(ctx.conditionalOrExpression())
+ .build();
+
evalDescr.setContent(getTextPreservingWhitespace(ctx.conditionalOrExpression()));
+ conditionalBranchDescr.setCondition(evalDescr);
+
+ // main branch
+ if (ctx.do1 != null) {
+ NamedConsequenceDescr namedConsequenceDescr =
visitNamedConsequenceInvocation(ctx.do1);
+ conditionalBranchDescr.setConsequence(namedConsequenceDescr);
+ } else if (ctx.break1 != null) {
+ NamedConsequenceDescr namedConsequenceDescr =
visitBreakingNamedConsequenceInvocation(ctx.break1);
+ conditionalBranchDescr.setConsequence(namedConsequenceDescr);
+ }
+
+ // else branch
+ if (ctx.do2 != null) {
+ ConditionalBranchDescr elseBranchDescr =
BaseDescrFactory.builder(new ConditionalBranchDescr())
+ .withParserRuleContext(ctx.do2)
+ .build();
+ conditionalBranchDescr.setElseBranch(elseBranchDescr);
+ NamedConsequenceDescr namedConsequenceDescr =
visitNamedConsequenceInvocation(ctx.do2);
+ elseBranchDescr.setConsequence(namedConsequenceDescr);
+ } else if (ctx.break2 != null) {
+ ConditionalBranchDescr elseBranchDescr =
BaseDescrFactory.builder(new ConditionalBranchDescr())
+ .withParserRuleContext(ctx.break2)
+ .build();
+ conditionalBranchDescr.setElseBranch(elseBranchDescr);
+ NamedConsequenceDescr namedConsequenceDescr =
visitBreakingNamedConsequenceInvocation(ctx.break2);
+ elseBranchDescr.setConsequence(namedConsequenceDescr);
+ } else if (ctx.conditionalBranch() != null) {
+ // nested if
+ ConditionalBranchDescr nestedConditionalBranchDescr =
visitConditionalBranch(ctx.conditionalBranch());
+ conditionalBranchDescr.setElseBranch(nestedConditionalBranchDescr);
+ }
+
+ return conditionalBranchDescr;
+ }
+
@Override
public ForallDescr visitLhsForall(DRLParser.LhsForallContext ctx) {
ForallDescr forallDescr = BaseDescrFactory.builder(new ForallDescr())
@@ -792,9 +871,9 @@ public class DRLVisitorImpl extends
DRLParserBaseVisitor<Object> {
}
@Override
- public BaseDescr
visitLhsExpressionEnclosed(DRLParser.LhsExpressionEnclosedContext ctx) {
+ public List<BaseDescr>
visitLhsExpressionEnclosed(DRLParser.LhsExpressionEnclosedContext ctx) {
// enclosed expression is simply stripped because Descr itself is
encapsulated
- return (BaseDescr) visit(ctx.lhsExpression());
+ return visitDescrChildren(ctx);
}
@Override
@@ -887,8 +966,8 @@ public class DRLVisitorImpl extends
DRLParserBaseVisitor<Object> {
}
@Override
- public BaseDescr visitLhsUnary(DRLParser.LhsUnaryContext ctx) {
- return visitDescrChildren(ctx).get(0); // lhsUnary has only one child
+ public List<BaseDescr> visitLhsUnary(DRLParser.LhsUnaryContext ctx) {
+ return visitDescrChildren(ctx); // lhsUnary may have
consequenceInvocation, so not always a single child
}
/**
@@ -924,6 +1003,9 @@ public class DRLVisitorImpl extends
DRLParserBaseVisitor<Object> {
Object childResult = c.accept(this);
if (childResult instanceof BaseDescr) {
aggregator.add(new DescrNodePair((BaseDescr) childResult, c));
// pairing the returned Descr and the parser node
+ } else if (childResult instanceof List) {
+ List<BaseDescr> descrList = (List<BaseDescr>) childResult;
+ descrList.forEach(descr -> aggregator.add(new
DescrNodePair(descr, c))); // pairing the returned Descr and the parser node
}
}
return aggregator;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]