commit 800aaef02c811fab39454b02cdb7589b45c61e66
parent e4e1fdf1534021f113946a65701fdba78d1be9d9
Author: bsandro <email@bsandro.tech>
Date: Mon, 13 Jun 2022 03:04:39 +0300
Parsing return statements (initial stuff)
Diffstat:
3 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/ast/ast.go b/ast/ast.go
@@ -39,6 +39,16 @@ func (l *LetStatement) TokenLiteral() string {
return l.Token.Literal
}
+type ReturnStatement struct {
+ Token token.Token
+ ReturnValue Expression
+}
+
+func (rs *ReturnStatement) statementNode() {}
+func (rs *ReturnStatement) TokenLiteral() string {
+ return rs.Token.Literal
+}
+
type Program struct {
Statements []Statement
}
diff --git a/parser/parser.go b/parser/parser.go
@@ -16,7 +16,7 @@ type Parser struct {
func New(l *lexer.Lexer) *Parser {
p := &Parser{
- l: l,
+ l: l,
errors: []string{},
}
p.nextToken()
@@ -50,6 +50,8 @@ 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
}
@@ -72,6 +74,17 @@ func (p *Parser) parseLetStatement() *ast.LetStatement {
return statement
}
+func (p *Parser) parseReturnStatement() *ast.ReturnStatement {
+ statement := &ast.ReturnStatement{Token: p.curToken}
+ p.nextToken()
+
+ for !p.curTokenIs(token.SEMICOLON) {
+ p.nextToken()
+ }
+
+ return statement
+}
+
func (p *Parser) curTokenIs(t token.TokenType) bool {
return p.curToken.Type == t
}
@@ -91,6 +104,6 @@ func (p *Parser) expectPeek(t token.TokenType) bool {
}
func (p *Parser) peekError(t token.TokenType) {
- msg := fmt.Sprintf("token expected: %s, got: %s", t, p.peekToken.Type);
+ msg := fmt.Sprintf("token expected: %s, got: %s", t, p.peekToken.Type)
p.errors = append(p.errors, msg)
}
diff --git a/parser/parser_test.go b/parser/parser_test.go
@@ -65,6 +65,33 @@ func testLetStatement(t *testing.T, s ast.Statement, name string) bool {
return true
}
+func TestReturnStatements(t *testing.T) {
+ input := `
+return 5;
+return 10;
+return 112233;
+`
+ l := lexer.New(input)
+ p := New(l)
+ program := p.ParseProgram()
+ checkParserErrors(t, p)
+
+ if len(program.Statements) != 3 {
+ t.Fatalf("program.Statements has not 3 elements but %d", len(program.Statements))
+ }
+
+ for _, statement := range program.Statements {
+ returnStatement, ok := statement.(*ast.ReturnStatement)
+ if !ok {
+ t.Errorf("statement is not *ast.ReturnStatement but %T", statement)
+ continue
+ }
+ if returnStatement.TokenLiteral() != "return" {
+ t.Errorf("returnStatement.TokenLiteral() is not 'return' but %s", returnStatement.TokenLiteral())
+ }
+ }
+}
+
func checkParserErrors(t *testing.T, p *Parser) {
errors := p.Errors()
if len(errors) == 0 {