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

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

commit a76dcfd73db98d8d18e3a2a6fede0e314b5a3f4f
Author: Daniel Sun <[email protected]>
AuthorDate: Sat Jul 18 19:25:22 2026 +0900

    GROOVY-12173: Left-factor parser rules to reduce lookahead on hot parse 
paths
---
 src/antlr/GroovyParser.g4                          | 53 ++++++++++++++--------
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 32 +++++--------
 2 files changed, 46 insertions(+), 39 deletions(-)

diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
index 3eb0dedeed..8ab7bf6fb3 100644
--- a/src/antlr/GroovyParser.g4
+++ b/src/antlr/GroovyParser.g4
@@ -118,8 +118,10 @@ packageDeclaration
     ;
 
 importDeclaration
-    :   annotationsOpt IMPORT STATIC? qualifiedName (DOT MUL | AS 
alias=identifier)?
-    |   annotationsOpt IMPORT MODULE qualifiedName
+    :   annotationsOpt IMPORT
+        (   MODULE qualifiedName
+        |   STATIC? qualifiedName (DOT MUL | AS alias=identifier)?
+        )
     ;
 
 
@@ -557,8 +559,7 @@ block
     ;
 
 blockStatement
-    :   localVariableDeclaration
-    |   statement
+    :   statement
     ;
 
 localVariableDeclaration
@@ -579,8 +580,11 @@ variableDeclaration[int t]
     ;
 
 typeNamePairs
-    :   LPAREN typeNamePair (COMMA typeNamePair)* RPAREN
-    |   LPAREN keyedPair (COMMA keyedPair)* RPAREN
+    :   LPAREN
+        (   typeNamePair (COMMA typeNamePair)*
+        |   keyedPair (COMMA keyedPair)*
+        )
+        RPAREN
     ;
 
 typeNamePair
@@ -978,21 +982,32 @@ pathExpression returns [int t]
 pathElement returns [int t]
     :   nls
         (
-            DOT nls NEW creator[1]
-            { $t = 6; }
-        |
-            // AT: foo.@bar selects the field (or attribute), not property
-            (
-                (   DOT                 // The all-powerful dot.
-                |   SPREAD_DOT          // Spread operator:  x*.y  ===  
x?.collect{it.y}
-                |   SAFE_DOT            // Optional-null operator:  x?.y  === 
(x==null)?null:x.y
-                |   SAFE_CHAIN_DOT      // Optional-null chain operator:  
x??.y.z  === x?.y?.z
-                ) nls (AT | nonWildcardTypeArguments)?
-            |
-                METHOD_POINTER nls      // Method pointer operator: foo.&y == 
foo.metaClass.getMethodPointer(foo, "y")
+            // DOT is left-factored: `obj.new X` (inner-class creator) vs 
`obj.prop`
+            // previously sat in two alternatives that both started with DOT, 
forcing
+            // SLL prediction to explore both branches. After DOT, NEW is 
LL(1).
+            DOT nls
+            (   NEW creator[1]
+                { $t = 6; }
             |
-                METHOD_REFERENCE nls (nonWildcardTypeArguments)?  // Method 
reference: System.out::println
+                // AT: foo.@bar selects the field (or attribute), not property
+                (AT | nonWildcardTypeArguments)?
+                namePart
+                { $t = 1; }
             )
+        |
+            // Non-DOT member selection operators (still share namePart tail)
+            (   SPREAD_DOT          // Spread operator:  x*.y  ===  
x?.collect{it.y}
+            |   SAFE_DOT            // Optional-null operator:  x?.y  === 
(x==null)?null:x.y
+            |   SAFE_CHAIN_DOT      // Optional-null chain operator:  x??.y.z  
=== x?.y?.z
+            ) nls (AT | nonWildcardTypeArguments)?
+            namePart
+            { $t = 1; }
+        |
+            METHOD_POINTER nls      // Method pointer operator: foo.&y == 
foo.metaClass.getMethodPointer(foo, "y")
+            namePart
+            { $t = 1; }
+        |
+            METHOD_REFERENCE nls (nonWildcardTypeArguments)?  // Method 
reference: System.out::println
             namePart
             { $t = 1; }
 
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 aaeb90b9fd..deaaf9988d 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -4351,29 +4351,21 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
 
     @Override
     public Statement visitBlockStatement(final BlockStatementContext ctx) {
-        if (asBoolean(ctx.localVariableDeclaration())) {
-            return 
configureAST(this.visitLocalVariableDeclaration(ctx.localVariableDeclaration()),
 ctx);
-        }
-
-        if (asBoolean(ctx.statement())) {
-            Object astNode = this.visit(ctx.statement()); 
//this.configureAST((Statement) this.visit(ctx.statement()), ctx);
-
-            if (null == astNode) {
-                return null;
-            }
+        Object astNode = this.visit(ctx.statement());
 
-            if (astNode instanceof Statement) {
-                return (Statement) astNode;
-            } else if (astNode instanceof MethodNode) {
-                throw createParsingFailedException("Method definition not 
expected here", ctx);
-            } else if (astNode instanceof ImportNode) {
-                throw createParsingFailedException("Import statement not 
expected here", ctx);
-            } else {
-                throw createParsingFailedException("The statement(" + 
astNode.getClass() + ") not expected here", ctx);
-            }
+        if (null == astNode) {
+            return null;
         }
 
-        throw createParsingFailedException("Unsupported block statement: " + 
ctx.getText(), ctx);
+        if (astNode instanceof Statement) {
+            return (Statement) astNode;
+        } else if (astNode instanceof MethodNode) {
+            throw createParsingFailedException("Method definition not expected 
here", ctx);
+        } else if (astNode instanceof ImportNode) {
+            throw createParsingFailedException("Import statement not expected 
here", ctx);
+        } else {
+            throw createParsingFailedException("The statement(" + 
astNode.getClass() + ") not expected here", ctx);
+        }
     }
 
     @Override

Reply via email to