parser: add initial AST definitions
This commit is contained in:
parent
c62cc48b92
commit
8e99146570
56
parser/ast.go
Normal file
56
parser/ast.go
Normal file
@ -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
|
||||
}
|
@ -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() {
|
||||
}
|
||||
|
@ -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 != "" {
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user