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 457fb1e44b2e14476b8d6329d484f7761a6ce0f5 Author: Toshiya Kobayashi <[email protected]> AuthorDate: Mon Jun 27 15:42:21 2022 +0900 Enhance test/grammar coverage. matches, single quoted string, escape (#9) - Introduced drlExpression, drlPrimary, drlLiteral, DRL_STRING_LITERAL --- .../src/main/antlr4/org/drools/parser/DRLLexer.g4 | 30 ++++++++ .../src/main/antlr4/org/drools/parser/DRLParser.g4 | 79 ++++++++++++++++++---- .../java/org/drools/parser/DRLVisitorImpl.java | 15 +++- .../java/org/drools/parser/MiscDRLParserTest.java | 61 +++++++++++++++++ 4 files changed, 168 insertions(+), 17 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 8ba1364c40..ed2416b6ac 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 @@ -39,6 +39,7 @@ EXISTS : 'exists'; NOT : 'not'; IN : 'in'; FROM : 'from'; +MATCHES : 'matches'; SALIENCE : 'salience'; ENABLED : 'enabled'; @@ -69,6 +70,10 @@ TIME_INTERVAL | (('0'..'9')+ 'ms') ; +DRL_STRING_LITERAL + : ('"' ( DrlEscapeSequence | ~('\\'|'"') )* '"') + | ('\'' ( DrlEscapeSequence | ~('\\'|'\'') )* '\'') { setText( normalizeString( getText() ) ); } + ; ///////////////// // SYMBOLS @@ -80,3 +85,28 @@ NULL_SAFE_DOT : '!.' ; QUESTION_DIV : '?/' ; MISC : '\'' | '\\' | '$' ; + +///////////////// +// Fragment +///////////////// +fragment +DrlEscapeSequence + : '\\' ('b'|'B'|'t'|'n'|'f'|'r'|'"'|'\''|'\\'|'.'|'o'| + 'x'|'a'|'e'|'c'|'d'|'D'|'s'|'S'|'w'|'W'|'p'|'A'| + 'G'|'Z'|'z'|'Q'|'E'|'*'|'['|']'|'('|')'|'$'|'^'| + '{'|'}'|'?'|'+'|'-'|'&'|'|') + | DrlUnicodeEscape + | DrlOctalEscape + ; + +fragment +DrlOctalEscape + : '\\' ('0'..'3') ('0'..'7') ('0'..'7') + | '\\' ('0'..'7') ('0'..'7') + | '\\' ('0'..'7') + ; + +fragment +DrlUnicodeEscape + : '\\' 'u' HexDigit HexDigit HexDigit HexDigit + ; 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 c9db7951aa..b68437835f 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 @@ -58,32 +58,83 @@ 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 : shiftExpression, additiveExpression, multiplicativeExpression, unaryExpression, unaryExpressionNotPlusMinus, ..., primary +relationalExpression : drlExpression? ; + +/* extending JavaParser expression */ +drlExpression + : drlPrimary + | drlExpression bop=DOT + ( + identifier + | methodCall + | THIS + | NEW nonWildcardTypeArguments? innerCreator + | SUPER superSuffix + | explicitGenericInvocation + ) + | drlExpression LBRACK drlExpression RBRACK + | methodCall + | NEW creator + | LPAREN annotation* typeType (BITAND typeType)* RPAREN drlExpression + | drlExpression postfix=(INC | DEC) + | prefix=(ADD|SUB|INC|DEC) drlExpression + | prefix=(TILDE|BANG) drlExpression + | drlExpression bop=(MUL|DIV|MOD) drlExpression + | drlExpression bop=(ADD|SUB) 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=(EQUAL | NOTEQUAL) drlExpression + | drlExpression bop=BITAND drlExpression + | drlExpression bop=CARET drlExpression + | drlExpression bop=BITOR drlExpression + | drlExpression bop=AND drlExpression + | drlExpression bop=OR drlExpression + | <assoc=right> drlExpression bop=QUESTION drlExpression COLON drlExpression + | <assoc=right> drlExpression + bop=(ASSIGN | ADD_ASSIGN | SUB_ASSIGN | MUL_ASSIGN | DIV_ASSIGN | AND_ASSIGN | OR_ASSIGN | XOR_ASSIGN | RSHIFT_ASSIGN | URSHIFT_ASSIGN | LSHIFT_ASSIGN | MOD_ASSIGN) + drlExpression + | lambdaExpression // Java8 + | switchExpression // Java17 + + // Java 8 methodReference + | drlExpression COLONCOLON typeArguments? identifier + | typeType COLONCOLON (typeArguments? identifier | NEW) + | classType COLONCOLON typeArguments? NEW + ; -/* extending JavaParser */ -primary - : LPAREN expression RPAREN +/* extending JavaParser primary */ +drlPrimary + : LPAREN drlExpression RPAREN | THIS | SUPER - | literal + | drlLiteral | identifier | typeTypeOrVoid DOT CLASS | nonWildcardTypeArguments (explicitGenericInvocationSuffix | THIS arguments) | inlineListExpression ; +/* extending JavaParser literal */ +drlLiteral + : integerLiteral + | floatLiteral + | CHAR_LITERAL + | DRL_STRING_LITERAL + | BOOL_LITERAL + | NULL_LITERAL + | TEXT_BLOCK // Java17 + ; + inlineListExpression : LBRACK expressionList? RBRACK ; expressionList - : expression (COMMA expression)* + : drlExpression (COMMA drlExpression)* ; -drlExpression : conditionalExpression ( op=assignmentOperator right=drlExpression )? ; -conditionalExpression : left=conditionalOrExpression ternaryExpression? ; -ternaryExpression : QUESTION ts=drlExpression COLON fs=drlExpression ; - /* patternSource := FROM ( fromAccumulate @@ -112,9 +163,9 @@ lhsExists : EXISTS lhsPatternBind ; */ lhsNot : NOT lhsPatternBind ; -rhs : blockStatement+ ; +rhs : blockStatement* ; -stringId : ( IDENTIFIER | STRING_LITERAL ) ; +stringId : ( IDENTIFIER | DRL_STRING_LITERAL ) ; type : IDENTIFIER typeArguments? ( DOT IDENTIFIER typeArguments? )* (LBRACK RBRACK)* ; @@ -129,8 +180,8 @@ drlAnnotation : AT name=qualifiedName drlArguments? ; attributes : attribute ( COMMA? attribute )* ; attribute : ( 'salience' DECIMAL_LITERAL ) | ( 'enabled' | 'no-loop' | 'auto-focus' | 'lock-on-active' | 'refract' | 'direct' ) BOOL_LITERAL? - | ( 'agenda-group' | 'activation-group' | 'ruleflow-group' | 'date-effective' | 'date-expires' | 'dialect' ) STRING_LITERAL - | 'calendars' STRING_LITERAL ( COMMA STRING_LITERAL )* + | ( 'agenda-group' | 'activation-group' | 'ruleflow-group' | 'date-effective' | 'date-expires' | 'dialect' ) DRL_STRING_LITERAL + | 'calendars' DRL_STRING_LITERAL ( COMMA DRL_STRING_LITERAL )* | 'timer' ( DECIMAL_LITERAL | TEXT ) | 'duration' ( DECIMAL_LITERAL | TEXT ) ; 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 98f6388b49..5706ddd9db 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 @@ -145,7 +145,16 @@ public class DRLVisitorImpl extends DRLParserBaseVisitor<Object> { } @Override - public Object visitExpression(DRLParser.ExpressionContext ctx) { + public Object visitDrlExpression(DRLParser.DrlExpressionContext ctx) { + return ctx.children.stream() + .map(c -> c instanceof TerminalNode ? c : c.accept(this)) + .filter(Objects::nonNull) + .map(Object::toString) + .collect(Collectors.joining(" ")); + } + + @Override + public Object visitDrlPrimary(DRLParser.DrlPrimaryContext ctx) { return ctx.children.stream() .map(c -> c instanceof TerminalNode ? c : c.accept(this)) .filter(Objects::nonNull) @@ -163,14 +172,14 @@ public class DRLVisitorImpl extends DRLParserBaseVisitor<Object> { } @Override - public Object visitLiteral(DRLParser.LiteralContext ctx) { + public Object visitDrlLiteral(DRLParser.DrlLiteralContext ctx) { ParseTree node = ctx; while (true) { if (node instanceof TerminalNode) { return node.toString(); } if (node.getChildCount() != 1) { - return super.visitLiteral(ctx); + return super.visitDrlLiteral(ctx); } node = node.getChild(0); } 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 07746c0299..c105a4a29f 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 @@ -13,6 +13,7 @@ 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.ExprConstraintDescr; import org.drools.drl.ast.descr.FromDescr; import org.drools.drl.ast.descr.FunctionImportDescr; import org.drools.drl.ast.descr.GlobalDescr; @@ -397,4 +398,64 @@ public class MiscDRLParserTest extends TestCase { ((PatternDescr) pdo2).getIdentifier()); } } + + @Test + public void testCompatibleRestriction() throws Exception { + String source = "package com.sample rule test when Test( ( text == null || text2 matches \"\" ) ) then end"; + PackageDescr pkg = parser.parse(source); + + assertEquals( "com.sample", + pkg.getName() ); + RuleDescr rule = (RuleDescr) pkg.getRules().get( 0 ); + assertEquals( "test", + rule.getName() ); + ExprConstraintDescr expr = (ExprConstraintDescr) ((PatternDescr) rule.getLhs().getDescrs().get(0 )).getDescrs().get(0 ); + assertEquals( "( text == null || text2 matches \"\" )", + expr.getText() ); + } + + @Test + public void testSimpleConstraint() throws Exception { + String source = "package com.sample rule test when Cheese( type == 'stilton', price > 10 ) then end"; + PackageDescr pkg = parser.parse(source); + + assertEquals( "com.sample", + pkg.getName() ); + RuleDescr rule = (RuleDescr) pkg.getRules().get( 0 ); + assertEquals( "test", + rule.getName() ); + + assertEquals( 1, + rule.getLhs().getDescrs().size() ); + PatternDescr pattern = (PatternDescr) rule.getLhs().getDescrs().get( 0 ); + + AndDescr constraint = (AndDescr) pattern.getConstraint(); + assertEquals( 2, + constraint.getDescrs().size() ); + assertEquals( "type == \"stilton\"", + constraint.getDescrs().get( 0 ).toString() ); + assertEquals( "price > 10", + constraint.getDescrs().get( 1 ).toString() ); + } + + @Test + public void testStringEscapes() throws Exception { + String source = "package com.sample rule test when Cheese( type matches \"\\..*\\\\.\" ) then end"; + PackageDescr pkg = parser.parse(source); + assertEquals( "com.sample", + pkg.getName() ); + RuleDescr rule = (RuleDescr) pkg.getRules().get( 0 ); + assertEquals( "test", + rule.getName() ); + + assertEquals( 1, + rule.getLhs().getDescrs().size() ); + PatternDescr pattern = (PatternDescr) rule.getLhs().getDescrs().get( 0 ); + + AndDescr constraint = (AndDescr) pattern.getConstraint(); + assertEquals( 1, + constraint.getDescrs().size() ); + assertEquals( "type matches \"\\..*\\\\.\"", + constraint.getDescrs().get( 0 ).toString() ); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
