diff --git a/parser/ast.go b/parser/ast.go new file mode 100644 index 0000000..ce0cba7 --- /dev/null +++ b/parser/ast.go @@ -0,0 +1,56 @@ +package parser + +import "github.com/fatih/hcl/scanner" + +type NodeType int + +const ( + Unknown NodeType = 0 + Number + Float + Bool + String + List + Object +) + +// Node is an element in the parse tree. +type Node interface { + String() string + Type() NodeType + Start() scanner.Pos + End() scanner.Pos +} + +// IdentStatement represents an identifier. +type IdentStatement struct { + Token scanner.Token + Pos scanner.Pos // position of the literal + Value string +} + +type BlockStatement struct { + Lbrace scanner.Pos // position of "{" + Rbrace scanner.Pos // position of "}" + List []Node // the nodes in lexical order +} + +// AssignStatement represents an assignment +type AssignStatement struct { + Lhs Node // left hand side of the assignment + Rhs Node // right hand side of the assignment + Assign scanner.Pos // position of "=" +} + +// ListStatement represents a list +type ListStatement struct { + Lbrack scanner.Pos // position of "[" + Rbrack scanner.Pos // position of "]" + List []Node // the elements in lexical order +} + +// ObjectStatment represents an object +type ObjectStatement struct { + Idents []Node // the idents in elements in lexical order + BlockStatement +} diff --git a/parser/parser.go b/parser/parser.go index 0bfe2c2..46a1729 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1 +1,16 @@ package parser + +import "github.com/fatih/hcl/scanner" + +type Parser struct { + sc *scanner.Scanner +} + +func NewParser(src []byte) *Parser { + return &Parser{ + sc: scanner.NewScanner(src), + } +} + +func (p *Parser) Parse() { +} diff --git a/scanner/position.go b/scanner/position.go index 8ba9195..aef546c 100644 --- a/scanner/position.go +++ b/scanner/position.go @@ -2,10 +2,10 @@ package scanner import "fmt" -// Position describes an arbitrary source position +// Pos describes an arbitrary source position // including the file, line, and column location. // A Position is valid if the line number is > 0. -type Position struct { +type Pos struct { Filename string // filename, if any Offset int // offset, starting at 0 Line int // line number, starting at 1 @@ -13,7 +13,7 @@ type Position struct { } // IsValid returns true if the position is valid. -func (p *Position) IsValid() bool { return p.Line > 0 } +func (p *Pos) IsValid() bool { return p.Line > 0 } // String returns a string in one of several forms: // @@ -21,7 +21,7 @@ func (p *Position) IsValid() bool { return p.Line > 0 } // line:column valid position without file name // file invalid position with file name // - invalid position without file name -func (p Position) String() string { +func (p Pos) String() string { s := p.Filename if p.IsValid() { if s != "" { diff --git a/scanner/scanner.go b/scanner/scanner.go index 41f5b21..ebf91db 100644 --- a/scanner/scanner.go +++ b/scanner/scanner.go @@ -19,8 +19,8 @@ type Scanner struct { src []byte // Source buffer for immutable access // Source Position - srcPos Position // current position - prevPos Position // previous position, used for peek() method + srcPos Pos // current position + prevPos Pos // previous position, used for peek() method lastCharLen int // length of last character in bytes lastLineLen int // length of last line in characters (for correct column reporting) @@ -30,7 +30,7 @@ type Scanner struct { // Error is called for each error encountered. If no Error // function is set, the error is reported to os.Stderr. - Error func(pos Position, msg string) + Error func(pos Pos, msg string) // ErrorCount is incremented by one for each error encountered. ErrorCount int @@ -39,7 +39,7 @@ type Scanner struct { // Scan. The Filename field is always left untouched by the Scanner. If // an error is reported (via Error) and Position is invalid, the scanner is // not inside a token. - tokPos Position + tokPos Pos } // NewScannerstring creates and initializes a new instance of Scanner using @@ -449,7 +449,7 @@ func (s *Scanner) scanIdentifier() string { // recentPosition returns the position of the character immediately after the // character or token returned by the last call to Scan. -func (s *Scanner) recentPosition() (pos Position) { +func (s *Scanner) recentPosition() (pos Pos) { pos.Offset = s.srcPos.Offset - s.lastCharLen switch { case s.srcPos.Column > 0: diff --git a/scanner/scanner_test.go b/scanner/scanner_test.go index aa27d58..47b91e1 100644 --- a/scanner/scanner_test.go +++ b/scanner/scanner_test.go @@ -184,7 +184,7 @@ func TestPosition(t *testing.T) { s := NewScanner(buf.Bytes()) - pos := Position{"", 4, 1, 5} + pos := Pos{"", 4, 1, 5} s.Scan() for _, listName := range orderedTokenLists { @@ -369,7 +369,7 @@ func testError(t *testing.T, src, pos, msg string, tok TokenType) { s := NewScanner([]byte(src)) errorCalled := false - s.Error = func(p Position, m string) { + s.Error = func(p Pos, m string) { if !errorCalled { if pos != p.String() { t.Errorf("pos = %q, want %q for %q", p, pos, src) diff --git a/scanner/token.go b/scanner/token.go index f6f473d..1891130 100644 --- a/scanner/token.go +++ b/scanner/token.go @@ -5,7 +5,7 @@ import "strconv" // Token defines a single HCL token which can be obtained via the Scanner type Token struct { token TokenType - pos Position + pos Pos text string } @@ -92,7 +92,7 @@ func (t Token) Type() TokenType { } // Pos returns the token's position -func (t Token) Pos() Position { +func (t Token) Pos() Pos { return t.pos }