umx_compiler

UMX virtual machine "Monkey" interpreter / bytecode compiler
git clone git://bsandro.tech/umx_compiler
Log | Files | Refs

commit 800aaef02c811fab39454b02cdb7589b45c61e66
parent e4e1fdf1534021f113946a65701fdba78d1be9d9
Author: bsandro <email@bsandro.tech>
Date:   Mon, 13 Jun 2022 03:04:39 +0300

Parsing return statements (initial stuff)

Diffstat:
Mast/ast.go | 10++++++++++
Mparser/parser.go | 17+++++++++++++++--
Mparser/parser_test.go | 27+++++++++++++++++++++++++++
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 {