parser: imrprovements to AST types
This commit is contained in:
parent
0a3fe0e81e
commit
8d60ae5dc5
116
parser/ast.go
116
parser/ast.go
@ -21,13 +21,16 @@ type Node interface {
|
||||
Pos() scanner.Pos
|
||||
}
|
||||
|
||||
func (Source) node() {}
|
||||
func (Ident) node() {}
|
||||
func (BlockStatement) node() {}
|
||||
func (Source) node() {}
|
||||
func (Ident) node() {}
|
||||
|
||||
func (AssignStatement) node() {}
|
||||
func (ListStatement) node() {}
|
||||
func (ObjectStatement) node() {}
|
||||
|
||||
func (LiteralType) node() {}
|
||||
func (ObjectType) node() {}
|
||||
func (ListType) node() {}
|
||||
|
||||
// Source represents a single HCL source file
|
||||
type Source struct {
|
||||
nodes []Node
|
||||
@ -57,33 +60,13 @@ type Ident struct {
|
||||
}
|
||||
|
||||
func (i *Ident) String() string {
|
||||
return i.token.String()
|
||||
return i.token.Text
|
||||
}
|
||||
|
||||
func (i *Ident) Pos() scanner.Pos {
|
||||
return i.token.Pos
|
||||
}
|
||||
|
||||
type BlockStatement struct {
|
||||
lbrace scanner.Pos // position of "{"
|
||||
rbrace scanner.Pos // position of "}"
|
||||
list []Node // the nodes in lexical order
|
||||
}
|
||||
|
||||
func (b *BlockStatement) String() string {
|
||||
s := "{\n"
|
||||
for _, n := range b.list {
|
||||
s += n.String() + "\n"
|
||||
}
|
||||
|
||||
s += "}"
|
||||
return s
|
||||
}
|
||||
|
||||
func (b *BlockStatement) Pos() scanner.Pos {
|
||||
return b.lbrace
|
||||
}
|
||||
|
||||
// AssignStatement represents an assignment
|
||||
type AssignStatement struct {
|
||||
lhs Node // left hand side of the assignment
|
||||
@ -99,31 +82,10 @@ func (a *AssignStatement) Pos() scanner.Pos {
|
||||
return a.lhs.Pos()
|
||||
}
|
||||
|
||||
// ListStatement represents a list
|
||||
type ListStatement struct {
|
||||
lbrack scanner.Pos // position of "["
|
||||
rbrack scanner.Pos // position of "]"
|
||||
list []Node // the elements in lexical order
|
||||
}
|
||||
|
||||
func (l *ListStatement) String() string {
|
||||
s := "[\n"
|
||||
for _, n := range l.list {
|
||||
s += n.String() + ",\n"
|
||||
}
|
||||
|
||||
s += "]"
|
||||
return s
|
||||
}
|
||||
|
||||
func (l *ListStatement) Pos() scanner.Pos {
|
||||
return l.lbrack
|
||||
}
|
||||
|
||||
// ObjectStatment represents an object
|
||||
// ObjectStatment represents an object statement
|
||||
type ObjectStatement struct {
|
||||
Idents []Node // the idents in elements in lexical order
|
||||
BlockStatement
|
||||
ObjectType
|
||||
}
|
||||
|
||||
func (o *ObjectStatement) String() string {
|
||||
@ -136,10 +98,66 @@ func (o *ObjectStatement) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
s += o.BlockStatement.String()
|
||||
s += o.ObjectType.String()
|
||||
return s
|
||||
}
|
||||
|
||||
func (o *ObjectStatement) Pos() scanner.Pos {
|
||||
return o.Idents[0].Pos()
|
||||
}
|
||||
|
||||
// LiteralType represents a literal of basic type. Valid types are:
|
||||
// scanner.NUMBER, scanner.FLOAT, scanner.BOOL and scanner.STRING
|
||||
type LiteralType struct {
|
||||
token scanner.Token
|
||||
}
|
||||
|
||||
func (l *LiteralType) String() string {
|
||||
return l.token.Text
|
||||
}
|
||||
|
||||
func (l *LiteralType) Pos() scanner.Pos {
|
||||
return l.token.Pos
|
||||
}
|
||||
|
||||
// ListStatement represents a HCL List type
|
||||
type ListType struct {
|
||||
lbrack scanner.Pos // position of "["
|
||||
rbrack scanner.Pos // position of "]"
|
||||
list []Node // the elements in lexical order
|
||||
}
|
||||
|
||||
func (l *ListType) String() string {
|
||||
s := "[\n"
|
||||
for _, n := range l.list {
|
||||
s += n.String() + ",\n"
|
||||
}
|
||||
|
||||
s += "]"
|
||||
return s
|
||||
}
|
||||
|
||||
func (l *ListType) Pos() scanner.Pos {
|
||||
return l.lbrack
|
||||
}
|
||||
|
||||
// ObjectType represents a HCL Object Type
|
||||
type ObjectType struct {
|
||||
lbrace scanner.Pos // position of "{"
|
||||
rbrace scanner.Pos // position of "}"
|
||||
list []Node // the nodes in lexical order
|
||||
}
|
||||
|
||||
func (b *ObjectType) String() string {
|
||||
s := "{\n"
|
||||
for _, n := range b.list {
|
||||
s += n.String() + "\n"
|
||||
}
|
||||
|
||||
s += "}"
|
||||
return s
|
||||
}
|
||||
|
||||
func (b *ObjectType) Pos() scanner.Pos {
|
||||
return b.lbrace
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/fatih/hcl/scanner"
|
||||
@ -29,10 +30,13 @@ func (p *Parser) Parse() (Node, error) {
|
||||
node := &Source{}
|
||||
|
||||
for {
|
||||
if n := p.parseStatement(); n != nil {
|
||||
node.add(n)
|
||||
n, err := p.parseNode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
node.add(n)
|
||||
|
||||
// break if we hit the end
|
||||
if p.tok.Type == scanner.EOF {
|
||||
break
|
||||
@ -42,17 +46,20 @@ func (p *Parser) Parse() (Node, error) {
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseStatement() Node {
|
||||
defer un(trace(p, "ParseStatement"))
|
||||
func (p *Parser) parseNode() (Node, error) {
|
||||
defer un(trace(p, "ParseNode"))
|
||||
|
||||
tok := p.scan()
|
||||
|
||||
fmt.Println(tok) // debug
|
||||
|
||||
if tok.Type.IsLiteral() {
|
||||
if p.prevTok.Type.IsLiteral() {
|
||||
return p.parseObject()
|
||||
return p.parseObjectType()
|
||||
}
|
||||
|
||||
if tok := p.scan(); tok.Type == scanner.ASSIGN {
|
||||
tok := p.scan()
|
||||
if tok.Type == scanner.ASSIGN {
|
||||
return p.parseAssignment()
|
||||
}
|
||||
|
||||
@ -60,34 +67,45 @@ func (p *Parser) parseStatement() Node {
|
||||
return p.parseIdent()
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil, errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
func (p *Parser) parseAssignment() Node {
|
||||
func (p *Parser) parseAssignment() (*AssignStatement, error) {
|
||||
defer un(trace(p, "ParseAssignment"))
|
||||
return &AssignStatement{
|
||||
a := &AssignStatement{
|
||||
lhs: &Ident{
|
||||
token: p.prevTok,
|
||||
},
|
||||
assign: p.tok.Pos,
|
||||
rhs: p.parseStatement(),
|
||||
}
|
||||
|
||||
n, err := p.parseNode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
a.rhs = n
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseIdent() Node {
|
||||
func (p *Parser) parseIdent() (*Ident, error) {
|
||||
defer un(trace(p, "ParseIdent"))
|
||||
|
||||
if !p.tok.Type.IsLiteral() {
|
||||
return nil, errors.New("can't parse non literal token")
|
||||
}
|
||||
|
||||
return &Ident{
|
||||
token: p.tok,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseObject() Node {
|
||||
return nil
|
||||
func (p *Parser) parseObjectType() (*ObjectStatement, error) {
|
||||
return nil, errors.New("ObjectStatement is not implemented yet")
|
||||
}
|
||||
|
||||
func (p *Parser) parseList() Node {
|
||||
return nil
|
||||
func (p *Parser) parseListType() (*ListType, error) {
|
||||
return nil, errors.New("ListStatement is not implemented yet")
|
||||
}
|
||||
|
||||
// scan returns the next token from the underlying scanner.
|
||||
|
@ -2,7 +2,7 @@ package parser
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestAssignStatment(t *testing.T) {
|
||||
func TestAssignStatement(t *testing.T) {
|
||||
src := `ami = "${var.foo}"`
|
||||
p := New([]byte(src))
|
||||
p.enableTrace = true
|
||||
|
@ -1,6 +1,9 @@
|
||||
package scanner
|
||||
|
||||
import "strconv"
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Token defines a single HCL token which can be obtained via the Scanner
|
||||
type Token struct {
|
||||
@ -90,5 +93,5 @@ func (t TokenType) IsOperator() bool { return operator_beg < t && t < operator_e
|
||||
// applicable for certain token types, such as token.IDENT,
|
||||
// token.STRING, etc..
|
||||
func (t Token) String() string {
|
||||
return t.Text
|
||||
return fmt.Sprintf("%s %s %s", t.Pos.String(), t.Type.String(), t.Text)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user