You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by ma...@apache.org on 2024/02/14 11:52:37 UTC
(incubator-kie-drools) 12/49: Enhance test/grammar coverage. and, or, listExpression (#7)
This is an automated email from the ASF dual-hosted git repository.
mariofusco pushed a commit to branch dev-new-parser
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git
commit 37185cf825775b9c73c9172028b9c64747de1fe7
Author: Toshiya Kobayashi <to...@gmail.com>
AuthorDate: Sun May 29 16:34:48 2022 +0900
Enhance test/grammar coverage. and, or, listExpression (#7)
---
drools-drl/drools-drl10-parser/pom.xml | 6 ++
.../src/main/antlr4/org/drools/parser/DRLLexer.g4 | 3 +
.../src/main/antlr4/org/drools/parser/DRLParser.g4 | 28 ++++-
.../java/org/drools/parser/DRLVisitorImpl.java | 52 ++++++---
.../java/org/drools/parser/MiscDRLParserTest.java | 120 +++++++++++++++++++++
5 files changed, 192 insertions(+), 17 deletions(-)
diff --git a/drools-drl/drools-drl10-parser/pom.xml b/drools-drl/drools-drl10-parser/pom.xml
index 599ec8ab07..93eefbc5d0 100644
--- a/drools-drl/drools-drl10-parser/pom.xml
+++ b/drools-drl/drools-drl10-parser/pom.xml
@@ -47,6 +47,12 @@
<version>${version.junit}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>${version.org.assertj}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
diff --git a/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLLexer.g4 b/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLLexer.g4
index 0f4ee3cc48..8ba1364c40 100644
--- a/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLLexer.g4
+++ b/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLLexer.g4
@@ -32,6 +32,9 @@ WHEN : 'when';
THEN : 'then';
END : 'end';
+KWD_AND : 'and';
+KWD_OR : 'or';
+
EXISTS : 'exists';
NOT : 'not';
IN : 'in';
diff --git a/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLParser.g4 b/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLParser.g4
index 2818590bd5..c9db7951aa 100644
--- a/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLParser.g4
+++ b/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRLParser.g4
@@ -19,8 +19,8 @@ ruledef : RULE name=stringId (EXTENDS stringId)? drlAnnotation* attributes? WHEN
lhs : lhsExpression ;
lhsExpression : lhsOr* ;
-lhsOr : LPAREN OR lhsAnd+ RPAREN | lhsAnd (OR lhsAnd)* ;
-lhsAnd : LPAREN AND lhsUnary+ RPAREN | lhsUnary (AND lhsUnary)* ;
+lhsOr : LPAREN KWD_OR lhsAnd+ RPAREN | lhsAnd (KWD_OR lhsAnd)* ;
+lhsAnd : LPAREN KWD_AND lhsUnary+ RPAREN | lhsUnary (KWD_AND lhsUnary)* ;
/*
lhsUnary : ( lhsExists namedConsequence?
@@ -38,7 +38,7 @@ lhsUnary : (
| lhsNot
| lhsPatternBind
) ;
-lhsPatternBind : label? ( LPAREN lhsPattern (OR lhsPattern)* RPAREN | lhsPattern ) ;
+lhsPatternBind : label? ( LPAREN lhsPattern (KWD_OR lhsPattern)* RPAREN | lhsPattern ) ;
/*
lhsPattern : xpathPrimary (OVER patternFilter)? |
@@ -58,7 +58,27 @@ andExpression : left=equalityExpression (BITAND right=equalityExpression)* ;
equalityExpression : left=instanceOfExpression ( ( op=EQUAL | op=NOTEQUAL ) right=instanceOfExpression )* ;
instanceOfExpression : left=inExpression ( 'instanceof' right=type )? ;
inExpression : left=relationalExpression ( 'not'? 'in' LPAREN drlExpression (COMMA drlExpression)* RPAREN )? ;
-relationalExpression : expression? ; // TODO
+relationalExpression : expression? ; // TODO : shiftExpression, additiveExpression, multiplicativeExpression, unaryExpression, unaryExpressionNotPlusMinus, ..., primary
+
+/* extending JavaParser */
+primary
+ : LPAREN expression RPAREN
+ | THIS
+ | SUPER
+ | literal
+ | identifier
+ | typeTypeOrVoid DOT CLASS
+ | nonWildcardTypeArguments (explicitGenericInvocationSuffix | THIS arguments)
+ | inlineListExpression
+ ;
+
+inlineListExpression
+ : LBRACK expressionList? RBRACK
+ ;
+
+expressionList
+ : expression (COMMA expression)*
+ ;
drlExpression : conditionalExpression ( op=assignmentOperator right=drlExpression )? ;
conditionalExpression : left=conditionalOrExpression ternaryExpression? ;
diff --git a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java
index d93c707abe..98f6388b49 100644
--- a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java
+++ b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLVisitorImpl.java
@@ -2,6 +2,7 @@ package org.drools.parser;
import java.util.ArrayDeque;
import java.util.Deque;
+import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -19,7 +20,8 @@ public class DRLVisitorImpl extends DRLParserBaseVisitor<Object> {
private RuleDescr currentRule;
private PatternDescr currentPattern;
- private Deque<ConditionalElementDescr> currentConstructStack = new ArrayDeque<>(); // e.g. whole LHS, not, exist
+
+ private final Deque<ConditionalElementDescr> currentConstructStack = new ArrayDeque<>(); // e.g. whole LHS (= AndDescr), NotDescr, ExistsDescr
@Override
public Object visitCompilationUnit(DRLParser.CompilationUnitContext ctx) {
@@ -86,23 +88,47 @@ public class DRLVisitorImpl extends DRLParserBaseVisitor<Object> {
@Override
public Object visitLhsPatternBind(DRLParser.LhsPatternBindContext ctx) {
- // TODO: this logic will likely be split to visitLhsPattern
if (ctx.lhsPattern().size() == 1) {
- DRLParser.LhsPatternContext lhsPatternCtx = ctx.lhsPattern(0);
- currentPattern = new PatternDescr(lhsPatternCtx.objectType.getText());
+ Object result = super.visitLhsPatternBind(ctx);
+ PatternDescr patternDescr = (PatternDescr) currentConstructStack.peek().getDescrs().get(0);
if (ctx.label() != null) {
- currentPattern.setIdentifier(ctx.label().IDENTIFIER().getText());
+ patternDescr.setIdentifier(ctx.label().IDENTIFIER().getText());
}
- if (lhsPatternCtx.patternSource() != null) {
- String expression = lhsPatternCtx.patternSource().getText();
- FromDescr from = new FromDescr();
- from.setDataSource(new MVELExprDescr(expression));
- from.setResource(currentPattern.getResource());
- currentPattern.setSource(from);
+ return result;
+ } else if (ctx.lhsPattern().size() > 1) {
+ OrDescr orDescr = new OrDescr();
+ currentConstructStack.peek().addDescr(orDescr);
+ currentConstructStack.push(orDescr);
+ try {
+ Object result = super.visitLhsPatternBind(ctx);
+ List<? extends BaseDescr> descrs = orDescr.getDescrs();
+ for (BaseDescr descr : descrs) {
+ PatternDescr patternDescr = (PatternDescr) descr;
+ if (ctx.label() != null) {
+ patternDescr.setIdentifier(ctx.label().IDENTIFIER().getText());
+ }
+ }
+ return result;
+ } finally {
+ currentConstructStack.pop();
}
- currentConstructStack.peek().addDescr(currentPattern);
+ } else {
+ throw new IllegalStateException("ctx.lhsPattern().size() == 0 : " + ctx.getText());
+ }
+ }
+
+ @Override
+ public Object visitLhsPattern(DRLParser.LhsPatternContext ctx) {
+ currentPattern = new PatternDescr(ctx.objectType.getText());
+ if (ctx.patternSource() != null) {
+ String expression = ctx.patternSource().getText();
+ FromDescr from = new FromDescr();
+ from.setDataSource(new MVELExprDescr(expression));
+ from.setResource(currentPattern.getResource());
+ currentPattern.setSource(from);
}
- Object result = super.visitLhsPatternBind(ctx);
+ Object result = super.visitLhsPattern(ctx);
+ currentConstructStack.peek().addDescr(currentPattern);
currentPattern = null;
return result;
}
diff --git a/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/MiscDRLParserTest.java b/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/MiscDRLParserTest.java
index caabed1592..07746c0299 100644
--- a/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/MiscDRLParserTest.java
+++ b/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/MiscDRLParserTest.java
@@ -10,11 +10,15 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import junit.framework.TestCase;
+import org.assertj.core.api.Assertions;
+import org.drools.drl.ast.descr.AndDescr;
+import org.drools.drl.ast.descr.BaseDescr;
import org.drools.drl.ast.descr.FromDescr;
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.NotDescr;
+import org.drools.drl.ast.descr.OrDescr;
import org.drools.drl.ast.descr.PackageDescr;
import org.drools.drl.ast.descr.PatternDescr;
import org.drools.drl.ast.descr.RuleDescr;
@@ -22,6 +26,8 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import static org.assertj.core.api.Assertions.assertThat;
+
/*
* This test class is being ported from org.drools.mvel.compiler.lang.RuleParserTest
*/
@@ -277,4 +283,118 @@ public class MiscDRLParserTest extends TestCase {
assertEquals("customerService.getCustomer(o.getCustomerId())",
((FromDescr) customer.getSource()).getDataSource().getText());
}
+
+ @Test
+ public void testFromWithInlineList() throws Exception {
+ String source = "rule XYZ \n" +
+ " when \n" +
+ " o: Order( ) \n" +
+ " not( Number( ) from [1, 2, 3] ) \n" +
+ " then \n" +
+ " System.err.println(\"Invalid customer id found!\"); \n" +
+ " o.addError(\"Invalid customer id\"); \n" +
+ "end \n";
+ PackageDescr pkg = parser.parse(source);
+ assertFalse(parser.getErrors().toString(),
+ parser.hasErrors());
+
+ RuleDescr rule = (RuleDescr) pkg.getRules().get(0);
+ assertEquals("XYZ",
+ rule.getName());
+
+ PatternDescr number = (PatternDescr) ((NotDescr) rule.getLhs().getDescrs().get(1)).getDescrs().get(0);
+ assertThat(((FromDescr) number.getSource()).getDataSource().toString()).isEqualToIgnoringWhitespace("[1, 2, 3]");
+ }
+
+ @Test
+ public void testFromWithInlineListMethod() throws Exception {
+ String source = "rule XYZ \n" +
+ " when \n" +
+ " o: Order( ) \n" +
+ " Number( ) from [1, 2, 3].sublist(1, 2) \n" +
+ " then \n" +
+ " System.err.println(\"Invalid customer id found!\"); \n" +
+ " o.addError(\"Invalid customer id\"); \n" +
+ "end \n";
+ PackageDescr pkg = parser.parse(source);
+ assertFalse(parser.getErrors().toString(),
+ parser.hasErrors());
+
+ RuleDescr rule = (RuleDescr) pkg.getRules().get(0);
+ assertEquals("XYZ",
+ rule.getName());
+
+ assertFalse(parser.hasErrors());
+ PatternDescr number = (PatternDescr) rule.getLhs().getDescrs().get(1);
+
+ assertThat(((FromDescr) number.getSource()).getDataSource().toString()).isEqualToIgnoringWhitespace("[1, 2, 3].sublist(1, 2)");
+ }
+
+ @Test
+ public void testFromWithInlineListIndex() throws Exception {
+ String source = "rule XYZ \n" +
+ " when \n" +
+ " o: Order( ) \n" +
+ " Number( ) from [1, 2, 3][1] \n" +
+ " then \n" +
+ " System.err.println(\"Invalid customer id found!\"); \n" +
+ " o.addError(\"Invalid customer id\"); \n" +
+ "end \n";
+ PackageDescr pkg = parser.parse(source);
+
+ assertFalse(parser.getErrors().toString(),
+ parser.hasErrors());
+
+ RuleDescr rule = (RuleDescr) pkg.getRules().get(0);
+ assertEquals("XYZ",
+ rule.getName());
+
+ assertFalse(parser.hasErrors());
+ PatternDescr number = (PatternDescr) rule.getLhs().getDescrs().get(1);
+ assertThat(((FromDescr) number.getSource()).getDataSource().toString()).isEqualToIgnoringWhitespace("[1, 2, 3][1]");
+ }
+
+ @Test
+ public void testRuleWithoutEnd() throws Exception {
+ String source = "rule \"Invalid customer id\" \n" +
+ " when \n" +
+ " o: Order( ) \n" +
+ " then \n" +
+ " System.err.println(\"Invalid customer id found!\"); \n";
+ parser.parse(source);
+ assertTrue(parser.hasErrors());
+ }
+
+ @Test
+ public void testOrWithSpecialBind() throws Exception {
+ String source = "rule \"A and (B or C or D)\" \n" +
+ " when \n" +
+ " pdo1 : ParametricDataObject( paramID == 101, stringValue == \"1000\" ) and \n" +
+ " pdo2 :(ParametricDataObject( paramID == 101, stringValue == \"1001\" ) or \n" +
+ " ParametricDataObject( paramID == 101, stringValue == \"1002\" ) or \n" +
+ " ParametricDataObject( paramID == 101, stringValue == \"1003\" )) \n" +
+ " then \n" +
+ " System.out.println( \"Rule: A and (B or C or D) Fired. pdo1: \" + pdo1 + \" pdo2: \"+ pdo2); \n" +
+ "end\n";
+ PackageDescr pkg = parser.parse(source);
+ assertFalse(parser.getErrors().toString(),
+ parser.hasErrors());
+
+ RuleDescr rule = pkg.getRules().get(0);
+ AndDescr lhs = rule.getLhs();
+ assertEquals(2,
+ lhs.getDescrs().size());
+
+ PatternDescr pdo1 = (PatternDescr) lhs.getDescrs().get(0);
+ assertEquals("pdo1",
+ pdo1.getIdentifier());
+
+ OrDescr or = (OrDescr) rule.getLhs().getDescrs().get(1);
+ assertEquals(3,
+ or.getDescrs().size());
+ for (BaseDescr pdo2 : or.getDescrs()) {
+ assertEquals("pdo2",
+ ((PatternDescr) pdo2).getIdentifier());
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org