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