- 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
This commit is contained in:
parent
4a3edec5e6
commit
145d61ba57
@ -1,6 +1,7 @@
|
|||||||
package parser
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"monkey/ast"
|
"monkey/ast"
|
||||||
"monkey/lexer"
|
"monkey/lexer"
|
||||||
"monkey/token"
|
"monkey/token"
|
||||||
@ -10,10 +11,12 @@ type Parser struct {
|
|||||||
lexer *lexer.Lexer
|
lexer *lexer.Lexer
|
||||||
current_token token.Token
|
current_token token.Token
|
||||||
peek_token token.Token
|
peek_token token.Token
|
||||||
|
|
||||||
|
errors []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(l_lexer *lexer.Lexer) *Parser {
|
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
|
// Read two tokens so current_token and peek_token are both set
|
||||||
l_parser.next_token()
|
l_parser.next_token()
|
||||||
@ -22,6 +25,10 @@ func New(l_lexer *lexer.Lexer) *Parser {
|
|||||||
return l_parser
|
return l_parser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l_parser *Parser) Errors() []string {
|
||||||
|
return l_parser.errors
|
||||||
|
}
|
||||||
|
|
||||||
func (l_parser *Parser) ParseProgram() *ast.Program {
|
func (l_parser *Parser) ParseProgram() *ast.Program {
|
||||||
program := &ast.Program{}
|
program := &ast.Program{}
|
||||||
program.Statements = []ast.Statement{}
|
program.Statements = []ast.Statement{}
|
||||||
@ -68,6 +75,21 @@ func (l_parser *Parser) parse_let_statement() *ast.LetStatement {
|
|||||||
return statement
|
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 {
|
func (l_parser *Parser) current_token_is(l_token token.TokenType) bool {
|
||||||
return l_parser.current_token.Type == l_token
|
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 {
|
func (l_parser *Parser) peek_token_is(l_token token.TokenType) bool {
|
||||||
return l_parser.peek_token.Type == l_token
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -17,6 +17,8 @@ func TestLetStatement(l_test *testing.T) {
|
|||||||
l_parser := New(l_lexer)
|
l_parser := New(l_lexer)
|
||||||
|
|
||||||
program := l_parser.ParseProgram()
|
program := l_parser.ParseProgram()
|
||||||
|
check_parser_errors(l_test, l_parser)
|
||||||
|
|
||||||
if program == nil {
|
if program == nil {
|
||||||
l_test.Fatalf("ParseProgram() returned 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
|
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()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user