zclsyntax: recoverAfterBodyItem implementation
This recovery method attempts to place the peeker directly after the newline indicating the end of the current body item. It does this by counting open and close bracketing constructs and then returning when a newline is encountered with no bracketing constructs open. It's designed for use in the "header" part of a body item, with no bracketing constructs open yet. It _might_ work in other situations, but is likely to end up choosing the wrong end point if used in the middle of a bracketed expression that itself contains newlines.
This commit is contained in:
parent
9348014b2d
commit
db5167e3d8
@ -377,11 +377,45 @@ Token:
|
||||
}
|
||||
|
||||
func (p *parser) recoverAfterBodyItem() {
|
||||
// TODO: Seek forward until we find a newline that isn't inside any
|
||||
// bracketer, and return with the peeker placed after it so we're
|
||||
// ready to try to parse another body item.
|
||||
p.recovery = true
|
||||
var open []TokenType
|
||||
|
||||
Token:
|
||||
for {
|
||||
tok := p.Read()
|
||||
|
||||
switch tok.Type {
|
||||
|
||||
case TokenNewline:
|
||||
if len(open) == 0 {
|
||||
break Token
|
||||
}
|
||||
|
||||
case TokenEOF:
|
||||
break Token
|
||||
|
||||
case TokenOBrace, TokenOBrack, TokenOParen, TokenOQuote, TokenOHeredoc, TokenTemplateInterp, TokenTemplateControl:
|
||||
open = append(open, tok.Type)
|
||||
|
||||
case TokenCBrace, TokenCBrack, TokenCParen, TokenCQuote, TokenCHeredoc:
|
||||
opener := p.oppositeBracket(tok.Type)
|
||||
for len(open) > 0 && open[len(open)-1] != opener {
|
||||
open = open[:len(open)-1]
|
||||
}
|
||||
if len(open) > 0 {
|
||||
open = open[:len(open)-1]
|
||||
}
|
||||
|
||||
case TokenTemplateSeqEnd:
|
||||
for len(open) > 0 && open[len(open)-1] != TokenTemplateInterp && open[len(open)-1] != TokenTemplateControl {
|
||||
open = open[:len(open)-1]
|
||||
}
|
||||
if len(open) > 0 {
|
||||
open = open[:len(open)-1]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// oppositeBracket finds the bracket that opposes the given bracketer, or
|
||||
|
@ -79,7 +79,6 @@ func TestParseConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
`block "foo" {}`,
|
||||
0,
|
||||
@ -133,6 +132,93 @@ func TestParseConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
`
|
||||
block "invalid" 1.2 {}
|
||||
block "valid" {}
|
||||
`,
|
||||
1,
|
||||
&Body{
|
||||
Attributes: Attributes{},
|
||||
Blocks: Blocks{
|
||||
&Block{
|
||||
Type: "block",
|
||||
Labels: []string{"invalid"},
|
||||
Body: nil,
|
||||
|
||||
TypeRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 2, Column: 1, Byte: 1},
|
||||
End: zcl.Pos{Line: 2, Column: 6, Byte: 6},
|
||||
},
|
||||
LabelRanges: []zcl.Range{
|
||||
{
|
||||
Start: zcl.Pos{Line: 2, Column: 7, Byte: 7},
|
||||
End: zcl.Pos{Line: 2, Column: 16, Byte: 16},
|
||||
},
|
||||
},
|
||||
|
||||
// Since we failed parsing before we got to the
|
||||
// braces, the type range is used as a placeholder
|
||||
// for these.
|
||||
OpenBraceRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 2, Column: 1, Byte: 1},
|
||||
End: zcl.Pos{Line: 2, Column: 6, Byte: 6},
|
||||
},
|
||||
CloseBraceRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 2, Column: 1, Byte: 1},
|
||||
End: zcl.Pos{Line: 2, Column: 6, Byte: 6},
|
||||
},
|
||||
},
|
||||
|
||||
// Recovery behavior should allow us to still see this
|
||||
// second block, even though the first was invalid.
|
||||
&Block{
|
||||
Type: "block",
|
||||
Labels: []string{"valid"},
|
||||
Body: &Body{
|
||||
Attributes: Attributes{},
|
||||
Blocks: Blocks{},
|
||||
|
||||
SrcRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 3, Column: 15, Byte: 38},
|
||||
End: zcl.Pos{Line: 3, Column: 17, Byte: 40},
|
||||
},
|
||||
EndRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 3, Column: 17, Byte: 40},
|
||||
End: zcl.Pos{Line: 3, Column: 17, Byte: 40},
|
||||
},
|
||||
},
|
||||
|
||||
TypeRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 3, Column: 1, Byte: 24},
|
||||
End: zcl.Pos{Line: 3, Column: 6, Byte: 29},
|
||||
},
|
||||
LabelRanges: []zcl.Range{
|
||||
{
|
||||
Start: zcl.Pos{Line: 3, Column: 7, Byte: 30},
|
||||
End: zcl.Pos{Line: 3, Column: 14, Byte: 37},
|
||||
},
|
||||
},
|
||||
OpenBraceRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 3, Column: 15, Byte: 38},
|
||||
End: zcl.Pos{Line: 3, Column: 16, Byte: 39},
|
||||
},
|
||||
CloseBraceRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 3, Column: 16, Byte: 39},
|
||||
End: zcl.Pos{Line: 3, Column: 17, Byte: 40},
|
||||
},
|
||||
},
|
||||
},
|
||||
SrcRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 1, Column: 1, Byte: 0},
|
||||
End: zcl.Pos{Line: 4, Column: 1, Byte: 41},
|
||||
},
|
||||
EndRange: zcl.Range{
|
||||
Start: zcl.Pos{Line: 4, Column: 1, Byte: 41},
|
||||
End: zcl.Pos{Line: 4, Column: 1, Byte: 41},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
prettyConfig := &pretty.Config{
|
||||
|
Loading…
Reference in New Issue
Block a user