parser: implement node interface methods
This commit is contained in:
parent
77c7bc18c5
commit
82c5032a95
@ -14,39 +14,88 @@ const (
|
|||||||
Object
|
Object
|
||||||
)
|
)
|
||||||
|
|
||||||
// Node is an element in the parse tree.
|
// Node is an element in the abstract syntax tree.
|
||||||
type Node interface {
|
type Node interface {
|
||||||
|
node()
|
||||||
String() string
|
String() string
|
||||||
Type() NodeType
|
|
||||||
Pos() scanner.Pos
|
Pos() scanner.Pos
|
||||||
End() scanner.Pos
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (IdentStatement) node() {}
|
||||||
|
func (BlockStatement) node() {}
|
||||||
|
func (AssignStatement) node() {}
|
||||||
|
func (ListStatement) node() {}
|
||||||
|
func (ObjectStatement) node() {}
|
||||||
|
|
||||||
// IdentStatement represents an identifier.
|
// IdentStatement represents an identifier.
|
||||||
type IdentStatement struct {
|
type IdentStatement struct {
|
||||||
Token scanner.Token
|
pos scanner.Pos // position of the literal
|
||||||
Pos scanner.Pos // position of the literal
|
token scanner.Token
|
||||||
Value string
|
value string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i IdentStatement) String() string {
|
||||||
|
return i.value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i IdentStatement) Pos() scanner.Pos {
|
||||||
|
return i.pos
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlockStatement struct {
|
type BlockStatement struct {
|
||||||
Lbrace scanner.Pos // position of "{"
|
lbrace scanner.Pos // position of "{"
|
||||||
Rbrace scanner.Pos // position of "}"
|
rbrace scanner.Pos // position of "}"
|
||||||
List []Node // the nodes in lexical order
|
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
|
||||||
Rhs Node // right hand side of the assignment
|
rhs Node // right hand side of the assignment
|
||||||
Assign scanner.Pos // position of "="
|
assign scanner.Pos // position of "="
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a AssignStatement) String() string {
|
||||||
|
return a.lhs.String() + " = " + a.rhs.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a AssignStatement) Pos() scanner.Pos {
|
||||||
|
return a.lhs.Pos()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListStatement represents a list
|
// ListStatement represents a list
|
||||||
type ListStatement struct {
|
type ListStatement struct {
|
||||||
Lbrack scanner.Pos // position of "["
|
lbrack scanner.Pos // position of "["
|
||||||
Rbrack scanner.Pos // position of "]"
|
rbrack scanner.Pos // position of "]"
|
||||||
List []Node // the elements in lexical order
|
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
|
||||||
@ -54,3 +103,21 @@ type ObjectStatement struct {
|
|||||||
Idents []Node // the idents in elements in lexical order
|
Idents []Node // the idents in elements in lexical order
|
||||||
BlockStatement
|
BlockStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o ObjectStatement) String() string {
|
||||||
|
s := ""
|
||||||
|
|
||||||
|
for i, n := range o.Idents {
|
||||||
|
s += n.String()
|
||||||
|
if i != len(o.Idents) {
|
||||||
|
s += " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s += o.BlockStatement.String()
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o ObjectStatement) Pos() scanner.Pos {
|
||||||
|
return o.Idents[0].Pos()
|
||||||
|
}
|
||||||
|
@ -3,14 +3,46 @@ 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
|
||||||
|
n int // buffer size (max = 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewParser(src []byte) *Parser {
|
func NewParser(src []byte) *Parser {
|
||||||
return &Parser{
|
return &Parser{
|
||||||
sc: scanner.NewScanner(src),
|
sc: scanner.New(src),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) Parse() {
|
func (p *Parser) Parse() Node {
|
||||||
|
tok := p.scan()
|
||||||
|
|
||||||
|
switch tok.Type() {
|
||||||
|
case scanner.IDENT:
|
||||||
|
// p.parseStatement()
|
||||||
|
case scanner.EOF:
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scan returns the next token from the underlying scanner.
|
||||||
|
// If a token has been unscanned then read that instead.
|
||||||
|
func (p *Parser) scan() scanner.Token {
|
||||||
|
// If we have a token on the buffer, then return it.
|
||||||
|
if p.buf.n != 0 {
|
||||||
|
p.buf.n = 0
|
||||||
|
return p.buf.tok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise read the next token from the scanner and Save it to the buffer
|
||||||
|
// in case we unscan later.
|
||||||
|
p.buf.tok = p.sc.Scan()
|
||||||
|
|
||||||
|
return p.buf.tok
|
||||||
|
}
|
||||||
|
|
||||||
|
// unscan pushes the previously read token back onto the buffer.
|
||||||
|
func (p *Parser) unread() { p.buf.n = 1 }
|
||||||
|
@ -42,15 +42,9 @@ type Scanner struct {
|
|||||||
tokPos Pos
|
tokPos Pos
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewScannerstring creates and initializes a new instance of Scanner using
|
// New creates and initializes a new instance of Scanner using src as
|
||||||
// string src as its source content.
|
|
||||||
func NewScannerString(src string) *Scanner {
|
|
||||||
return NewScanner([]byte(src))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewScanner creates and initializes a new instance of Scanner using src as
|
|
||||||
// its source content.
|
// its source content.
|
||||||
func NewScanner(src []byte) *Scanner {
|
func New(src []byte) *Scanner {
|
||||||
// even though we accept a src, we read from a io.Reader compatible type
|
// even though we accept a src, we read from a io.Reader compatible type
|
||||||
// (*bytes.Buffer). So in the future we might easily change it to streaming
|
// (*bytes.Buffer). So in the future we might easily change it to streaming
|
||||||
// read.
|
// read.
|
||||||
|
@ -182,7 +182,7 @@ func TestPosition(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s := NewScanner(buf.Bytes())
|
s := New(buf.Bytes())
|
||||||
|
|
||||||
pos := Pos{"", 4, 1, 5}
|
pos := Pos{"", 4, 1, 5}
|
||||||
s.Scan()
|
s.Scan()
|
||||||
@ -329,7 +329,7 @@ func TestRealExample(t *testing.T) {
|
|||||||
{EOF, ``},
|
{EOF, ``},
|
||||||
}
|
}
|
||||||
|
|
||||||
s := NewScanner([]byte(complexHCL))
|
s := New([]byte(complexHCL))
|
||||||
for _, l := range literals {
|
for _, l := range literals {
|
||||||
tok := s.Scan()
|
tok := s.Scan()
|
||||||
if l.token != tok.Type() {
|
if l.token != tok.Type() {
|
||||||
@ -366,7 +366,7 @@ func TestError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testError(t *testing.T, src, pos, msg string, tok TokenType) {
|
func testError(t *testing.T, src, pos, msg string, tok TokenType) {
|
||||||
s := NewScanner([]byte(src))
|
s := New([]byte(src))
|
||||||
|
|
||||||
errorCalled := false
|
errorCalled := false
|
||||||
s.Error = func(p Pos, m string) {
|
s.Error = func(p Pos, m string) {
|
||||||
@ -401,7 +401,7 @@ func testTokenList(t *testing.T, tokenList []tokenPair) {
|
|||||||
fmt.Fprintf(buf, "%s\n", ident.text)
|
fmt.Fprintf(buf, "%s\n", ident.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := NewScanner(buf.Bytes())
|
s := New(buf.Bytes())
|
||||||
for _, ident := range tokenList {
|
for _, ident := range tokenList {
|
||||||
tok := s.Scan()
|
tok := s.Scan()
|
||||||
if tok.Type() != ident.tok {
|
if tok.Type() != ident.tok {
|
||||||
|
Loading…
Reference in New Issue
Block a user