parser: implement parsing assignments, stil wip

This commit is contained in:
Fatih Arslan 2015-10-12 01:38:59 +03:00
parent 82c5032a95
commit 99099cda62
2 changed files with 89 additions and 18 deletions

View File

@ -14,32 +14,54 @@ const (
Object Object
) )
// Node is an element in the abstract syntax tree. // Node is an element in the abstract syntax tree.
type Node interface { type Node interface {
node() node()
String() string String() string
Pos() scanner.Pos Pos() scanner.Pos
} }
func (Source) node() {}
func (IdentStatement) node() {} func (IdentStatement) node() {}
func (BlockStatement) node() {} func (BlockStatement) node() {}
func (AssignStatement) node() {} func (AssignStatement) node() {}
func (ListStatement) node() {} func (ListStatement) node() {}
func (ObjectStatement) node() {} func (ObjectStatement) node() {}
// Source represents a single HCL source file
type Source struct {
nodes []Node
}
func (s Source) add(node Node) {
s.nodes = append(s.nodes, node)
}
func (s Source) String() string {
buf := ""
for _, n := range s.nodes {
buf += n.String()
}
return buf
}
func (s Source) Pos() scanner.Pos {
// always returns the uninitiliazed position
return scanner.Pos{}
}
// IdentStatement represents an identifier. // IdentStatement represents an identifier.
type IdentStatement struct { type IdentStatement struct {
pos scanner.Pos // position of the literal
token scanner.Token token scanner.Token
value string
} }
func (i IdentStatement) String() string { func (i IdentStatement) String() string {
return i.value return i.token.String()
} }
func (i IdentStatement) Pos() scanner.Pos { func (i IdentStatement) Pos() scanner.Pos {
return i.pos return i.token.Pos()
} }
type BlockStatement struct { type BlockStatement struct {

View File

@ -3,11 +3,12 @@ package parser
import "github.com/fatih/hcl/scanner" import "github.com/fatih/hcl/scanner"
type Parser struct { type Parser struct {
sc *scanner.Scanner sc *scanner.Scanner
buf struct {
tok scanner.Token // last read token tok scanner.Token // last read token
n int // buffer size (max = 1) prevTok scanner.Token // previous read token
}
n int // buffer size (max = 1)
} }
func NewParser(src []byte) *Parser { func NewParser(src []byte) *Parser {
@ -16,33 +17,81 @@ func NewParser(src []byte) *Parser {
} }
} }
// Parse returns the fully parsed source and returns the abstract syntax tree.
func (p *Parser) Parse() Node { func (p *Parser) Parse() Node {
tok := p.scan() tok := p.scan()
node := Source{}
switch tok.Type() { switch tok.Type() {
case scanner.IDENT: case scanner.IDENT:
// p.parseStatement() n := p.parseStatement()
node.add(n)
case scanner.EOF: case scanner.EOF:
} }
return node
}
func (p *Parser) parseStatement() Node {
tok := p.scan()
if tok.Type().IsLiteral() {
return p.parseIdent()
}
switch tok.Type() {
case scanner.LBRACE:
return p.parseObject()
case scanner.LBRACK:
return p.parseList()
case scanner.ASSIGN:
return p.parseAssignment()
}
return nil return nil
} }
func (p *Parser) parseIdent() Node {
return IdentStatement{
token: p.tok,
}
}
func (p *Parser) parseObject() Node {
return nil
}
func (p *Parser) parseList() Node {
return nil
}
func (p *Parser) parseAssignment() Node {
return AssignStatement{
lhs: IdentStatement{
token: p.prevTok,
},
assign: p.tok.Pos(),
rhs: p.parseStatement(),
}
}
// 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() scanner.Token { func (p *Parser) scan() scanner.Token {
// If we have a token on the buffer, then return it. // If we have a token on the buffer, then return it.
if p.buf.n != 0 { if p.n != 0 {
p.buf.n = 0 p.n = 0
return p.buf.tok return p.tok
} }
// store previous token
p.prevTok = p.tok
// Otherwise read the next token from the scanner and Save it to the buffer // Otherwise read the next token from the scanner and Save it to the buffer
// in case we unscan later. // in case we unscan later.
p.buf.tok = p.sc.Scan() p.tok = p.sc.Scan()
return p.tok
return p.buf.tok
} }
// unscan pushes the previously read token back onto the buffer. // unscan pushes the previously read token back onto the buffer.
func (p *Parser) unread() { p.buf.n = 1 } func (p *Parser) unscan() { p.n = 1 }