umx_compiler

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

commit 8c8be1578f07ada04e5b7e54fe3150b52c4b18c2
parent cfa21e313f6b842cf3c1e4e8c02c021cde91a2af
Author: bsandro <email@bsandro.tech>
Date:   Sun, 19 Jun 2022 00:19:06 +0300

parser if-else expression support

Diffstat:
Mparser/parser.go | 7+++++++
Mparser/parser_test.go | 45+++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/parser/parser.go b/parser/parser.go @@ -281,6 +281,13 @@ func (p *Parser) parseIfExpression() ast.Expression { return nil } expr.Consequence = p.parseBlockStatement() + if p.peekTokenIs(token.ELSE) { + p.nextToken() + if !p.expectPeek(token.LCURLY) { + return nil + } + expr.Alternative = p.parseBlockStatement() + } return expr } diff --git a/parser/parser_test.go b/parser/parser_test.go @@ -435,3 +435,48 @@ func TestIfExpression(t *testing.T) { t.Fatalf("expr alternative is not nil") } } + +func TestIfElseExpression(t *testing.T) { + input := "if (x<y) { x } else { y }" + l := lexer.New(input) + p := New(l) + prg := p.ParseProgram() + checkParserErrors(t, p) + if len(prg.Statements) != 1 { + t.Fatalf("len(prg.Statements) is not 1 but %d", len(prg.Statements)) + } + statement, ok := prg.Statements[0].(*ast.ExpressionStatement) + if !ok { + t.Fatalf("prg.Statements[0] is not ExpressionStatement but %T", prg.Statements[0]) + } + expr, ok := statement.Expression.(*ast.IfExpression) + if !ok { + t.Fatalf("statement.Expression is not IfExpression but %T", statement.Expression) + } + if !testInfixExpression(t, expr.Condition, "x", "<", "y") { + return + } + if len(expr.Consequence.Statements) != 1 { + t.Fatalf("len(expr.Consequence.Statements) is not 1 but %d", len(expr.Consequence.Statements)) + } + cons, ok := expr.Consequence.Statements[0].(*ast.ExpressionStatement) + if !ok { + t.Fatalf("consequence statement is not Statement but %T", expr.Consequence.Statements[0]) + } + if !testIdentifier(t, cons.Expression, "x") { + return + } + if expr.Alternative == nil { + t.Fatalf("expr alternative cannot be empty") + } + if len(expr.Alternative.Statements) != 1 { + t.Fatalf("len(expr.Alternative.Statements) is not 1 but %d", len(expr.Alternative.Statements)) + } + alt, ok := expr.Alternative.Statements[0].(*ast.ExpressionStatement) + if !ok { + t.Fatalf("alternative statement is not Statement but %T", expr.Alternative.Statements[0]) + } + if !testIdentifier(t, alt.Expression, "y") { + return + } +}