You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/04/11 12:55:58 UTC

[groovy] branch GROOVY-10003 updated: GROOVY-10003: Eliminate some ambiguities while parsing

This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch GROOVY-10003
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/GROOVY-10003 by this push:
     new 9b71785  GROOVY-10003: Eliminate some ambiguities while parsing
9b71785 is described below

commit 9b717852d2aeebeae1c8250534fc6c33968c5eed
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sun Apr 11 20:52:35 2021 +0800

    GROOVY-10003: Eliminate some ambiguities while parsing
    
    2. tweak command chain expression related rules
---
 src/antlr/GroovyLexer.g4                           |   2 +-
 src/antlr/GroovyParser.g4                          | 152 ++++++++++++++++++---
 .../apache/groovy/parser/antlr4/AstBuilder.java    |   4 +-
 src/test-resources/core/Lambda_01x.groovy          |   6 +-
 4 files changed, 139 insertions(+), 25 deletions(-)

diff --git a/src/antlr/GroovyLexer.g4 b/src/antlr/GroovyLexer.g4
index 6989d6d..b677a6c 100644
--- a/src/antlr/GroovyLexer.g4
+++ b/src/antlr/GroovyLexer.g4
@@ -974,4 +974,4 @@ SH_COMMENT
 // Unexpected characters will be handled by groovy parser later.
 UNEXPECTED_CHAR
     :   .
-    ;
+    ;
\ No newline at end of file
diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
index ac064e2..39797da 100644
--- a/src/antlr/GroovyParser.g4
+++ b/src/antlr/GroovyParser.g4
@@ -396,7 +396,7 @@ thisFormalParameter
     ;
 
 formalParameter
-    :   variableModifiersOpt type? ELLIPSIS? variableDeclaratorId (nls ASSIGN nls expression)?
+    :   variableModifiersOpt type? ELLIPSIS? variableDeclaratorId (nls ASSIGN nls plainExpression)?
     ;
 
 methodBody
@@ -482,7 +482,7 @@ standardLambdaParameters
 
 lambdaBody
     :   block
-    |   statementExpression
+    |   plainStatementExpression
     ;
 
 // CLOSURE
@@ -538,7 +538,7 @@ elementValuePairName
 elementValue
     :   elementValueArrayInitializer
     |   annotation
-    |   expression
+    |   plainExpression
     ;
 
 elementValueArrayInitializer
@@ -621,7 +621,7 @@ tryCatchStatement
     ;
 
 assertStatement
-    :   ASSERT ce=expression (nls (COLON | COMMA) nls me=expression)?
+    :   ASSERT ce=plainExpression (nls (COLON | COMMA) nls me=plainExpression)?
     ;
 
 statement
@@ -630,8 +630,8 @@ statement
     |   loopStatement                                                                                       #loopStmtAlt
     |   tryCatchStatement                                                                                   #tryCatchStmtAlt
     |   SYNCHRONIZED expressionInPar nls block                                                              #synchronizedStmtAlt
-    |   RETURN expression?                                                                                  #returnStmtAlt
-    |   THROW expression                                                                                    #throwStmtAlt
+    |   RETURN plainExpression?                                                                                  #returnStmtAlt
+    |   THROW plainExpression                                                                                    #throwStmtAlt
     |   breakStatement                                                                                      #breakStmtAlt
     |   continueStatement                                                                                   #continueStmtAlt
     |   identifier COLON nls statement                                                                      #labeledStmtAlt
@@ -663,7 +663,7 @@ resourceList
 
 resource
     :   localVariableDeclaration
-    |   expression
+    |   plainExpression
     ;
 
 
@@ -675,7 +675,7 @@ switchBlockStatementGroup
     ;
 
 switchLabel
-    :   CASE expression COLON
+    :   CASE plainExpression COLON
     |   DEFAULT COLON
     ;
 
@@ -685,11 +685,11 @@ forControl
     ;
 
 enhancedForControl
-    :   variableModifiersOpt type? variableDeclaratorId (COLON | IN) expression
+    :   variableModifiersOpt type? variableDeclaratorId (COLON | IN) plainExpression
     ;
 
 classicalForControl
-    :   forInit? SEMI expression? SEMI forUpdate?
+    :   forInit? SEMI plainExpression? SEMI forUpdate?
     ;
 
 forInit
@@ -721,7 +721,13 @@ expressionList[boolean canSpread]
     ;
 
 expressionListElement[boolean canSpread]
-    :   MUL? expression
+    :   MUL? plainExpression
+    ;
+
+enhancedPlainStatementExpression
+options { baseContext = enhancedStatementExpression; }
+    :   plainStatementExpression
+    |   standardLambdaExpression
     ;
 
 enhancedStatementExpression
@@ -729,6 +735,11 @@ enhancedStatementExpression
     |   standardLambdaExpression
     ;
 
+plainStatementExpression
+options { baseContext = statementExpression; }
+    :   plainCommandExpression                   #commandExprAlt
+    ;
+
 statementExpression
     :   commandExpression                   #commandExprAlt
     ;
@@ -831,7 +842,7 @@ expression
                            |   POWER_ASSIGN
                            |   ELVIS_ASSIGN
                            ) nls
-                     enhancedStatementExpression                                            #assignmentExprAlt
+                     right=enhancedStatementExpression                                            #assignmentExprAlt
     ;
 
 castOperandExpression
@@ -847,6 +858,109 @@ options { baseContext = expression; }
     |   op=(INC | DEC | ADD | SUB) castOperandExpression                                    #unaryAddExprAlt
     ;
 
+plainExpression
+options { baseContext = expression; }
+    // must come before postfixExpression to resovle the ambiguities between casting and call on parentheses plainExpression, e.g. (int)(1 / 2)
+    :   castParExpression castOperandExpression                                                      #castExprAlt
+
+    // qualified names, array expressions, method invocation, post inc/dec
+    |   postfixExpression                                                                            #postfixExprAlt
+
+    // ~(BNOT)/!(LNOT) (level 1)
+    |   (BITNOT | NOT) nls plainExpression                                                           #unaryNotExprAlt
+
+    // math power operator (**) (level 2)
+    |   left=plainExpression op=POWER nls right=plainExpression                                      #powerExprAlt
+
+    // ++(prefix)/--(prefix)/+(unary)/-(unary) (level 3)
+    |   op=(INC | DEC | ADD | SUB) plainExpression                                                   #unaryAddExprAlt
+
+    // multiplication/division/modulo (level 4)
+    |   left=plainExpression nls op=(MUL | DIV | MOD) nls right=plainExpression                      #multiplicativeExprAlt
+
+    // binary addition/subtraction (level 5)
+    |   left=plainExpression op=(ADD | SUB) nls right=plainExpression                                #additiveExprAlt
+
+    // bit shift expressions (level 6)
+    |   left=plainExpression nls
+            (           (   dlOp=LT LT
+                        |   tgOp=GT GT GT
+                        |   dgOp=GT GT
+                        )
+            |   rangeOp=(    RANGE_INCLUSIVE
+                        |    RANGE_EXCLUSIVE
+                        )
+            ) nls
+        right=plainExpression                                                                        #shiftExprAlt
+
+    // boolean relational expressions (level 7)
+    |   left=plainExpression nls op=(AS | INSTANCEOF | NOT_INSTANCEOF) nls type                      #relationalExprAlt
+    |   left=plainExpression nls op=(LE | GE | GT | LT | IN | NOT_IN)  nls right=plainExpression     #relationalExprAlt
+
+    // equality/inequality (==/!=) (level 8)
+    |   left=plainExpression nls
+            op=(    IDENTICAL
+               |    NOT_IDENTICAL
+               |    EQUAL
+               |    NOTEQUAL
+               |    SPACESHIP
+               ) nls
+        right=plainExpression                                                                         #equalityExprAlt
+
+    // regex find and match (=~ and ==~) (level 8.5)
+    // jez: moved =~ closer to precedence of == etc, as...
+    // 'if (foo =~ "a.c")' is very close in intent to 'if (foo == "abc")'
+    |   left=plainExpression nls op=(REGEX_FIND | REGEX_MATCH) nls right=plainExpression              #regexExprAlt
+
+    // bitwise or non-short-circuiting and (&)  (level 9)
+    |   left=plainExpression nls op=BITAND nls right=plainExpression                                  #andExprAlt
+
+    // exclusive or (^)  (level 10)
+    |   left=plainExpression nls op=XOR nls right=plainExpression                                     #exclusiveOrExprAlt
+
+    // bitwise or non-short-circuiting or (|)  (level 11)
+    |   left=plainExpression nls op=BITOR nls right=plainExpression                                   #inclusiveOrExprAlt
+
+    // logical and (&&)  (level 12)
+    |   left=plainExpression nls op=AND nls right=plainExpression                                     #logicalAndExprAlt
+
+    // logical or (||)  (level 13)
+    |   left=plainExpression nls op=OR nls right=plainExpression                                      #logicalOrExprAlt
+
+    // conditional test (level 14)
+    |   <assoc=right> con=plainExpression nls
+        (   QUESTION nls tb=plainExpression nls COLON nls
+        |   ELVIS nls
+        )
+        fb=plainExpression                                                                             #conditionalExprAlt
+
+    // assignment plainExpression (level 15)
+    // "(a) = [1]" is a special case of multipleAssignmentExprAlt, it will be handle by assignmentExprAlt
+    |   <assoc=right> left=variableNames nls op=ASSIGN nls right=plainStatementExpression              #multipleAssignmentExprAlt
+    |   <assoc=right> left=plainExpression nls
+                        op=(   ASSIGN
+                           |   ADD_ASSIGN
+                           |   SUB_ASSIGN
+                           |   MUL_ASSIGN
+                           |   DIV_ASSIGN
+                           |   AND_ASSIGN
+                           |   OR_ASSIGN
+                           |   XOR_ASSIGN
+                           |   RSHIFT_ASSIGN
+                           |   URSHIFT_ASSIGN
+                           |   LSHIFT_ASSIGN
+                           |   MOD_ASSIGN
+                           |   POWER_ASSIGN
+                           |   ELVIS_ASSIGN
+                           ) nls
+                     right=enhancedPlainStatementExpression                                                  #assignmentExprAlt
+    ;
+
+plainCommandExpression
+options { baseContext = commandExpression; }
+    :   plainExpression
+    ;
+
 commandExpression
     :   expression
         (
@@ -1048,20 +1162,20 @@ options { baseContext = mapEntryList; }
     ;
 
 mapEntry
-    :   mapEntryLabel COLON nls expression
-    |   MUL COLON nls expression
+    :   mapEntryLabel COLON nls plainExpression
+    |   MUL COLON nls plainExpression
     ;
 
 namedPropertyArg
 options { baseContext = mapEntry; }
-    :   namedPropertyArgLabel COLON nls expression
-    |   MUL COLON nls expression
+    :   namedPropertyArgLabel COLON nls plainExpression
+    |   MUL COLON nls plainExpression
     ;
 
 namedArg
 options { baseContext = mapEntry; }
-    :   namedArgLabel COLON nls expression
-    |   MUL COLON nls expression
+    :   namedArgLabel COLON nls plainExpression
+    |   MUL COLON nls plainExpression
     ;
 
 mapEntryLabel
@@ -1092,7 +1206,7 @@ creator[int t]
     ;
 
 dim
-    :   annotationsOpt LBRACK expression? RBRACK
+    :   annotationsOpt LBRACK plainExpression? RBRACK
     ;
 
 arrayInitializer
diff --git a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 8d6e98d..2510a25 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -3023,7 +3023,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
                     new BinaryExpression(
                             configureAST(new TupleExpression(leftExpr), ctx.left),
                             this.createGroovyToken(ctx.op),
-                            this.visitEnhancedStatementExpression(ctx.enhancedStatementExpression())),
+                            (Expression) this.visit(ctx.right)),
                     ctx);
         }
 
@@ -3050,7 +3050,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
                 new BinaryExpression(
                         leftExpr,
                         this.createGroovyToken(ctx.op),
-                        this.visitEnhancedStatementExpression(ctx.enhancedStatementExpression())),
+                        (Expression) this.visit(ctx.right)),
                 ctx);
     }
 
diff --git a/src/test-resources/core/Lambda_01x.groovy b/src/test-resources/core/Lambda_01x.groovy
index 5c147ac..9ea2efe 100644
--- a/src/test-resources/core/Lambda_01x.groovy
+++ b/src/test-resources/core/Lambda_01x.groovy
@@ -61,6 +61,6 @@ assert 6 == c()(3)
 c = { (e) -> { e * 2 } }
 assert 6 == c()(3)
 
-assert ['1', '2', '3'] == [0, 1, 2].collect(e -> String.valueOf e + 1)
-assert [3, 4, 5] == ['0', '1', '2'].collect(e -> Integer.parseInt e plus 1 plus 2)
-assert [4] == ['0'].collect(e -> e.length() plus 1 plus 2)
\ No newline at end of file
+assert ['1', '2', '3'] == [0, 1, 2].collect(e -> String.valueOf(e + 1))
+assert [3, 4, 5] == ['0', '1', '2'].collect(e -> Integer.parseInt(e ).plus(1).plus(2))
+assert [4] == ['0'].collect(e -> e.length().plus(1).plus(2))
\ No newline at end of file