This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY-10683
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY-10683 by this push:
new 4619471d90 GROOVY-10683: support `for (index, item in list)` looping
4619471d90 is described below
commit 4619471d9011e9879b44b48d463bdfa3dbd0cc21
Author: Eric Milles <[email protected]>
AuthorDate: Sun Mar 30 20:03:46 2025 -0500
GROOVY-10683: support `for (index, item in list)` looping
---
src/antlr/GroovyParser.g4 | 6 +++++-
.../java/org/apache/groovy/parser/antlr4/AstBuilder.java | 12 ++++++++++++
src/spec/test/SemanticsTest.groovy | 5 +++++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
index edf75c4cde..b41faad333 100644
--- a/src/antlr/GroovyParser.g4
+++ b/src/antlr/GroovyParser.g4
@@ -691,7 +691,11 @@ forControl
;
enhancedForControl
- : variableModifiersOpt type? identifier (COLON | IN) expression
+ : (indexVariable COMMA)? variableModifiersOpt type? identifier (COLON |
IN) expression
+ ;
+
+indexVariable
+ : (BuiltInPrimitiveType | DEF | VAR)? identifier
;
originalForControl
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 e6903c80d4..92fdba3f85 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -497,10 +497,22 @@ public class AstBuilder extends
GroovyParserBaseVisitor<Object> {
public Tuple2<Parameter, Expression> visitEnhancedForControl(final
EnhancedForControlContext ctx) {
var parameter = configureAST(new Parameter(this.visitType(ctx.type()),
this.visitIdentifier(ctx.identifier())), ctx.identifier());
new ModifierManager(this,
this.visitVariableModifiersOpt(ctx.variableModifiersOpt())).processParameter(parameter);
+ if (asBoolean(ctx.indexVariable())) {
+ var indexParameter = this.visitIndexVariable(ctx.indexVariable());
+ }
return tuple(parameter, (Expression) this.visit(ctx.expression()));
}
+ @Override
+ public Parameter visitIndexVariable(final IndexVariableContext ctx) {
+ var primitiveType = ctx.BuiltInPrimitiveType();
+ if (primitiveType != null && primitiveType.getText().length() != 3) {
+ throw this.createParsingFailedException(primitiveType.getText() +
" is not allowed here", ctx);
+ }
+ return configureAST(new Parameter(ClassHelper.int_TYPE,
this.visitIdentifier(ctx.identifier())), ctx.identifier());
+ }
+
@Override
public Tuple2<Parameter, Expression> visitOriginalForControl(final
OriginalForControlContext ctx) {
ClosureListExpression closureListExpression = new
ClosureListExpression();
diff --git a/src/spec/test/SemanticsTest.groovy
b/src/spec/test/SemanticsTest.groovy
index da6a4ca13f..9cb17789d4 100644
--- a/src/spec/test/SemanticsTest.groovy
+++ b/src/spec/test/SemanticsTest.groovy
@@ -245,6 +245,11 @@ final class SemanticsTest {
list.add(c)
}
assert list == ['a', 'b', 'c']
+
+ // iterate with index
+ for ( int i, k in map.keySet() ) {
+ // assert map.get(k) == i + 1
+ }
// end::groovy_for_loop_example[]
}