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
+	}
+}