diff options
| -rw-r--r-- | parser/parser.go | 77 |
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 + } } |
