hclsyntax: allow block labels to be naked identifiers

This was allowed in legacy HCL, and although it was never documented as
usable in the Terraform documentation it appears that some Terraform
configurations use this form anyway.

While it is non-ideal to have another edge-case to support/maintain, this
capability adds no ambiguity and doesn't add significant complexity, so
we'll allow it to be pragmatic for existing usage.
This commit is contained in:
Martin Atkins 2018-03-03 10:09:10 -08:00
parent 074b73b8b5
commit d66303f45b
3 changed files with 65 additions and 4 deletions

View File

@ -132,7 +132,7 @@ func (p *parser) ParseBodyItem() (Node, hcl.Diagnostics) {
switch next.Type {
case TokenEqual:
return p.finishParsingBodyAttribute(ident)
case TokenOQuote, TokenOBrace:
case TokenOQuote, TokenOBrace, TokenIdent:
return p.finishParsingBodyBlock(ident)
default:
p.recoverAfterBodyItem()
@ -232,6 +232,12 @@ Token:
}, diags
}
case TokenIdent:
tok = p.Read() // eat token
label, labelRange := string(tok.Bytes), tok.Range
labels = append(labels, label)
labelRanges = append(labelRanges, labelRange)
default:
switch tok.Type {
case TokenEqual:

View File

@ -228,6 +228,59 @@ func TestParseConfig(t *testing.T) {
},
},
},
{
"block foo {}\n",
0,
&Body{
Attributes: Attributes{},
Blocks: Blocks{
&Block{
Type: "block",
Labels: []string{"foo"},
Body: &Body{
Attributes: Attributes{},
Blocks: Blocks{},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 11, Byte: 10},
End: hcl.Pos{Line: 1, Column: 13, Byte: 12},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 13, Byte: 12},
End: hcl.Pos{Line: 1, Column: 13, Byte: 12},
},
},
TypeRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
LabelRanges: []hcl.Range{
{
Start: hcl.Pos{Line: 1, Column: 7, Byte: 6},
End: hcl.Pos{Line: 1, Column: 10, Byte: 9},
},
},
OpenBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 11, Byte: 10},
End: hcl.Pos{Line: 1, Column: 12, Byte: 11},
},
CloseBraceRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 12, Byte: 11},
End: hcl.Pos{Line: 1, Column: 13, Byte: 12},
},
},
},
SrcRange: hcl.Range{
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 2, Column: 1, Byte: 13},
},
EndRange: hcl.Range{
Start: hcl.Pos{Line: 2, Column: 1, Byte: 13},
End: hcl.Pos{Line: 2, Column: 1, Byte: 13},
},
},
},
{
`
block "invalid" 1.2 {}

View File

@ -161,7 +161,7 @@ language-agnostic HCL information model.
ConfigFile = Body;
Body = (Attribute | Block)*;
Attribute = Identifier "=" Expression Newline;
Block = Identifier (StringLit)* "{" Newline Body "}" Newline;
Block = Identifier (StringLit|Identifier)* "{" Newline Body "}" Newline;
```
### Configuration Files
@ -186,8 +186,10 @@ for later evaluation by the calling application.
### Blocks
A _block_ creates a child body that is annotated with a block _type_ and
zero or more optional block _labels_. Blocks create a structural heirachy
which can be interpreted by the calling application.
zero or more block _labels_. Blocks create a structural heirachy which can be
interpreted by the calling application.
Block labels can either be quoted literal strings or naked identifiers.
## Expressions