|
@@ -1,12 +1,14 @@
|
|
|
package parser
|
|
|
|
|
|
import (
|
|
|
+ "fmt"
|
|
|
+
|
|
|
"code.osinet.fr/fgm/waiig15/ast"
|
|
|
"code.osinet.fr/fgm/waiig15/lexer"
|
|
|
"code.osinet.fr/fgm/waiig15/token"
|
|
|
- "fmt"
|
|
|
)
|
|
|
|
|
|
+// Parser implements the parsing mechanism top-level layer.
|
|
|
type Parser struct {
|
|
|
errors []string
|
|
|
l *lexer.Lexer
|
|
@@ -15,6 +17,8 @@ type Parser struct {
|
|
|
peekToken token.Token
|
|
|
}
|
|
|
|
|
|
+// New returns a new Parser instance with the first two parser tokens already
|
|
|
+// loaded.
|
|
|
func New(l *lexer.Lexer) *Parser {
|
|
|
p := &Parser{
|
|
|
l: l,
|
|
@@ -28,10 +32,13 @@ func New(l *lexer.Lexer) *Parser {
|
|
|
return p
|
|
|
}
|
|
|
|
|
|
+// Errors is a getter for Parser.errors.
|
|
|
func (p *Parser) Errors() []string {
|
|
|
return p.errors
|
|
|
}
|
|
|
|
|
|
+// ParseProgram is the outermost parsing logic, accumulating statements in a
|
|
|
+// Program instance and returning that instance once parsing is done.
|
|
|
func (p *Parser) ParseProgram() *ast.Program {
|
|
|
program := &ast.Program{
|
|
|
Statements: []ast.Statement{},
|
|
@@ -58,10 +65,10 @@ func (p *Parser) expectPeek(t token.TokenType) bool {
|
|
|
if p.peekTokenIs(t) {
|
|
|
p.nextToken()
|
|
|
return true
|
|
|
- } else {
|
|
|
- p.peekError(t)
|
|
|
- return false
|
|
|
}
|
|
|
+
|
|
|
+ p.peekError(t)
|
|
|
+ return false
|
|
|
}
|
|
|
|
|
|
func (p *Parser) nextToken() {
|
|
@@ -69,41 +76,12 @@ func (p *Parser) nextToken() {
|
|
|
p.peekToken = p.l.NextToken()
|
|
|
}
|
|
|
|
|
|
-func (p *Parser) parseLetStatement() *ast.LetStatement {
|
|
|
- stmt := &ast.LetStatement{
|
|
|
- Token: p.curToken,
|
|
|
- }
|
|
|
-
|
|
|
- // Let statement starts with an IDENT token, so if next token is not an
|
|
|
- // IDENT, the next statement cannot be a Let statement.
|
|
|
- if !p.expectPeek(token.IDENT) {
|
|
|
- return nil
|
|
|
- }
|
|
|
-
|
|
|
- stmt.Name = &ast.Identifier{
|
|
|
- Token: p.curToken,
|
|
|
- Value: p.curToken.Literal,
|
|
|
- }
|
|
|
-
|
|
|
- // The previous expectPeek() call fetched the next token, so we should now
|
|
|
- // be on the assignment.
|
|
|
- if !p.expectPeek(token.ASSIGN) {
|
|
|
- return nil
|
|
|
- }
|
|
|
-
|
|
|
- // Skip the expression for now, progress to the semicolon terminating the
|
|
|
- // statement.
|
|
|
- for !p.curTokenIs(token.SEMICOLON) {
|
|
|
- p.nextToken()
|
|
|
- }
|
|
|
-
|
|
|
- return stmt
|
|
|
-}
|
|
|
-
|
|
|
func (p *Parser) parseStatement() ast.Statement {
|
|
|
switch p.curToken.Type {
|
|
|
case token.LET:
|
|
|
return p.parseLetStatement()
|
|
|
+ case token.RETURN:
|
|
|
+ return p.parseReturnStatement()
|
|
|
default:
|
|
|
return nil
|
|
|
}
|
|
@@ -122,4 +100,3 @@ func (p *Parser) peekError(t token.TokenType) {
|
|
|
func (p *Parser) peekTokenIs(t token.TokenType) bool {
|
|
|
return p.peekToken.Type == t
|
|
|
}
|
|
|
-
|