parser: add support for object type

This commit is contained in:
Fatih Arslan 2015-10-17 01:14:40 +03:00
parent 4e690ec67d
commit 16d5eb5f08
4 changed files with 43 additions and 17 deletions

View File

@ -88,11 +88,11 @@ func (l *ListType) Add(node Node) {
// ObjectType represents a HCL Object Type // ObjectType represents a HCL Object Type
type ObjectType struct { type ObjectType struct {
Lbrace token.Pos // position of "{" Lbrace token.Pos // position of "{"
Rbrace token.Pos // position of "}" Rbrace token.Pos // position of "}"
List []Node // the nodes in lexical order List *ObjectList // the nodes in lexical order
} }
func (b *ObjectType) Pos() token.Pos { func (o *ObjectType) Pos() token.Pos {
return b.Lbrace return o.Lbrace
} }

View File

@ -27,7 +27,7 @@ func Walk(node Node, fn func(Node) bool) {
Walk(l, fn) Walk(l, fn)
} }
case *ObjectType: case *ObjectType:
for _, l := range n.List { for _, l := range n.List.Items {
Walk(l, fn) Walk(l, fn)
} }
} }

View File

@ -30,6 +30,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() (ast.Node, error) { func (p *Parser) Parse() (ast.Node, error) {
return p.parseObjectList()
}
func (p *Parser) parseObjectList() (*ast.ObjectList, error) {
defer un(trace(p, "ParseObjectList")) defer un(trace(p, "ParseObjectList"))
node := &ast.ObjectList{} node := &ast.ObjectList{}
@ -75,11 +79,11 @@ func (p *Parser) parseObjectItem() (*ast.ObjectItem, error) {
case token.LBRACE: case token.LBRACE:
if len(keys) > 1 { if len(keys) > 1 {
// nested object // nested object
fmt.Println("nested object") panic("nested object is not implemented")
} }
// object // object
fmt.Println("object") panic("normal object is not implemented")
} }
return nil, fmt.Errorf("not yet implemented: %s", p.tok.Type) return nil, fmt.Errorf("not yet implemented: %s", p.tok.Type)
@ -154,10 +158,33 @@ func (p *Parser) parseObjectKey() ([]*ast.ObjectKey, error) {
} }
} }
// parseObjectType parses an object type and returns a ObjectType AST
func (p *Parser) parseObjectType() (*ast.ObjectType, error) {
defer un(trace(p, "ParseObjectType"))
// we assume that the currently scanned token is a LBRACE
o := &ast.ObjectType{
Lbrace: p.tok.Pos,
}
l, err := p.parseObjectList()
// if we hit RBRACE, we are good to go (means we parsed all Items), if it's
// not a RBRACE, it's an syntax error and we just return it.
if err != nil && p.tok.Type != token.RBRACE {
return nil, err
}
o.List = l
o.Rbrace = p.tok.Pos // advanced via parseObjectList
return o, nil
}
// parseListType parses a list type and returns a ListType AST // parseListType parses a list type and returns a ListType AST
func (p *Parser) parseListType() (*ast.ListType, error) { func (p *Parser) parseListType() (*ast.ListType, error) {
defer un(trace(p, "ParseListType")) defer un(trace(p, "ParseListType"))
// we assume that the currently scanned token is a LBRACK
l := &ast.ListType{ l := &ast.ListType{
Lbrack: p.tok.Pos, Lbrack: p.tok.Pos,
} }
@ -177,7 +204,9 @@ func (p *Parser) parseListType() (*ast.ListType, error) {
case token.BOOL: case token.BOOL:
// TODO(arslan) should we support? not supported by HCL yet // TODO(arslan) should we support? not supported by HCL yet
case token.LBRACK: case token.LBRACK:
// TODO(arslan) should we support nested lists? // TODO(arslan) should we support nested lists? Even though it's
// written in README of HCL, it's not a parse of the grammar
// (defined in parse.y)
case token.RBRACK: case token.RBRACK:
// finished // finished
l.Rbrack = p.tok.Pos l.Rbrack = p.tok.Pos
@ -198,13 +227,6 @@ func (p *Parser) parseLiteralType() (*ast.LiteralType, error) {
}, nil }, nil
} }
// parseObjectType parses an object type and returns a ObjectType AST
func (p *Parser) parseObjectType() (*ast.ObjectType, error) {
defer un(trace(p, "ParseObjectYpe"))
return nil, errors.New("ObjectType is not implemented yet")
}
// scan returns the next token from the underlying scanner. // scan returns the next token from the underlying scanner.
// If a token has been unscanned then read that instead. // If a token has been unscanned then read that instead.
func (p *Parser) scan() token.Token { func (p *Parser) scan() token.Token {

View File

@ -12,7 +12,11 @@ import (
) )
func TestParseType(t *testing.T) { func TestParseType(t *testing.T) {
src := `foo = ["fatih", "arslan", 1224]` src := `foo = {
fatih = "true"
arslan = "deneme"
}`
p := New([]byte(src)) p := New([]byte(src))
p.enableTrace = true p.enableTrace = true