From 4acd6db163650ee26068b3e54c688794b605afe4 Mon Sep 17 00:00:00 2001 From: Toshiya Kobayashi Date: Thu, 3 Nov 2022 16:23:55 +0900 Subject: [PATCH] Enhance test/grammar coverage. OR, inline map (#13) --- .../antlr4/org/drools/parser/DRLParser.g4 | 15 +- .../org/drools/parser/DRLVisitorImpl.java | 17 ++- .../org/drools/parser/MiscDRLParserTest.java | 136 ++++++++++++++++++ .../parser/literal_bool_and_negative.drl | 25 ++++ .../org/drools/parser/test_EmptyPattern.drl | 24 ++++ .../parser/test_SimpleMethodCallWithFrom.drl | 25 ++++ 6 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/literal_bool_and_negative.drl create mode 100644 drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_EmptyPattern.drl create mode 100644 drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleMethodCallWithFrom.drl 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 00c61cbc1e5..4684804a10f 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 @@ -64,7 +64,7 @@ lhsPattern : xpathPrimary (OVER patternFilter)? | ( QUESTION? qualifiedIdentifier LPAREN positionalConstraints? constraints? RPAREN (OVER patternFilter)? (FROM patternSource)? ) ; */ -lhsPattern : QUESTION? objectType=drlQualifiedName LPAREN (positionalConstraints? constraints? ) RPAREN (DRL_FROM patternSource)? ; +lhsPattern : QUESTION? objectType=drlQualifiedName LPAREN positionalConstraints? constraints? RPAREN (DRL_FROM patternSource)? ; positionalConstraints : constraint (COMMA constraint)* SEMI ; constraints : constraint (COMMA constraint)* ; constraint : label? ( nestedConstraint | conditionalOrExpression ) ; @@ -198,6 +198,7 @@ drlPrimary | typeTypeOrVoid DOT CLASS | nonWildcardTypeArguments (explicitGenericInvocationSuffix | THIS arguments) | inlineListExpression + | inlineMapExpression ; /* extending JavaParser literal */ @@ -219,6 +220,18 @@ expressionList : drlExpression (COMMA drlExpression)* ; +inlineMapExpression + : LBRACK mapExpressionList RBRACK + ; + +mapExpressionList + : mapEntry (COMMA mapEntry)* + ; + +mapEntry + : drlExpression COLON drlExpression + ; + /* patternSource := FROM ( fromAccumulate 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 28775cfa8d9..a152733d179 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 @@ -214,7 +214,6 @@ public Object visitDrlIdentifier(DRLParser.DrlIdentifierContext ctx) { return ctx.getText(); } - @Override public Object visitDrlLiteral(DRLParser.DrlLiteralContext ctx) { ParseTree node = ctx; @@ -277,6 +276,22 @@ public Object visitLhsNot(DRLParser.LhsNotContext ctx) { } } + @Override + public Object visitLhsOr(DRLParser.LhsOrContext ctx) { + if (!ctx.DRL_OR().isEmpty()) { + OrDescr orDescr = new OrDescr(); + currentConstructStack.peek().addDescr(orDescr); + currentConstructStack.push(orDescr); + try { + return super.visitLhsOr(ctx); + } finally { + currentConstructStack.pop(); + } + } else { + return super.visitLhsOr(ctx); + } + } + public PackageDescr getPackageDescr() { return packageDescr; } 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 48d3460f62a..596aa5f926c 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 @@ -20,6 +20,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.NotDescr; import org.drools.drl.ast.descr.OrDescr; import org.drools.drl.ast.descr.PackageDescr; @@ -681,4 +682,139 @@ public void testConsequenceWithDeclaration() throws Exception { assertTrue( ((String) rule.getConsequence()).indexOf( "i++" ) > 0 ); // note, need to assert that "i++" is preserved as is, no extra spaces. } + + @Test + public void testRuleParseLhs() throws Exception { + final String text = "rule X when Person(age < 42, location==\"atlanta\") \nor\nPerson(name==\"bob\") then end"; + PackageDescr pkg = parser.parse(text); + RuleDescr rule = (RuleDescr) pkg.getRules().get(0); + + assertFalse(parser.getErrors().toString(), + parser.hasErrors()); + + assertNotNull(rule); + + AndDescr lhs = rule.getLhs(); + assertEquals(1, + lhs.getDescrs().size()); + assertEquals(2, + ((OrDescr) lhs.getDescrs().get(0)).getDescrs().size()); + } + + @Test + public void testRuleParseLhsWithStringQuotes() throws Exception { + final String text = "rule X when Person( location==\"atlanta\\\"\") then end\n"; + PackageDescr pkg = parser.parse(text); + RuleDescr rule = (RuleDescr) pkg.getRules().get(0); + + assertFalse(parser.getErrors().toString(), + parser.hasErrors()); + + assertNotNull(rule); + + AndDescr lhs = rule.getLhs(); + ExprConstraintDescr constr = (ExprConstraintDescr) ((PatternDescr) lhs.getDescrs().get(0)).getDescrs().get(0); + + assertThat(constr.getText()).isEqualToIgnoringWhitespace("location==\"atlanta\\\"\""); + } + + @Test + public void testRuleParseLhsWithStringQuotes2() throws Exception { + final String text = "rule X when Cheese( $x: type, type == \"s\\tti\\\"lto\\nn\" ) then end\n"; + PackageDescr pkg = parser.parse(text); + RuleDescr rule = (RuleDescr) pkg.getRules().get(0); + assertFalse(parser.getErrors().toString(), + parser.hasErrors()); + + assertNotNull(rule); + + AndDescr lhs = rule.getLhs(); + ExprConstraintDescr constr = (ExprConstraintDescr) ((PatternDescr) lhs.getDescrs().get(0)).getDescrs().get(1); + + assertThat(constr.getText()).isEqualToIgnoringWhitespace("type == \"s\\tti\\\"lto\\nn\""); + } + + @Test + public void testLiteralBoolAndNegativeNumbersRule() throws Exception { + String source = readResource("literal_bool_and_negative.drl"); + PackageDescr pkg = parser.parse(source); + RuleDescr rule = (RuleDescr) pkg.getRules().get(0); + + assertFalse(parser.getErrors().toString(), + parser.hasErrors()); + + assertNotNull(rule); + + assertEquals("simple_rule", + rule.getName()); + assertNotNull(rule.getLhs()); + + assertThat((String) rule.getConsequence()).isEqualToIgnoringWhitespace("cons();"); + + final AndDescr lhs = rule.getLhs(); + assertEquals(3, + lhs.getDescrs().size()); + + PatternDescr pattern = (PatternDescr) lhs.getDescrs().get(0); + assertEquals(1, + pattern.getConstraint().getDescrs().size()); + AndDescr fieldAnd = (AndDescr) pattern.getConstraint(); + ExprConstraintDescr fld = (ExprConstraintDescr) fieldAnd.getDescrs().get(0); + assertThat(fld.getExpression()).isEqualToIgnoringWhitespace("bar == false"); + + pattern = (PatternDescr) lhs.getDescrs().get(1); + assertEquals(1, + pattern.getConstraint().getDescrs().size()); + + fieldAnd = (AndDescr) pattern.getConstraint(); + fld = (ExprConstraintDescr) fieldAnd.getDescrs().get(0); + + assertThat(fld.getText()).isEqualToIgnoringWhitespace("boo > -42"); + + pattern = (PatternDescr) lhs.getDescrs().get(2); + assertEquals(1, + pattern.getConstraint().getDescrs().size()); + + fieldAnd = (AndDescr) pattern.getConstraint(); + fld = (ExprConstraintDescr) fieldAnd.getDescrs().get(0); + + assertThat(fld.getText()).isEqualToIgnoringWhitespace("boo > -42.42"); + } + + @Test + public void testEmptyPattern() throws Exception { + String source = readResource("test_EmptyPattern.drl"); + PackageDescr pkg = parser.parse(source); + + assertFalse(parser.getErrors().toString(), + parser.hasErrors()); + + assertEquals(1, + pkg.getRules().size()); + final RuleDescr ruleDescr = (RuleDescr) pkg.getRules().get(0); + assertEquals("simple rule", + ruleDescr.getName()); + assertNotNull(ruleDescr.getLhs()); + assertEquals(1, + ruleDescr.getLhs().getDescrs().size()); + final PatternDescr patternDescr = (PatternDescr) ruleDescr.getLhs().getDescrs().get(0); + assertEquals(0, + patternDescr.getConstraint().getDescrs().size()); // this + assertEquals("Cheese", + patternDescr.getObjectType()); + } + + @Test + public void testSimpleMethodCallWithFrom() throws Exception { + String source = readResource("test_SimpleMethodCallWithFrom.drl"); + PackageDescr pkg = parser.parse(source); + assertFalse(parser.getErrors().toString(), + parser.hasErrors()); + RuleDescr rule = (RuleDescr) pkg.getRules().get(0); + final PatternDescr pattern = (PatternDescr) rule.getLhs().getDescrs().get(0); + final FromDescr from = (FromDescr) pattern.getSource(); + final MVELExprDescr method = (MVELExprDescr) from.getDataSource(); + + assertThat(method.getExpression()).isEqualToIgnoringWhitespace("something.doIt( foo,bar,42,\"hello\",[ a : \"b\", \"something\" : 42, \"a\" : foo, x : [x:y]],\"end\", [a, \"b\", 42] )"); + } } diff --git a/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/literal_bool_and_negative.drl b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/literal_bool_and_negative.drl new file mode 100644 index 00000000000..ce6ee78c0c6 --- /dev/null +++ b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/literal_bool_and_negative.drl @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +//check that it can handle true/false literals, and +//negative numbers +rule simple_rule + when + Foo(bar == false) + Foo(boo > -42) + Foo(boo > -42.42) + then + cons(); +end diff --git a/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_EmptyPattern.drl b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_EmptyPattern.drl new file mode 100644 index 00000000000..0c70f0ce121 --- /dev/null +++ b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_EmptyPattern.drl @@ -0,0 +1,24 @@ +/* + * Copyright 2015 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package org.drools.compiler.test; + +import org.drools.compiler.Cheese; + +rule "simple rule" + when + Cheese( ) + then +end \ No newline at end of file diff --git a/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleMethodCallWithFrom.drl b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleMethodCallWithFrom.drl new file mode 100644 index 00000000000..8c6b5be3be4 --- /dev/null +++ b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/test_SimpleMethodCallWithFrom.drl @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + + +rule blah + + when + + Col1() from something.doIt( foo,bar,42,"hello",[ a : "b", "something" : 42, "a" : foo, x : [x:y]],"end", [a, "b", 42] ) + Col2() + then + partay(); +end