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