zclwrite: parsing of blocks
There's something a little off here, as illustrated by the failing round trip test. Will figure that out later.
This commit is contained in:
parent
948b2e0b7b
commit
cb768a591a
@ -195,8 +195,7 @@ func parseBodyItem(nativeItem zclsyntax.Node, from inputTokens) (inputTokens, No
|
||||
case *zclsyntax.Attribute:
|
||||
item = parseAttribute(tItem, within, leadComments, lineComments, newline)
|
||||
case *zclsyntax.Block:
|
||||
// TODO: implement this
|
||||
panic("block parsing not yet implemented")
|
||||
item = parseBlock(tItem, within, leadComments, lineComments, newline)
|
||||
default:
|
||||
// should never happen if caller is behaving
|
||||
panic("unsupported native item type")
|
||||
@ -255,6 +254,78 @@ func parseAttribute(nativeAttr *zclsyntax.Attribute, from, leadComments, lineCom
|
||||
return attr
|
||||
}
|
||||
|
||||
func parseBlock(nativeBlock *zclsyntax.Block, from, leadComments, lineComments, newline inputTokens) *Block {
|
||||
var allTokens TokenSeq
|
||||
block := &Block{}
|
||||
|
||||
if leadComments.Len() > 0 {
|
||||
block.LeadCommentTokens = leadComments.Seq()
|
||||
allTokens = append(allTokens, block.LeadCommentTokens)
|
||||
}
|
||||
|
||||
before, typeTokens, from := from.Partition(nativeBlock.TypeRange)
|
||||
if before.Len() > 0 {
|
||||
allTokens = append(allTokens, before.Seq())
|
||||
}
|
||||
block.TypeTokens = typeTokens.Seq()
|
||||
allTokens = append(allTokens, block.TypeTokens)
|
||||
|
||||
for _, rng := range nativeBlock.LabelRanges {
|
||||
var labelTokens inputTokens
|
||||
before, labelTokens, from = from.Partition(rng)
|
||||
if before.Len() > 0 {
|
||||
allTokens = append(allTokens, before.Seq())
|
||||
}
|
||||
seq := labelTokens.Seq()
|
||||
block.LabelTokens = append(block.LabelTokens, seq)
|
||||
*(block.LabelTokensFlat) = append(*(block.LabelTokensFlat), seq)
|
||||
allTokens = append(allTokens, seq)
|
||||
}
|
||||
|
||||
before, oBrace, from := from.Partition(nativeBlock.OpenBraceRange)
|
||||
if before.Len() > 0 {
|
||||
allTokens = append(allTokens, before.Seq())
|
||||
}
|
||||
block.OBraceTokens = oBrace.Seq()
|
||||
allTokens = append(allTokens, block.OBraceTokens)
|
||||
|
||||
// We go a bit out of order here: we go hunting for the closing brace
|
||||
// so that we have a delimited body, but then we'll deal with the body
|
||||
// before we actually append the closing brace and any straggling tokens
|
||||
// that appear after it.
|
||||
bodyTokens, cBrace, from := from.Partition(nativeBlock.CloseBraceRange)
|
||||
before, body, after := parseBody(nativeBlock.Body, bodyTokens)
|
||||
|
||||
if before.Len() > 0 {
|
||||
allTokens = append(allTokens, before.Seq())
|
||||
}
|
||||
block.Body = body
|
||||
allTokens = append(allTokens, body.AllTokens)
|
||||
if after.Len() > 0 {
|
||||
allTokens = append(allTokens, after.Seq())
|
||||
}
|
||||
|
||||
block.CBraceTokens = cBrace.Seq()
|
||||
allTokens = append(allTokens, block.CBraceTokens)
|
||||
|
||||
// stragglers
|
||||
if after.Len() > 0 {
|
||||
allTokens = append(allTokens, from.Seq())
|
||||
}
|
||||
if lineComments.Len() > 0 {
|
||||
// blocks don't actually have line comments, so we'll just treat
|
||||
// them as extra stragglers
|
||||
allTokens = append(allTokens, lineComments.Seq())
|
||||
}
|
||||
if newline.Len() > 0 {
|
||||
block.EOLTokens = newline.Seq()
|
||||
allTokens = append(allTokens, block.EOLTokens)
|
||||
}
|
||||
|
||||
block.AllTokens = &allTokens
|
||||
return block
|
||||
}
|
||||
|
||||
func parseExpression(nativeExpr zclsyntax.Expression, from inputTokens) *Expression {
|
||||
// TODO: Populate VarRefs by analyzing the result of nativeExpr.Variables()
|
||||
return &Expression{
|
||||
@ -336,7 +407,7 @@ func partitionTokens(toks zclsyntax.Tokens, rng zcl.Range) (start, end int) {
|
||||
return len(toks), len(toks)
|
||||
}
|
||||
|
||||
if toks[i].Range.ContainsOffset(rng.Start.Byte) {
|
||||
if toks[i].Range.Start.Byte >= rng.Start.Byte {
|
||||
start = i
|
||||
break
|
||||
}
|
||||
@ -348,8 +419,8 @@ func partitionTokens(toks zclsyntax.Tokens, rng zcl.Range) (start, end int) {
|
||||
return start, len(toks)
|
||||
}
|
||||
|
||||
if toks[i].Range.End.Byte >= rng.End.Byte {
|
||||
end = i + 1 // end marker is exclusive
|
||||
if toks[i].Range.Start.Byte >= rng.End.Byte {
|
||||
end = i // end marker is exclusive
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -530,6 +530,468 @@ func TestParse(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"b {}\n",
|
||||
&Body{
|
||||
Items: []Node{
|
||||
&Block{
|
||||
AllTokens: &TokenSeq{
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenIdent,
|
||||
Bytes: []byte(`b`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenOBrace,
|
||||
Bytes: []byte(`{`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
(*TokenSeq)(nil), // the empty body
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenCBrace,
|
||||
Bytes: []byte(`}`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
TypeTokens: &TokenSeq{Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenIdent,
|
||||
Bytes: []byte(`b`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
}},
|
||||
OBraceTokens: &TokenSeq{Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenOBrace,
|
||||
Bytes: []byte(`{`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
}},
|
||||
Body: &Body{},
|
||||
CBraceTokens: &TokenSeq{Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenCBrace,
|
||||
Bytes: []byte(`}`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
}},
|
||||
EOLTokens: &TokenSeq{Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
AllTokens: &TokenSeq{
|
||||
&TokenSeq{
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenIdent,
|
||||
Bytes: []byte(`b`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenOBrace,
|
||||
Bytes: []byte(`{`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
(*TokenSeq)(nil), // the empty body
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenCBrace,
|
||||
Bytes: []byte(`}`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"b {\n a = 1\n}\n",
|
||||
&Body{
|
||||
Items: []Node{
|
||||
&Block{
|
||||
AllTokens: &TokenSeq{
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenIdent,
|
||||
Bytes: []byte(`b`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenOBrace,
|
||||
Bytes: []byte(`{`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenIdent,
|
||||
Bytes: []byte(`a`),
|
||||
SpacesBefore: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenEqual,
|
||||
Bytes: []byte(`=`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNumberLit,
|
||||
Bytes: []byte(`1`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenCBrace,
|
||||
Bytes: []byte(`}`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
TypeTokens: &TokenSeq{Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenIdent,
|
||||
Bytes: []byte(`b`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
}},
|
||||
OBraceTokens: &TokenSeq{Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenOBrace,
|
||||
Bytes: []byte(`{`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
}},
|
||||
Body: &Body{
|
||||
Items: []Node{
|
||||
&Attribute{
|
||||
AllTokens: &TokenSeq{
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenIdent,
|
||||
Bytes: []byte(`a`),
|
||||
SpacesBefore: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenEqual,
|
||||
Bytes: []byte(`=`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNumberLit,
|
||||
Bytes: []byte(`1`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
NameTokens: &TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenIdent,
|
||||
Bytes: []byte(`a`),
|
||||
SpacesBefore: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
EqualsTokens: &TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenEqual,
|
||||
Bytes: []byte(`=`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
Expr: &Expression{
|
||||
AllTokens: &TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNumberLit,
|
||||
Bytes: []byte(`1`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
EOLTokens: &TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
AllTokens: &TokenSeq{
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenIdent,
|
||||
Bytes: []byte(`a`),
|
||||
SpacesBefore: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenEqual,
|
||||
Bytes: []byte(`=`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNumberLit,
|
||||
Bytes: []byte(`1`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
CBraceTokens: &TokenSeq{Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenCBrace,
|
||||
Bytes: []byte(`}`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
}},
|
||||
EOLTokens: &TokenSeq{Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
AllTokens: &TokenSeq{
|
||||
&TokenSeq{
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenIdent,
|
||||
Bytes: []byte(`b`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenOBrace,
|
||||
Bytes: []byte(`{`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenIdent,
|
||||
Bytes: []byte(`a`),
|
||||
SpacesBefore: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenEqual,
|
||||
Bytes: []byte(`=`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNumberLit,
|
||||
Bytes: []byte(`1`),
|
||||
SpacesBefore: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenCBrace,
|
||||
Bytes: []byte(`}`),
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
&TokenSeq{
|
||||
Tokens{
|
||||
{
|
||||
Type: zclsyntax.TokenNewline,
|
||||
Bytes: []byte{'\n'},
|
||||
SpacesBefore: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
prettyConfig := &pretty.Config{
|
||||
|
@ -27,6 +27,20 @@ baz = 1
|
||||
foobar = 1
|
||||
baz = 1
|
||||
|
||||
block {
|
||||
a = "a"
|
||||
b = "b"
|
||||
c = "c"
|
||||
d = "d"
|
||||
|
||||
subblock {
|
||||
}
|
||||
|
||||
subblock {
|
||||
e = "e"
|
||||
}
|
||||
}
|
||||
|
||||
# and they all lived happily ever after
|
||||
`,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user