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 22fc046f425c064d6b2235de4f4cc1dbd55bb7ed Author: Toshiya Kobayashi <[email protected]> AuthorDate: Thu Sep 22 19:32:46 2022 +0900 Enhance test/grammar coverage. keyword collision (#11) - Add "DRL_" prefix for DRL keywords for clarification --- .../src/main/antlr4/org/drools/parser/DRLLexer.g4 | 78 ++++---- .../src/main/antlr4/org/drools/parser/DRLParser.g4 | 197 +++++++++++++++++++-- .../java/org/drools/parser/DRLVisitorImpl.java | 15 +- .../java/org/drools/parser/MiscDRLParserTest.java | 12 ++ .../org/drools/parser/eol_funny_business.drl | 35 ++++ 5 files changed, 272 insertions(+), 65 deletions(-) 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 ed2416b6ac..f92c120d0a 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 @@ -18,45 +18,45 @@ import JavaLexer; // KEYWORDS ///////////////// -PACKAGE : 'package'; -UNIT : 'unit'; -IMPORT : 'import'; -FUNCTION : 'function'; -STATIC : 'static'; -GLOBAL : 'global'; -RULE : 'rule'; -QUERY : 'query'; -EXTENDS : 'extends'; -SUPER : 'super'; -WHEN : 'when'; -THEN : 'then'; -END : 'end'; - -KWD_AND : 'and'; -KWD_OR : 'or'; - -EXISTS : 'exists'; -NOT : 'not'; -IN : 'in'; -FROM : 'from'; -MATCHES : 'matches'; - -SALIENCE : 'salience'; -ENABLED : 'enabled'; -NO_LOOP : 'no-loop'; -AUTO_FOCUS : 'auto-focus'; -LOCK_ON_ACTIVE : 'lock-on-active'; -REFRACT : 'refract'; -DIRECT : 'direct'; -AGENDA_GROUP : 'agenda-group'; -ACTIVATION_GROUP : 'activation-group'; -RULEFLOW_GROUP : 'ruleflow-group'; -DATE_EFFECTIVE : 'date-effective'; -DATE_EXPIRES : 'date-expires'; -DIALECT : 'dialect'; -CALENDARS : 'calendars'; -TIMER : 'timer'; -DURATION : 'duration'; +DRL_PACKAGE : 'package'; +DRL_UNIT : 'unit'; +DRL_IMPORT : 'import'; +DRL_FUNCTION : 'function'; +DRL_STATIC : 'static'; +DRL_GLOBAL : 'global'; +DRL_RULE : 'rule'; +DRL_QUERY : 'query'; +DRL_EXTENDS : 'extends'; +DRL_SUPER : 'super'; +DRL_WHEN : 'when'; +DRL_THEN : 'then'; +DRL_END : 'end'; + +DRL_AND : 'and'; +DRL_OR : 'or'; + +DRL_EXISTS : 'exists'; +DRL_NOT : 'not'; +DRL_IN : 'in'; +DRL_FROM : 'from'; +DRL_MATCHES : 'matches'; + +DRL_SALIENCE : 'salience'; +DRL_ENABLED : 'enabled'; +DRL_NO_LOOP : 'no-loop'; +DRL_AUTO_FOCUS : 'auto-focus'; +DRL_LOCK_ON_ACTIVE : 'lock-on-active'; +DRL_REFRACT : 'refract'; +DRL_DIRECT : 'direct'; +DRL_AGENDA_GROUP : 'agenda-group'; +DRL_ACTIVATION_GROUP : 'activation-group'; +DRL_RULEFLOW_GROUP : 'ruleflow-group'; +DRL_DATE_EFFECTIVE : 'date-effective'; +DRL_DATE_EXPIRES : 'date-expires'; +DRL_DIALECT : 'dialect'; +DRL_CALENDARS : 'calendars'; +DRL_TIMER : 'timer'; +DRL_DURATION : 'duration'; ///////////////// // LEXER 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 2551a83593..690828a176 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 @@ -4,23 +4,42 @@ options { tokenVocab=DRLLexer; } import JavaParser; + /* + * statement := importStatement + * | globalStatement + * | declare + * | rule + * | ruleAttribute + * | function + * | query + * ; + */ +compilationUnit : packagedef? unitdef? drlStatementdef* ; -compilationUnit : packagedef? unitdef? importdef* attributes* globaldef* ruledef* ; +drlStatementdef + : importdef + | globaldef + | functiondef + | attributes + | ruledef + ; + +packagedef : DRL_PACKAGE name=drlQualifiedName SEMI? ; -packagedef : PACKAGE name=qualifiedName SEMI? ; +unitdef : DRL_UNIT name=drlQualifiedName SEMI? ; -unitdef : UNIT name=qualifiedName SEMI? ; +importdef : DRL_IMPORT (DRL_FUNCTION|DRL_STATIC)? drlQualifiedName (DOT MUL)? SEMI? ; -importdef : IMPORT (FUNCTION|STATIC)? qualifiedName (DOT MUL)? SEMI? ; +globaldef : DRL_GLOBAL type drlIdentifier SEMI? ; -globaldef : GLOBAL type IDENTIFIER SEMI? ; +// rule := RULE stringId (EXTENDS stringId)? annotation* attributes? lhs? rhs END -ruledef : RULE name=stringId (EXTENDS stringId)? drlAnnotation* attributes? WHEN lhs THEN rhs END ; +ruledef : DRL_RULE name=stringId (DRL_EXTENDS stringId)? drlAnnotation* attributes? DRL_WHEN lhs DRL_THEN rhs DRL_END ; -lhs : lhsExpression ; +lhs : lhsExpression? ; lhsExpression : lhsOr* ; -lhsOr : LPAREN KWD_OR lhsAnd+ RPAREN | lhsAnd (KWD_OR lhsAnd)* ; -lhsAnd : LPAREN KWD_AND lhsUnary+ RPAREN | lhsUnary (KWD_AND lhsUnary)* ; +lhsOr : LPAREN DRL_OR lhsAnd+ RPAREN | lhsAnd (DRL_OR lhsAnd)* ; +lhsAnd : LPAREN DRL_AND lhsUnary+ RPAREN | lhsUnary (DRL_AND lhsUnary)* ; /* lhsUnary : ( lhsExists namedConsequence? @@ -38,14 +57,14 @@ lhsUnary : ( | lhsNot | lhsPatternBind ) ; -lhsPatternBind : label? ( LPAREN lhsPattern (KWD_OR lhsPattern)* RPAREN | lhsPattern ) ; +lhsPatternBind : label? ( LPAREN lhsPattern (DRL_OR lhsPattern)* RPAREN | lhsPattern ) ; /* lhsPattern : xpathPrimary (OVER patternFilter)? | ( QUESTION? qualifiedIdentifier LPAREN positionalConstraints? constraints? RPAREN (OVER patternFilter)? (FROM patternSource)? ) ; */ -lhsPattern : QUESTION? objectType=qualifiedName LPAREN (positionalConstraints? constraints? ) RPAREN (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 ) ; @@ -60,6 +79,76 @@ instanceOfExpression : left=inExpression ( 'instanceof' right=type )? ; inExpression : left=relationalExpression ( 'not'? 'in' LPAREN drlExpression (COMMA drlExpression)* RPAREN )? ; relationalExpression : drlExpression? ; + +/* function := FUNCTION type? ID parameters(typed) chunk_{_} */ +functiondef : DRL_FUNCTION typeTypeOrVoid? IDENTIFIER formalParameters block ; + + +/* extending JavaParser qualifiedName */ +drlQualifiedName + : drlIdentifier (DOT drlIdentifier)* + ; + +/* extending JavaParser identifier */ +drlIdentifier + : drlKeywords + | IDENTIFIER + | MODULE + | OPEN + | REQUIRES + | EXPORTS + | OPENS + | TO + | USES + | PROVIDES + | WITH + | TRANSITIVE + | YIELD + | SEALED + | PERMITS + | RECORD + | VAR + ; + +drlKeywords + : DRL_PACKAGE + | DRL_UNIT + | DRL_IMPORT + | DRL_FUNCTION + | DRL_STATIC + | DRL_GLOBAL + | DRL_RULE + | DRL_QUERY + | DRL_EXTENDS + | DRL_SUPER + | DRL_WHEN + | DRL_THEN + | DRL_END + | DRL_AND + | DRL_OR + | DRL_EXISTS + | DRL_NOT + | DRL_IN + | DRL_FROM + | DRL_MATCHES + | DRL_SALIENCE + | DRL_ENABLED + | DRL_NO_LOOP + | DRL_AUTO_FOCUS + | DRL_LOCK_ON_ACTIVE + | DRL_REFRACT + | DRL_DIRECT + | DRL_AGENDA_GROUP + | DRL_ACTIVATION_GROUP + | DRL_RULEFLOW_GROUP + | DRL_DATE_EFFECTIVE + | DRL_DATE_EXPIRES + | DRL_DIALECT + | DRL_CALENDARS + | DRL_TIMER + | DRL_DURATION + ; + /* extending JavaParser expression */ drlExpression : drlPrimary @@ -84,7 +173,7 @@ drlExpression | drlExpression (LT LT | GT GT GT | GT GT) drlExpression | drlExpression bop=(LE | GE | GT | LT) drlExpression | drlExpression bop=INSTANCEOF (typeType | pattern) - | drlExpression bop=MATCHES drlExpression + | drlExpression bop=DRL_MATCHES drlExpression | drlExpression bop=(EQUAL | NOTEQUAL) drlExpression | drlExpression bop=BITAND drlExpression | drlExpression bop=CARET drlExpression @@ -110,7 +199,7 @@ drlPrimary | THIS | SUPER | drlLiteral - | identifier + | drlIdentifier | typeTypeOrVoid DOT CLASS | nonWildcardTypeArguments (explicitGenericInvocationSuffix | THIS arguments) | inlineListExpression @@ -153,7 +242,7 @@ fromExpression : conditionalOrExpression ; | lhsPatternBind ) */ -lhsExists : EXISTS lhsPatternBind ; +lhsExists : DRL_EXISTS lhsPatternBind ; /* lhsNot := NOT ( (LEFT_PAREN (or_key|and_key))=> lhsOr // prevents '((' for prefixed and/or @@ -161,9 +250,9 @@ lhsExists : EXISTS lhsPatternBind ; | lhsPatternBind ) */ -lhsNot : NOT lhsPatternBind ; +lhsNot : DRL_NOT lhsPatternBind ; -rhs : blockStatement* ; +rhs : drlRhsBlockStatement* ; stringId : ( IDENTIFIER | DRL_STRING_LITERAL ) ; @@ -175,7 +264,7 @@ type : IDENTIFIER typeArguments? ( DOT IDENTIFIER typeArguments? )* (LBRACK RBRA drlArguments : LPAREN drlArgument (COMMA drlArgument)* RPAREN ; drlArgument : ( stringId | floatLiteral | BOOL_LITERAL | NULL_LITERAL ) ; -drlAnnotation : AT name=qualifiedName drlArguments? ; +drlAnnotation : AT name=drlQualifiedName drlArguments? ; attributes : attribute ( COMMA? attribute )* ; attribute : ( 'salience' DECIMAL_LITERAL ) @@ -198,3 +287,77 @@ assignmentOperator : ASSIGN label : IDENTIFIER COLON ; unif : IDENTIFIER UNIFY ; + +/* extending JavaParser blockStatement */ +drlRhsBlockStatement + : localVariableDeclaration SEMI + | drlRhsStatement + | localTypeDeclaration + ; + +/* extending JavaParser statement */ +drlRhsStatement + : blockLabel=block + | ASSERT drlRhsExpression (COLON drlRhsExpression)? SEMI + | IF parExpression drlRhsStatement (ELSE drlRhsStatement)? + | FOR LPAREN forControl RPAREN drlRhsStatement + | WHILE parExpression drlRhsStatement + | DO drlRhsStatement WHILE parExpression SEMI + | TRY block (catchClause+ finallyBlock? | finallyBlock) + | TRY resourceSpecification block catchClause* finallyBlock? + | SWITCH parExpression LBRACE switchBlockStatementGroup* switchLabel* RBRACE + | SYNCHRONIZED parExpression block + | RETURN drlRhsExpression? SEMI + | THROW drlRhsExpression SEMI + | BREAK identifier? SEMI + | CONTINUE identifier? SEMI + | YIELD drlRhsExpression SEMI // Java17 + | SEMI + | statementExpression=drlRhsExpression SEMI + | switchExpression SEMI? // Java17 + | identifierLabel=identifier COLON drlRhsStatement + ; + +/* extending JavaParser expression */ +drlRhsExpression + : drlPrimary + | drlRhsExpression bop=DOT + ( + identifier + | methodCall + | THIS + | NEW nonWildcardTypeArguments? innerCreator + | SUPER superSuffix + | explicitGenericInvocation + ) + | drlRhsExpression LBRACK drlRhsExpression RBRACK + | methodCall + | NEW creator + | LPAREN annotation* typeType (BITAND typeType)* RPAREN drlRhsExpression + | drlRhsExpression postfix=(INC | DEC) + | prefix=(ADD|SUB|INC|DEC) drlRhsExpression + | prefix=(TILDE|BANG) drlRhsExpression + | drlRhsExpression bop=(MUL|DIV|MOD) drlRhsExpression + | drlRhsExpression bop=(ADD|SUB) drlRhsExpression + | drlRhsExpression (LT LT | GT GT GT | GT GT) drlRhsExpression + | drlRhsExpression bop=(LE | GE | GT | LT) drlRhsExpression + | drlRhsExpression bop=INSTANCEOF (typeType | pattern) + | drlRhsExpression bop=DRL_MATCHES drlRhsExpression + | drlRhsExpression bop=(EQUAL | NOTEQUAL) drlRhsExpression + | drlRhsExpression bop=BITAND drlRhsExpression + | drlRhsExpression bop=CARET drlRhsExpression + | drlRhsExpression bop=BITOR drlRhsExpression + | drlRhsExpression bop=AND drlRhsExpression + | drlRhsExpression bop=OR drlRhsExpression + | <assoc=right> drlRhsExpression bop=QUESTION drlRhsExpression COLON drlRhsExpression + | <assoc=right> drlRhsExpression + bop=(ASSIGN | ADD_ASSIGN | SUB_ASSIGN | MUL_ASSIGN | DIV_ASSIGN | AND_ASSIGN | OR_ASSIGN | XOR_ASSIGN | RSHIFT_ASSIGN | URSHIFT_ASSIGN | LSHIFT_ASSIGN | MOD_ASSIGN) + drlRhsExpression + | lambdaExpression // Java8 + | switchExpression // Java17 + + // Java 8 methodReference + | drlRhsExpression COLONCOLON typeArguments? identifier + | typeType COLONCOLON (typeArguments? identifier | NEW) + | classType COLONCOLON typeArguments? NEW + ; \ No newline at end of file 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 8caa78a977..d45028d82a 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 @@ -59,7 +59,7 @@ public class DRLVisitorImpl extends DRLParserBaseVisitor<Object> { @Override public Object visitGlobaldef(DRLParser.GlobaldefContext ctx) { - GlobalDescr globalDescr = new GlobalDescr(ctx.IDENTIFIER().getText(), ctx.type().getText()); + GlobalDescr globalDescr = new GlobalDescr(ctx.drlIdentifier().getText(), ctx.type().getText()); populateStartEnd(globalDescr, ctx); packageDescr.addGlobal(globalDescr); return super.visitGlobaldef(ctx); @@ -67,8 +67,8 @@ public class DRLVisitorImpl extends DRLParserBaseVisitor<Object> { @Override public Object visitImportdef(DRLParser.ImportdefContext ctx) { - String target = ctx.qualifiedName().getText() + (ctx.MUL() != null ? ".*" : ""); - if (ctx.FUNCTION() != null || ctx.STATIC() != null) { + String target = ctx.drlQualifiedName().getText() + (ctx.MUL() != null ? ".*" : ""); + if (ctx.DRL_FUNCTION() != null || ctx.DRL_STATIC() != null) { FunctionImportDescr functionImportDescr = new FunctionImportDescr(); functionImportDescr.setTarget(target); populateStartEnd(functionImportDescr, ctx); @@ -180,14 +180,11 @@ public class DRLVisitorImpl extends DRLParserBaseVisitor<Object> { } @Override - public Object visitIdentifier(DRLParser.IdentifierContext ctx) { - if (ctx.IDENTIFIER() == null) { - return ""; - } else { - return ctx.IDENTIFIER().getText(); - } + public Object visitDrlIdentifier(DRLParser.DrlIdentifierContext ctx) { + return ctx.getText(); } + @Override public Object visitDrlLiteral(DRLParser.DrlLiteralContext ctx) { ParseTree node = ctx; 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 baaaa5a5e4..079b3ccb9a 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 @@ -494,4 +494,16 @@ public class MiscDRLParserTest extends TestCase { // Note : RuleParserTest.testEmptyRule allows this DRL, but I think is doesn't make sense to pass this DRL } + + @Test + public void testKeywordCollisions() throws Exception { + String source = readResource("eol_funny_business.drl"); // keywords everywhere + PackageDescr pkg = parser.parse(source); + + assertFalse( parser.getErrors().toString(), + parser.hasErrors() ); + + assertEquals( 1, + pkg.getRules().size() ); + } } diff --git a/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/eol_funny_business.drl b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/eol_funny_business.drl new file mode 100644 index 0000000000..0090d3d018 --- /dev/null +++ b/drools-drl/drools-drl10-parser/src/test/resources/org/drools/parser/eol_funny_business.drl @@ -0,0 +1,35 @@ +/* + * 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 test.dialect.rule.end.package.mine; + +global java.lang.String rule; + +import com.dialect.something.SomeClass + +function boolean test() { + return true; +} + +rule type1 + when + $id : Something( duration == "foo") + then + The.method(); + attributes; + rule; + package; +end + --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
