Skip to content

Commit b5553f9

Browse files
committed
HCL: allow if and in as attribute and object key names
The HCL lexer reserves `IF` and `IN` as dedicated tokens for use in for-expressions, but the spec doesn't reserve these as keywords at the body level. Terraform itself accepts `if` and `in` as attribute names and object keys, so the parser should too. Extend the `attribute` and `qualifiedIdentifier` rules to accept `IF` and `IN` alongside `Identifier`. The visitor walks `qualifiedIdentifier` children in source order to keep dotted-name positions correct when the alternatives are interleaved. Fixes #6446
1 parent 240bead commit b5553f9

5 files changed

Lines changed: 265 additions & 109 deletions

File tree

rewrite-hcl/src/main/antlr/HCLParser.g4

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ bodyContent
1919
;
2020

2121
attribute
22-
: (Identifier | NULL) ASSIGN expression
22+
: (Identifier | NULL | IF | IN) ASSIGN expression
2323
;
2424

2525
block
@@ -91,7 +91,7 @@ objectelem
9191
;
9292

9393
qualifiedIdentifier
94-
: Identifier (DOT Identifier)*
94+
: (Identifier | IF | IN) (DOT (Identifier | IF | IN))*
9595
;
9696

9797
// For Expressions

rewrite-hcl/src/main/java/org/openrewrite/hcl/internal/HclParserVisitor.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public Hcl visitAttribute(HCLParser.AttributeContext ctx) {
7171
randomId(),
7272
Space.format(prefix),
7373
Markers.EMPTY,
74-
c.Identifier() != null ? visitIdentifier(c.Identifier()) : visitIdentifier(c.NULL()),
74+
visitIdentifier(attributeNameToken(c)),
7575
new HclLeftPadded<>(
7676
sourceBefore("="),
7777
Hcl.Attribute.Type.Assignment,
@@ -82,6 +82,33 @@ public Hcl visitAttribute(HCLParser.AttributeContext ctx) {
8282
));
8383
}
8484

85+
private static TerminalNode attributeNameToken(HCLParser.AttributeContext ctx) {
86+
if (ctx.Identifier() != null) {
87+
return ctx.Identifier();
88+
} else if (ctx.NULL() != null) {
89+
return ctx.NULL();
90+
} else if (ctx.IF() != null) {
91+
return ctx.IF();
92+
} else if (ctx.IN() != null) {
93+
return ctx.IN();
94+
}
95+
throw new IllegalStateException("Unexpected attribute name token in: " + ctx.getText());
96+
}
97+
98+
private static List<TerminalNode> qualifiedIdentifierNames(HCLParser.QualifiedIdentifierContext ctx) {
99+
List<TerminalNode> names = new ArrayList<>();
100+
for (int i = 0; i < ctx.getChildCount(); i++) {
101+
ParseTree child = ctx.getChild(i);
102+
if (child instanceof TerminalNode) {
103+
int type = ((TerminalNode) child).getSymbol().getType();
104+
if (type != HCLParser.DOT) {
105+
names.add((TerminalNode) child);
106+
}
107+
}
108+
}
109+
return names;
110+
}
111+
85112
@Override
86113
public Hcl visitAttributeAccessExpression(HCLParser.AttributeAccessExpressionContext ctx) {
87114
return convert(ctx, (c, prefix) -> new Hcl.AttributeAccess(
@@ -744,7 +771,7 @@ public Hcl visitVariableExpr(HCLParser.VariableExprContext ctx) {
744771
if (ctx == null) {
745772
return null;
746773
}
747-
List<TerminalNode> identifiers = ctx.Identifier();
774+
List<TerminalNode> identifiers = qualifiedIdentifierNames(ctx);
748775
if (identifiers.size() == 1) {
749776
return visitIdentifier(identifiers.get(0));
750777
}

rewrite-hcl/src/main/java/org/openrewrite/hcl/internal/grammar/HCLParser.interp

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)