From 145d61ba57bad9b2160eaa2e168ff1d232d778e7 Mon Sep 17 00:00:00 2001 From: tijani Date: Thu, 26 May 2022 19:23:01 +0000 Subject: [PATCH] - The parser can now check for errors. - The test now handles checking for errors. git-svn-id: https://svn.tlawal.org/svn/monkey@19 f6afcba9-9ef1-4bdd-9b72-7484f5705bac --- parser/parser.go | 33 +++++++++++++++++++++++---------- parser/parser_test.go | 16 ++++++++++++++++ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index a5cce03..63f8fea 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1,6 +1,7 @@ package parser import ( + "fmt" "monkey/ast" "monkey/lexer" "monkey/token" @@ -10,10 +11,12 @@ type Parser struct { lexer *lexer.Lexer current_token token.Token peek_token token.Token + + errors []string } func New(l_lexer *lexer.Lexer) *Parser { - l_parser := &Parser{lexer: l_lexer} + l_parser := &Parser{lexer: l_lexer, errors: []string{}} // Read two tokens so current_token and peek_token are both set l_parser.next_token() @@ -22,6 +25,10 @@ func New(l_lexer *lexer.Lexer) *Parser { return l_parser } +func (l_parser *Parser) Errors() []string { + return l_parser.errors +} + func (l_parser *Parser) ParseProgram() *ast.Program { program := &ast.Program{} program.Statements = []ast.Statement{} @@ -68,6 +75,21 @@ func (l_parser *Parser) parse_let_statement() *ast.LetStatement { return statement } +func (l_parser *Parser) expect_peek(l_token token.TokenType) bool { + if l_parser.peek_token_is(l_token) { + l_parser.next_token() + return true + } else { + l_parser.peek_error(l_token) + return false + } +} + +func (l_parser *Parser) peek_error(l_token token.TokenType) { + message := fmt.Sprintf("expected next token to be %s, got %s", l_token, l_parser.peek_token.Type) + l_parser.errors = append(l_parser.errors, message) +} + func (l_parser *Parser) current_token_is(l_token token.TokenType) bool { return l_parser.current_token.Type == l_token } @@ -75,12 +97,3 @@ func (l_parser *Parser) current_token_is(l_token token.TokenType) bool { func (l_parser *Parser) peek_token_is(l_token token.TokenType) bool { return l_parser.peek_token.Type == l_token } - -func (l_parser *Parser) expect_peek(l_token token.TokenType) bool { - if l_parser.peek_token_is(l_token) { - l_parser.next_token() - return true - } else { - return false - } -} diff --git a/parser/parser_test.go b/parser/parser_test.go index aa7fd03..5cbc3de 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -17,6 +17,8 @@ func TestLetStatement(l_test *testing.T) { l_parser := New(l_lexer) program := l_parser.ParseProgram() + check_parser_errors(l_test, l_parser) + if program == nil { l_test.Fatalf("ParseProgram() returned nil") } @@ -65,3 +67,17 @@ func testLetStatement(l_test *testing.T, statement ast.Statement, name string) b } return true } + +func check_parser_errors(l_test *testing.T, l_parser *Parser) { + errors := l_parser.Errors() + if len(errors) == 0 { + return + } + + l_test.Errorf("parser has %d errors", len(errors)) + + for _, message := range errors { + l_test.Errorf("parser error: %q", message) + } + l_test.FailNow() +}