From 99099cda627165f1e22d318c63978275d68e85c3 Mon Sep 17 00:00:00 2001 From: Fatih Arslan Date: Mon, 12 Oct 2015 01:38:59 +0300 Subject: [PATCH] parser: implement parsing assignments, stil wip --- parser/ast.go | 32 +++++++++++++++++---- parser/parser.go | 75 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 89 insertions(+), 18 deletions(-) diff --git a/parser/ast.go b/parser/ast.go index 76c5db3..70c7dc6 100644 --- a/parser/ast.go +++ b/parser/ast.go @@ -14,32 +14,54 @@ const ( Object ) -// Node is an element in the abstract syntax tree. +// Node is an element in the abstract syntax tree. type Node interface { node() String() string Pos() scanner.Pos } +func (Source) node() {} func (IdentStatement) node() {} func (BlockStatement) node() {} func (AssignStatement) node() {} func (ListStatement) 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. type IdentStatement struct { - pos scanner.Pos // position of the literal token scanner.Token - value string } func (i IdentStatement) String() string { - return i.value + return i.token.String() } func (i IdentStatement) Pos() scanner.Pos { - return i.pos + return i.token.Pos() } type BlockStatement struct { diff --git a/parser/parser.go b/parser/parser.go index a3513f6..695cee6 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -3,11 +3,12 @@ package parser import "github.com/fatih/hcl/scanner" type Parser struct { - sc *scanner.Scanner - buf struct { - tok scanner.Token // last read token - n int // buffer size (max = 1) - } + sc *scanner.Scanner + + tok scanner.Token // last read token + prevTok scanner.Token // previous read token + + n int // buffer size (max = 1) } 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 { tok := p.scan() + node := Source{} + switch tok.Type() { case scanner.IDENT: - // p.parseStatement() + n := p.parseStatement() + node.add(n) 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 } +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. // 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 + if p.n != 0 { + p.n = 0 + return p.tok } + // store previous token + p.prevTok = p.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 + p.tok = p.sc.Scan() + return p.tok } // 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 }