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 aa202f5ad9 [incubator-kie-drools#5705] [new-parser] no viable 
alternative after … (#5767)
aa202f5ad9 is described below

commit aa202f5ad97002c87cd5e981bfb53d0c4107fbca
Author: Toshiya Kobayashi <[email protected]>
AuthorDate: Thu Mar 7 17:09:28 2024 +0900

    [incubator-kie-drools#5705] [new-parser] no viable alternative after … 
(#5767)
    
    * [incubator-kie-drools#5705] [new-parser] no viable alternative after 
contains operator
    
    * - Add comment
    
    * Update 
drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java
    
    Co-authored-by: Jiří Locker <[email protected]>
    
    * Update 
drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java
    
    Co-authored-by: Jiří Locker <[email protected]>
    
    * Update 
drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java
    
    Co-authored-by: Jiří Locker <[email protected]>
    
    * Update 
drools-drl/drools-drl-parser-tests/src/test/java/org/drools/drl/parser/antlr4/MiscDRLParserTest.java
    
    Co-authored-by: Jiří Locker <[email protected]>
    
    * - add javadoc to ParserHelper.isPluggableEvaluator
    
    ---------
    
    Co-authored-by: Jiří Locker <[email protected]>
---
 .../drl/parser/antlr4/MiscDRLParserTest.java       | 73 +++++++++++++++++++++-
 .../drools/drl/parser/antlr4/DRL6Expressions.g4    |  7 ++-
 .../org/drools/drl/parser/antlr4/DRLLexer.g4       | 10 ++-
 .../org/drools/drl/parser/antlr4/DRLParser.g4      | 21 +++++--
 .../org/drools/drl/parser/antlr4/ParserHelper.java |  8 +++
 5 files changed, 108 insertions(+), 11 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 cbc9686acb..c869a19062 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
@@ -39,11 +39,12 @@ import org.drools.drl.ast.descr.RuleDescr;
 import org.drools.drl.ast.descr.TypeDeclarationDescr;
 import org.drools.drl.ast.descr.TypeFieldDescr;
 import org.drools.drl.ast.descr.WindowDeclarationDescr;
-import org.drools.drl.parser.antlr4.DRLParserWrapper;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -3538,4 +3539,74 @@ class MiscDRLParserTest {
         assertThat(ruleDescr.getName()).isEqualTo("R1");
         assertThat(ruleDescr.getNamespace()).isEqualTo("org.drools");
     }
+
+    /**
+     * Each test input is a constraint expression covering one of the existing 
DRL operators. The test is successful if the parser has
+     * no errors and the descriptor's expression string is equal to the input.
+     *
+     * @param constraint expression using an operator
+     */
+    @ParameterizedTest
+    @ValueSource(strings = {
+            "country matches \"[a-z]*\"",
+            "country not matches \"[a-z]*\"",
+            "person memberOf $europeanDescendants",
+            "person not memberOf $europeanDescendants",
+            "countries contains \"UK\"",
+            "countries not contains \"UK\"",
+            "countries excludes \"UK\"",
+            "countries not excludes \"UK\"",
+            "firstName soundslike \"John\"",
+            "firstName not soundslike \"John\"",
+            "routingValue str[startsWith] \"R1\"",
+            "routingValue not str[startsWith] \"R1\""
+    })
+    void constraintOperators(String constraint) {
+        final String text = "package org.drools\n" +
+                "rule R1\n" +
+                "when\n" +
+                "    $p : Person(" + constraint + ")\n" +
+                "then\n" +
+                "end\n";
+
+        PackageDescr packageDescr = parser.parse(text);
+
+        RuleDescr ruleDescr = packageDescr.getRules().get(0);
+        AndDescr lhs = ruleDescr.getLhs();
+        PatternDescr patternDescr = (PatternDescr) lhs.getDescrs().get(0);
+        ExprConstraintDescr exprConstraintDescr = (ExprConstraintDescr) 
patternDescr.getConstraint().getDescrs().get(0);
+        
assertThat(exprConstraintDescr.getExpression()).isEqualToIgnoringWhitespace(constraint);
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = {
+            "country matches \"[a-z]*\" || matches \"[A-Z]*\"",
+            "country not matches \"[a-z]*\" || not matches \"[A-Z]*\"",
+            "person memberOf $europeanDescendants || memberOf 
$africanDescendants",
+            "person not memberOf $europeanDescendants || not memberOf 
$africanDescendants",
+            "countries contains \"UK\" || contains \"US\"",
+            "countries not contains \"UK\" || not contains \"US\"",
+            "countries excludes \"UK\" || excludes \"US\"",
+            "countries not excludes \"UK\" || not excludes \"US\"",
+            "firstName soundslike \"John\" || soundslike \"Paul\"",
+            "firstName not soundslike \"John\" && not soundslike \"Paul\"",
+            "routingValue str[startsWith] \"R1\" || str[startsWith] \"R2\"",
+            "routingValue not str[startsWith] \"R1\" && not str[startsWith] 
\"R2\""
+    })
+    void halfConstraintOperators(String constraint) {
+        final String text = "package org.drools\n" +
+                "rule R1\n" +
+                "when\n" +
+                "    $p : Person(" + constraint + ")\n" +
+                "then\n" +
+                "end\n";
+
+        PackageDescr packageDescr = parser.parse(text);
+
+        RuleDescr ruleDescr = packageDescr.getRules().get(0);
+        AndDescr lhs = ruleDescr.getLhs();
+        PatternDescr patternDescr = (PatternDescr) lhs.getDescrs().get(0);
+        ExprConstraintDescr exprConstraintDescr = (ExprConstraintDescr) 
patternDescr.getConstraint().getDescrs().get(0);
+        
assertThat(exprConstraintDescr.getExpression()).isEqualToIgnoringWhitespace(constraint);
+    }
 }
diff --git 
a/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRL6Expressions.g4
 
b/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRL6Expressions.g4
index 2b4a62e913..51ea965a0f 100644
--- 
a/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRL6Expressions.g4
+++ 
b/drools-drl/drools-drl-parser/src/main/antlr4/org/drools/drl/parser/antlr4/DRL6Expressions.g4
@@ -838,10 +838,11 @@ in_key
     ;
 
 operator_key
-  // TODO get rid of the DRL_MATCHES token or introduce DRL_CONTAINS etc. for 
consistency.
-  :      {(helper.isPluggableEvaluator(false))}? id=(IDENTIFIER|DRL_MATCHES) { 
helper.emit($id, DroolsEditorType.KEYWORD); }
+  // At the moment, we list possible DRLLexer tokens here, but we may be able 
to improve this by isolating lexers. IDENTIFIER is required to accept custom 
operators
+  // We need to keep this semantic predicate for custom operators
+  :      {(helper.isPluggableEvaluator(false))}? 
id=(IDENTIFIER|DRL_MATCHES|DRL_MEMBEROF|DRL_CONTAINS|DRL_EXCLUDES|DRL_SOUNDSLIKE|DRL_STR)
 { helper.emit($id, DroolsEditorType.KEYWORD); }
   ;
 
 neg_operator_key
-  :      {(helper.isPluggableEvaluator(true))}? id=IDENTIFIER { 
helper.emit($id, DroolsEditorType.KEYWORD); }
+  :      {(helper.isPluggableEvaluator(true))}? 
id=(IDENTIFIER|DRL_MATCHES|DRL_MEMBEROF|DRL_CONTAINS|DRL_EXCLUDES|DRL_SOUNDSLIKE|DRL_STR)
 { helper.emit($id, DroolsEditorType.KEYWORD); }
   ;
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 a54ee07fda..79c439586f 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
@@ -45,8 +45,6 @@ DRL_NOT : 'not';
 DRL_IN : 'in';
 DRL_FROM : 'from';
 DRL_COLLECT : 'collect';
-DRL_MATCHES : 'matches';
-DRL_MEMBEROF : 'memberOf';
 DRL_ACCUMULATE : 'accumulate';
 DRL_ACC : 'acc';
 DRL_INIT : 'init';
@@ -58,6 +56,14 @@ DRL_EVAL : 'eval';
 DRL_FORALL : 'forall';
 DRL_OVER : 'over';
 
+// constraint operators
+DRL_MATCHES : 'matches';
+DRL_MEMBEROF : 'memberOf';
+DRL_CONTAINS : 'contains';
+DRL_EXCLUDES : 'excludes';
+DRL_SOUNDSLIKE : 'soundslike';
+DRL_STR : 'str';
+
 // temporal operators
 DRL_AFTER : 'after';
 DRL_BEFORE : 'before';
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 5ae8c9016b..d65c9e2b73 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
@@ -129,6 +129,8 @@ positionalConstraints : constraint (COMMA constraint)* SEMI 
;
 constraints : constraint (COMMA constraint)* ;
 constraint : ( nestedConstraint | conditionalOrExpression ) ;
 nestedConstraint : ( IDENTIFIER ( DOT | HASH ) )* IDENTIFIER DOT LPAREN 
constraints RPAREN ;
+
+// TBD: constraint parsing could be delegated to DRL6ExpressionParser
 conditionalOrExpression : left=conditionalAndExpression (OR 
right=conditionalAndExpression)* ;
 conditionalAndExpression : left=inclusiveOrExpression (AND 
right=inclusiveOrExpression)* ;
 inclusiveOrExpression : left=exclusiveOrExpression (BITOR 
right=exclusiveOrExpression)* ;
@@ -149,9 +151,18 @@ relationalOperator
     | GE
     | GT
     | LT
+    | drlRelationalOperator
     | temporalOperator
     ;
 
+drlRelationalOperator
+    : DRL_NOT? DRL_MATCHES
+    | DRL_NOT? DRL_MEMBEROF
+    | DRL_NOT? DRL_CONTAINS
+    | DRL_NOT? DRL_EXCLUDES
+    | DRL_NOT? DRL_SOUNDSLIKE
+    | DRL_NOT? DRL_STR LBRACK IDENTIFIER RBRACK ;
+
 /* function := FUNCTION type? ID parameters(typed) chunk_{_} */
 functiondef : DRL_FUNCTION typeTypeOrVoid? IDENTIFIER formalParameters block ;
 
@@ -200,6 +211,10 @@ drlKeywords
     | DRL_FROM
     | DRL_MATCHES
     | DRL_MEMBEROF
+    | DRL_CONTAINS
+    | DRL_EXCLUDES
+    | DRL_SOUNDSLIKE
+    | DRL_STR
     | DRL_ACCUMULATE
     | DRL_ACC
     | DRL_INIT
@@ -249,13 +264,9 @@ 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 temporalOperator drlExpression
     | drlExpression bop=INSTANCEOF (typeType | pattern)
-    | drlExpression bop=DRL_MATCHES drlExpression
-    | drlExpression DRL_NOT? DRL_MEMBEROF drlExpression
+    | drlExpression relationalOperator drlExpression
     | drlExpression bop=DRL_UNIFY drlExpression
-    | drlExpression bop=(EQUAL | NOTEQUAL) drlExpression
     | drlExpression bop=BITAND drlExpression
     | drlExpression bop=CARET drlExpression
     | drlExpression bop=BITOR drlExpression
diff --git 
a/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/ParserHelper.java
 
b/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/ParserHelper.java
index 82d40b6302..1d533e3c51 100644
--- 
a/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/ParserHelper.java
+++ 
b/drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/antlr4/ParserHelper.java
@@ -231,6 +231,14 @@ public class ParserHelper {
         return text2Validate != null && 
DroolsSoftKeywords.isOperator(text2Validate, negated);
     }
 
+    /**
+     * Check if the next token is a registered operator.
+     * The registry is dynamic, so we can add custom operators dynamically.
+     * @see org.drools.drl.parser.impl.Operator#addOperatorToRegistry(String, 
boolean)
+     *
+     * @param negated true if the operator needs to support negation
+     * @return true if the next token is a registered operator
+     */
     public boolean isPluggableEvaluator( boolean negated ) {
         return isPluggableEvaluator( 1,
                                      negated );


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to