zclwrite: initial attribute and basic expression parsing

This is not yet complete, since it fails to capture the newline, line
comments, and variable references in expressions. However, it does
capture the broad structure of an attribute, along with gathering up
all of its _interior_ tokens.
This commit is contained in:
Martin Atkins 2017-06-07 08:24:33 -07:00
parent 15b38d8a48
commit 13c93e974f
3 changed files with 119 additions and 27 deletions

View File

@ -77,13 +77,17 @@ type Attribute struct {
LeadCommentTokens *TokenSeq LeadCommentTokens *TokenSeq
NameTokens *TokenSeq NameTokens *TokenSeq
EqualsTokens *TokenSeq EqualsTokens *TokenSeq
Value *Expression Expr *Expression
LineCommentTokens *TokenSeq LineCommentTokens *TokenSeq
EOLTokens *TokenSeq EOLTokens *TokenSeq
} }
func (a *Attribute) walkChildNodes(w internalWalkFunc) { func (a *Attribute) walkChildNodes(w internalWalkFunc) {
w(a.Value) w(a.Expr)
}
func (n *Attribute) Tokens() *TokenSeq {
return n.AllTokens
} }
type Block struct { type Block struct {

View File

@ -146,12 +146,11 @@ func parseBodyItem(nativeItem zclsyntax.Node, from inputTokens) (inputTokens, No
var item Node var item Node
switch nativeItem.(type) { switch tItem := nativeItem.(type) {
case *zclsyntax.Attribute: case *zclsyntax.Attribute:
// TODO: actually deconstruct the attribute parts item = parseAttribute(tItem, within)
item = &Unstructured{ // TODO: Grab the newline and any line comment from "after" and
AllTokens: within.Seq(), // write them into the attribute object.
}
case *zclsyntax.Block: case *zclsyntax.Block:
// TODO: actually deconstruct the block parts // TODO: actually deconstruct the block parts
item = &Unstructured{ item = &Unstructured{
@ -165,6 +164,50 @@ func parseBodyItem(nativeItem zclsyntax.Node, from inputTokens) (inputTokens, No
return before, item, after return before, item, after
} }
func parseAttribute(nativeAttr *zclsyntax.Attribute, from inputTokens) *Attribute {
var allTokens TokenSeq
attr := &Attribute{}
before, nameTokens, from := from.Partition(nativeAttr.NameRange)
if before.Len() > 0 {
allTokens = append(allTokens, before.Seq())
}
attr.NameTokens = nameTokens.Seq()
allTokens = append(allTokens, attr.NameTokens)
before, equalsTokens, from := from.Partition(nativeAttr.EqualsRange)
if before.Len() > 0 {
allTokens = append(allTokens, before.Seq())
}
attr.EqualsTokens = equalsTokens.Seq()
allTokens = append(allTokens, attr.EqualsTokens)
before, exprTokens, from := from.Partition(nativeAttr.Expr.Range())
if before.Len() > 0 {
allTokens = append(allTokens, before.Seq())
}
attr.Expr = parseExpression(nativeAttr.Expr, exprTokens)
allTokens = append(allTokens, attr.Expr.AllTokens)
// Collect any stragglers, although we shouldn't generally have any since
// the newline and any line comments don't get included in the attribute's
// range.
if from.Len() > 0 {
allTokens = append(allTokens, from.Seq())
}
attr.AllTokens = &allTokens
return attr
}
func parseExpression(nativeExpr zclsyntax.Expression, from inputTokens) *Expression {
// TODO: Populate VarRefs by analyzing the result of nativeExpr.Variables()
return &Expression{
AllTokens: from.Seq(),
}
}
// writerTokens takes a sequence of tokens as produced by the main zclsyntax // writerTokens takes a sequence of tokens as produced by the main zclsyntax
// package and transforms it into an equivalent sequence of tokens using // package and transforms it into an equivalent sequence of tokens using
// this package's own token model. // this package's own token model.

View File

@ -27,26 +27,7 @@ func TestParse(t *testing.T) {
"a = 1", "a = 1",
&Body{ &Body{
Items: []Node{ Items: []Node{
&Unstructured{ &Attribute{
AllTokens: &TokenSeq{Tokens{
{
Type: zclsyntax.TokenIdent,
Bytes: []byte(`a`),
SpacesBefore: 0,
},
{
Type: zclsyntax.TokenEqual,
Bytes: []byte(`=`),
SpacesBefore: 1,
},
{
Type: zclsyntax.TokenNumberLit,
Bytes: []byte(`1`),
SpacesBefore: 1,
},
}},
},
},
AllTokens: &TokenSeq{ AllTokens: &TokenSeq{
&TokenSeq{ &TokenSeq{
Tokens{ Tokens{
@ -55,11 +36,19 @@ func TestParse(t *testing.T) {
Bytes: []byte(`a`), Bytes: []byte(`a`),
SpacesBefore: 0, SpacesBefore: 0,
}, },
},
},
&TokenSeq{
Tokens{
{ {
Type: zclsyntax.TokenEqual, Type: zclsyntax.TokenEqual,
Bytes: []byte(`=`), Bytes: []byte(`=`),
SpacesBefore: 1, SpacesBefore: 1,
}, },
},
},
&TokenSeq{
Tokens{
{ {
Type: zclsyntax.TokenNumberLit, Type: zclsyntax.TokenNumberLit,
Bytes: []byte(`1`), Bytes: []byte(`1`),
@ -68,6 +57,62 @@ func TestParse(t *testing.T) {
}, },
}, },
}, },
NameTokens: &TokenSeq{Tokens{
{
Type: zclsyntax.TokenIdent,
Bytes: []byte(`a`),
SpacesBefore: 0,
},
}},
EqualsTokens: &TokenSeq{Tokens{
{
Type: zclsyntax.TokenEqual,
Bytes: []byte(`=`),
SpacesBefore: 1,
},
}},
Expr: &Expression{
AllTokens: &TokenSeq{Tokens{
{
Type: zclsyntax.TokenNumberLit,
Bytes: []byte(`1`),
SpacesBefore: 1,
},
}},
},
},
},
AllTokens: &TokenSeq{
&TokenSeq{
&TokenSeq{
Tokens{
{
Type: zclsyntax.TokenIdent,
Bytes: []byte(`a`),
SpacesBefore: 0,
},
},
},
&TokenSeq{
Tokens{
{
Type: zclsyntax.TokenEqual,
Bytes: []byte(`=`),
SpacesBefore: 1,
},
},
},
&TokenSeq{
Tokens{
{
Type: zclsyntax.TokenNumberLit,
Bytes: []byte(`1`),
SpacesBefore: 1,
},
},
},
},
},
}, },
}, },
} }