|
@@ -4,17 +4,22 @@ import (
|
|
|
"code.osinet.fr/fgm/waiig15/ast"
|
|
|
"code.osinet.fr/fgm/waiig15/lexer"
|
|
|
"code.osinet.fr/fgm/waiig15/token"
|
|
|
+ "fmt"
|
|
|
)
|
|
|
|
|
|
type Parser struct {
|
|
|
- l *lexer.Lexer
|
|
|
+ errors []string
|
|
|
+ l *lexer.Lexer
|
|
|
|
|
|
curToken token.Token
|
|
|
peekToken token.Token
|
|
|
}
|
|
|
|
|
|
func New(l *lexer.Lexer) *Parser {
|
|
|
- p := &Parser{l: l}
|
|
|
+ p := &Parser{
|
|
|
+ l: l,
|
|
|
+ errors: []string{},
|
|
|
+ }
|
|
|
|
|
|
// Read two tokens, so curToken and peeToken are both set.
|
|
|
p.nextToken()
|
|
@@ -23,9 +28,8 @@ func New(l *lexer.Lexer) *Parser {
|
|
|
return p
|
|
|
}
|
|
|
|
|
|
-func (p *Parser) nextToken() {
|
|
|
- p.curToken = p.peekToken
|
|
|
- p.peekToken = p.l.NextToken()
|
|
|
+func (p *Parser) Errors() []string {
|
|
|
+ return p.errors
|
|
|
}
|
|
|
|
|
|
func (p *Parser) ParseProgram() *ast.Program {
|
|
@@ -43,15 +47,28 @@ func (p *Parser) ParseProgram() *ast.Program {
|
|
|
return program
|
|
|
}
|
|
|
|
|
|
-func (p *Parser) parseStatement() ast.Statement {
|
|
|
- switch p.curToken.Type {
|
|
|
- case token.LET:
|
|
|
- return p.parseLetStatement()
|
|
|
- default:
|
|
|
- return nil
|
|
|
+// Is the current token in the parser of the given type ?
|
|
|
+func (p *Parser) curTokenIs(t token.TokenType) bool {
|
|
|
+ return p.curToken.Type == t
|
|
|
+}
|
|
|
+
|
|
|
+// Is the next token in the parser of the given type ? If it is, consume it,
|
|
|
+// else don't.
|
|
|
+func (p *Parser) expectPeek(t token.TokenType) bool {
|
|
|
+ if p.peekTokenIs(t) {
|
|
|
+ p.nextToken()
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ p.peekError(t)
|
|
|
+ return false
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func (p *Parser) nextToken() {
|
|
|
+ p.curToken = p.peekToken
|
|
|
+ p.peekToken = p.l.NextToken()
|
|
|
+}
|
|
|
+
|
|
|
func (p *Parser) parseLetStatement() *ast.LetStatement {
|
|
|
stmt := &ast.LetStatement{
|
|
|
Token: p.curToken,
|
|
@@ -83,9 +100,22 @@ func (p *Parser) parseLetStatement() *ast.LetStatement {
|
|
|
return stmt
|
|
|
}
|
|
|
|
|
|
-// Is the current token in the parser of the given type ?
|
|
|
-func (p *Parser) curTokenIs(t token.TokenType) bool {
|
|
|
- return p.curToken.Type == t
|
|
|
+func (p *Parser) parseStatement() ast.Statement {
|
|
|
+ switch p.curToken.Type {
|
|
|
+ case token.LET:
|
|
|
+ return p.parseLetStatement()
|
|
|
+ default:
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Log a mismatch error on the peek token type in the parser instance.
|
|
|
+//
|
|
|
+// - t is the type of token that was expected
|
|
|
+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)
|
|
|
}
|
|
|
|
|
|
// Is the next token in the parser of the given type ? Don't consume it.
|
|
@@ -93,13 +123,3 @@ func (p *Parser) peekTokenIs(t token.TokenType) bool {
|
|
|
return p.peekToken.Type == t
|
|
|
}
|
|
|
|
|
|
-// Is the next token in the parser of the given type ? If it is, consume it,
|
|
|
-// else don't.
|
|
|
-func (p *Parser) expectPeek(t token.TokenType) bool {
|
|
|
- if p.peekTokenIs(t) {
|
|
|
- p.nextToken()
|
|
|
- return true
|
|
|
- } else {
|
|
|
- return false
|
|
|
- }
|
|
|
-}
|