summaryrefslogtreecommitdiff
path: root/parser/parser.go
diff options
context:
space:
mode:
Diffstat (limited to 'parser/parser.go')
-rw-r--r--parser/parser.go77
1 files changed, 74 insertions, 3 deletions
diff --git a/parser/parser.go b/parser/parser.go
index 5840f0a..936d58a 100644
--- a/parser/parser.go
+++ b/parser/parser.go
@@ -1,25 +1,38 @@
package parser
import (
+ "fmt"
+
"github.com/mewsen/interpreter/ast"
"github.com/mewsen/interpreter/lexer"
"github.com/mewsen/interpreter/token"
)
type Parser struct {
- l *lexer.Lexer
+ l *lexer.Lexer
+ errors []string
curToken token.Token
peekToken token.Token
}
+func (p *Parser) peekError(t token.TokenType) {
+ msg := fmt.Sprintf("expected next token to be %s, got %s instead",
+ t, p.peekToken.Type)
+ p.errors = append(p.errors, msg)
+}
+
func (p *Parser) NextToken() {
p.curToken = p.peekToken
p.peekToken = p.l.NextToken()
}
+func (p *Parser) Errors() []string {
+ return p.errors
+}
+
func New(l *lexer.Lexer) *Parser {
- p := &Parser{l: l}
+ p := &Parser{l: l, errors: []string{}}
p.NextToken()
p.NextToken()
@@ -28,5 +41,63 @@ func New(l *lexer.Lexer) *Parser {
}
func (p *Parser) ParseProgram() *ast.Program {
- return nil
+ program := &ast.Program{}
+ program.Statements = []ast.Statement{}
+
+ for p.curToken.Type != token.EOF {
+ stmt := p.parseStatement()
+ if stmt != nil {
+ program.Statements = append(program.Statements, stmt)
+ }
+ p.NextToken()
+ }
+
+ return program
+}
+
+func (p *Parser) parseStatement() ast.Statement {
+ switch p.curToken.Type {
+ case token.LET:
+ return p.parseLetStatement()
+ default:
+ return nil
+ }
+}
+
+func (p *Parser) parseLetStatement() *ast.LetStatement {
+ stmt := &ast.LetStatement{Token: p.curToken}
+
+ if !p.expectPeek(token.IDENT) {
+ return nil
+ }
+
+ stmt.Name = &ast.Identifier{Token: p.curToken, Value: p.curToken.Literal}
+
+ if !p.expectPeek(token.ASSIGN) {
+ return nil
+ }
+
+ // TODO: We're skipping the expressions until we encounter a semicolon
+ for !p.curTokenIs(token.SEMICOLON) {
+ p.NextToken()
+ }
+
+ return stmt
+}
+
+func (p *Parser) curTokenIs(t token.TokenType) bool {
+ return p.curToken.Type == t
+}
+
+func (p *Parser) peekTokenIs(t token.TokenType) bool {
+ return p.peekToken.Type == t
+}
+
+func (p *Parser) expectPeek(t token.TokenType) bool {
+ if p.peekTokenIs(t) {
+ p.NextToken()
+ return true
+ } else {
+ return false
+ }
}