parser: assignments and objects are actually items and the same
This commit is contained in:
parent
3832ed0981
commit
62caacf06f
@ -8,28 +8,48 @@ type Node interface {
|
|||||||
Pos() scanner.Pos
|
Pos() scanner.Pos
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Source) node() {}
|
func (ObjectList) node() {}
|
||||||
func (Ident) node() {}
|
func (ObjectItem) node() {}
|
||||||
|
|
||||||
func (AssignStatement) node() {}
|
|
||||||
func (ObjectStatement) node() {}
|
|
||||||
|
|
||||||
func (LiteralType) node() {}
|
|
||||||
func (ObjectType) node() {}
|
func (ObjectType) node() {}
|
||||||
|
func (LiteralType) node() {}
|
||||||
func (ListType) node() {}
|
func (ListType) node() {}
|
||||||
|
func (Ident) node() {}
|
||||||
|
|
||||||
// Source represents a single HCL source file
|
// ObjectList represents a list of ObjectItems. An HCL file itself is an
|
||||||
type Source struct {
|
// ObjectList.
|
||||||
nodes []Node
|
type ObjectList struct {
|
||||||
|
items []*ObjectItem
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) add(node Node) {
|
func (o *ObjectList) add(item *ObjectItem) {
|
||||||
s.nodes = append(s.nodes, node)
|
o.items = append(o.items, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Source) Pos() scanner.Pos {
|
func (o *ObjectList) Pos() scanner.Pos {
|
||||||
// always returns the uninitiliazed position
|
// always returns the uninitiliazed position
|
||||||
return s.nodes[0].Pos()
|
return o.items[0].Pos()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectItem represents a HCL Object Item. An item is represented with a key
|
||||||
|
// (or keys). It can be an assignment or an object (both normal and nested)
|
||||||
|
type ObjectItem struct {
|
||||||
|
// key is either an Identifier or a String. The slice is only one lenght
|
||||||
|
// long, however if it's a nested object it'll can be larger than one. In
|
||||||
|
// that case "assign" is invalid as there is no assignments for a nested
|
||||||
|
// object.
|
||||||
|
key []Ident
|
||||||
|
|
||||||
|
// assign contains the position of "=", if any
|
||||||
|
assign scanner.Pos
|
||||||
|
|
||||||
|
// val is the item itself. It can be an object,list, number, bool or a
|
||||||
|
// string. If key lenght is larger than one, val can be only of type
|
||||||
|
// Object.
|
||||||
|
val Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ObjectItem) Pos() scanner.Pos {
|
||||||
|
return o.key[0].Pos()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IdentStatement represents an identifier.
|
// IdentStatement represents an identifier.
|
||||||
@ -41,27 +61,6 @@ func (i *Ident) Pos() scanner.Pos {
|
|||||||
return i.token.Pos
|
return i.token.Pos
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssignStatement represents an assignment
|
|
||||||
type AssignStatement struct {
|
|
||||||
lhs Node // left hand side of the assignment
|
|
||||||
rhs Node // right hand side of the assignment
|
|
||||||
assign scanner.Pos // position of "="
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AssignStatement) Pos() scanner.Pos {
|
|
||||||
return a.lhs.Pos()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectStatment represents an object statement
|
|
||||||
type ObjectStatement struct {
|
|
||||||
Idents []Node // the idents in elements in lexical order
|
|
||||||
ObjectType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *ObjectStatement) Pos() scanner.Pos {
|
|
||||||
return o.Idents[0].Pos()
|
|
||||||
}
|
|
||||||
|
|
||||||
// LiteralType represents a literal of basic type. Valid types are:
|
// LiteralType represents a literal of basic type. Valid types are:
|
||||||
// scanner.NUMBER, scanner.FLOAT, scanner.BOOL and scanner.STRING
|
// scanner.NUMBER, scanner.FLOAT, scanner.BOOL and scanner.STRING
|
||||||
type LiteralType struct {
|
type LiteralType struct {
|
||||||
|
@ -29,10 +29,10 @@ var errEofToken = errors.New("EOF token found")
|
|||||||
// Parse returns the fully parsed source and returns the abstract syntax tree.
|
// Parse returns the fully parsed source and returns the abstract syntax tree.
|
||||||
func (p *Parser) Parse() (Node, error) {
|
func (p *Parser) Parse() (Node, error) {
|
||||||
defer un(trace(p, "ParseSource"))
|
defer un(trace(p, "ParseSource"))
|
||||||
node := &Source{}
|
node := &ObjectList{}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
n, err := p.parseNode()
|
n, err := p.parseObjectItem()
|
||||||
if err == errEofToken {
|
if err == errEofToken {
|
||||||
break // we are finished
|
break // we are finished
|
||||||
}
|
}
|
||||||
@ -47,15 +47,15 @@ func (p *Parser) Parse() (Node, error) {
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) parseNode() (Node, error) {
|
func (p *Parser) parseObjectItem() (*ObjectItem, error) {
|
||||||
defer un(trace(p, "ParseNode"))
|
defer un(trace(p, "ParseObjectItem"))
|
||||||
|
|
||||||
tok := p.scan()
|
tok := p.scan()
|
||||||
fmt.Println(tok) // debug
|
fmt.Println(tok) // debug
|
||||||
|
|
||||||
switch tok.Type {
|
switch tok.Type {
|
||||||
case scanner.ASSIGN:
|
case scanner.ASSIGN:
|
||||||
return p.parseAssignment()
|
// return p.parseAssignment()
|
||||||
case scanner.LBRACK:
|
case scanner.LBRACK:
|
||||||
// return p.parseListType()
|
// return p.parseListType()
|
||||||
case scanner.LBRACE:
|
case scanner.LBRACE:
|
||||||
@ -66,39 +66,9 @@ func (p *Parser) parseNode() (Node, error) {
|
|||||||
return nil, errEofToken
|
return nil, errEofToken
|
||||||
}
|
}
|
||||||
|
|
||||||
if tok.Type.IsIdentifier() {
|
|
||||||
if p.prevTok.Type.IsIdentifier() {
|
|
||||||
return p.parseObjectStatement()
|
|
||||||
}
|
|
||||||
|
|
||||||
if tok.Type.IsLiteral() {
|
|
||||||
return p.parseLiteralType()
|
|
||||||
}
|
|
||||||
return p.parseIdent()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("not yet implemented: %s", tok.Type)
|
return nil, fmt.Errorf("not yet implemented: %s", tok.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseAssignment parses an assignment and returns a AssignStatement AST
|
|
||||||
func (p *Parser) parseAssignment() (*AssignStatement, error) {
|
|
||||||
defer un(trace(p, "ParseAssignment"))
|
|
||||||
a := &AssignStatement{
|
|
||||||
lhs: &Ident{
|
|
||||||
token: p.prevTok,
|
|
||||||
},
|
|
||||||
assign: p.tok.Pos,
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err := p.parseNode()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
a.rhs = n
|
|
||||||
return a, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseIdent parses a generic identifier and returns a Ident AST
|
// parseIdent parses a generic identifier and returns a Ident AST
|
||||||
func (p *Parser) parseIdent() (*Ident, error) {
|
func (p *Parser) parseIdent() (*Ident, error) {
|
||||||
defer un(trace(p, "ParseIdent"))
|
defer un(trace(p, "ParseIdent"))
|
||||||
@ -117,14 +87,6 @@ func (p *Parser) parseLiteralType() (*LiteralType, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseObjectStatement parses an object statement returns an ObjectStatement
|
|
||||||
// AST. ObjectsStatements represents both normal and nested objects statement
|
|
||||||
func (p *Parser) parseObjectStatement() (*ObjectStatement, error) {
|
|
||||||
defer un(trace(p, "ParseObjectStatement"))
|
|
||||||
|
|
||||||
return nil, errors.New("ObjectStatement is not implemented yet")
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseObjectType parses an object type and returns a ObjectType AST
|
// parseObjectType parses an object type and returns a ObjectType AST
|
||||||
func (p *Parser) parseObjectType() (*ObjectType, error) {
|
func (p *Parser) parseObjectType() (*ObjectType, error) {
|
||||||
return nil, errors.New("ObjectType is not implemented yet")
|
return nil, errors.New("ObjectType is not implemented yet")
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package parser
|
package parser
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func TestAssignStatement(t *testing.T) {
|
func TestAssignStatement(t *testing.T) {
|
||||||
src := `ami = "${var.foo}"`
|
src := `ami = "${var.foo}"`
|
||||||
@ -14,4 +17,13 @@ func TestAssignStatement(t *testing.T) {
|
|||||||
if n.Pos().Line != 1 {
|
if n.Pos().Line != 1 {
|
||||||
t.Errorf("AssignStatement position is wrong\n\twant: '%d'\n\tgot : '%d'", 1, n.Pos().Line)
|
t.Errorf("AssignStatement position is wrong\n\twant: '%d'\n\tgot : '%d'", 1, n.Pos().Line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n1, ok := n.(*ObjectList)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("First Node should be of type Source")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ns := range n1.nodes {
|
||||||
|
fmt.Printf("ns = %+v\n", ns)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user