Skip to content

Commit 1df3105

Browse files
authored
GROOVY-12173: Left-factor parser rules to reduce lookahead on hot parse paths (#2720)
1 parent bfdfd85 commit 1df3105

3 files changed

Lines changed: 412 additions & 39 deletions

File tree

src/antlr/GroovyParser.g4

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,10 @@ packageDeclaration
118118
;
119119

120120
importDeclaration
121-
: annotationsOpt IMPORT STATIC? qualifiedName (DOT MUL | AS alias=identifier)?
122-
| annotationsOpt IMPORT MODULE qualifiedName
121+
: annotationsOpt IMPORT
122+
( MODULE qualifiedName
123+
| STATIC? qualifiedName (DOT MUL | AS alias=identifier)?
124+
)
123125
;
124126

125127

@@ -557,8 +559,7 @@ block
557559
;
558560

559561
blockStatement
560-
: localVariableDeclaration
561-
| statement
562+
: statement
562563
;
563564

564565
localVariableDeclaration
@@ -579,8 +580,11 @@ variableDeclaration[int t]
579580
;
580581

581582
typeNamePairs
582-
: LPAREN typeNamePair (COMMA typeNamePair)* RPAREN
583-
| LPAREN keyedPair (COMMA keyedPair)* RPAREN
583+
: LPAREN
584+
( typeNamePair (COMMA typeNamePair)*
585+
| keyedPair (COMMA keyedPair)*
586+
)
587+
RPAREN
584588
;
585589

586590
typeNamePair
@@ -978,21 +982,29 @@ pathExpression returns [int t]
978982
pathElement returns [int t]
979983
: nls
980984
(
981-
DOT nls NEW creator[1]
982-
{ $t = 6; }
983-
|
984-
// AT: foo.@bar selects the field (or attribute), not property
985-
(
986-
( DOT // The all-powerful dot.
987-
| SPREAD_DOT // Spread operator: x*.y === x?.collect{it.y}
988-
| SAFE_DOT // Optional-null operator: x?.y === (x==null)?null:x.y
989-
| SAFE_CHAIN_DOT // Optional-null chain operator: x??.y.z === x?.y?.z
990-
) nls (AT | nonWildcardTypeArguments)?
991-
|
992-
METHOD_POINTER nls // Method pointer operator: foo.&y == foo.metaClass.getMethodPointer(foo, "y")
985+
DOT nls
986+
( NEW creator[1]
987+
{ $t = 6; }
993988
|
994-
METHOD_REFERENCE nls (nonWildcardTypeArguments)? // Method reference: System.out::println
989+
// AT: foo.@bar selects the field (or attribute), not property
990+
(AT | nonWildcardTypeArguments)?
991+
namePart
992+
{ $t = 1; }
995993
)
994+
|
995+
// Non-DOT member selection operators (still share namePart tail)
996+
( SPREAD_DOT // Spread operator: x*.y === x?.collect{it.y}
997+
| SAFE_DOT // Optional-null operator: x?.y === (x==null)?null:x.y
998+
| SAFE_CHAIN_DOT // Optional-null chain operator: x??.y.z === x?.y?.z
999+
) nls (AT | nonWildcardTypeArguments)?
1000+
namePart
1001+
{ $t = 1; }
1002+
|
1003+
METHOD_POINTER nls // Method pointer operator: foo.&y == foo.metaClass.getMethodPointer(foo, "y")
1004+
namePart
1005+
{ $t = 1; }
1006+
|
1007+
METHOD_REFERENCE nls (nonWildcardTypeArguments)? // Method reference: System.out::println
9961008
namePart
9971009
{ $t = 1; }
9981010

src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4351,29 +4351,21 @@ public BlockStatement visitBlockStatements(final BlockStatementsContext ctx) {
43514351

43524352
@Override
43534353
public Statement visitBlockStatement(final BlockStatementContext ctx) {
4354-
if (asBoolean(ctx.localVariableDeclaration())) {
4355-
return configureAST(this.visitLocalVariableDeclaration(ctx.localVariableDeclaration()), ctx);
4356-
}
4357-
4358-
if (asBoolean(ctx.statement())) {
4359-
Object astNode = this.visit(ctx.statement()); //this.configureAST((Statement) this.visit(ctx.statement()), ctx);
4360-
4361-
if (null == astNode) {
4362-
return null;
4363-
}
4354+
Object astNode = this.visit(ctx.statement());
43644355

4365-
if (astNode instanceof Statement) {
4366-
return (Statement) astNode;
4367-
} else if (astNode instanceof MethodNode) {
4368-
throw createParsingFailedException("Method definition not expected here", ctx);
4369-
} else if (astNode instanceof ImportNode) {
4370-
throw createParsingFailedException("Import statement not expected here", ctx);
4371-
} else {
4372-
throw createParsingFailedException("The statement(" + astNode.getClass() + ") not expected here", ctx);
4373-
}
4356+
if (null == astNode) {
4357+
return null;
43744358
}
43754359

4376-
throw createParsingFailedException("Unsupported block statement: " + ctx.getText(), ctx);
4360+
if (astNode instanceof Statement) {
4361+
return (Statement) astNode;
4362+
} else if (astNode instanceof MethodNode) {
4363+
throw createParsingFailedException("Method definition not expected here", ctx);
4364+
} else if (astNode instanceof ImportNode) {
4365+
throw createParsingFailedException("Import statement not expected here", ctx);
4366+
} else {
4367+
throw createParsingFailedException("The statement(" + astNode.getClass() + ") not expected here", ctx);
4368+
}
43774369
}
43784370

43794371
@Override

0 commit comments

Comments
 (0)