commit 8c8be1578f07ada04e5b7e54fe3150b52c4b18c2
parent cfa21e313f6b842cf3c1e4e8c02c021cde91a2af
Author: bsandro <email@bsandro.tech>
Date: Sun, 19 Jun 2022 00:19:06 +0300
parser if-else expression support
Diffstat:
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
+ }
+}