diff --git a/parser/parser_test.go b/parser/parser_test.go index f869eb5..6c7df26 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -92,18 +92,7 @@ func TestIdentifierExpression(t *testing.T) { t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T", program.Statements[0]) } - ident, ok := stmt.Expression.(*ast.Identifier) - if !ok { - t.Fatalf("exp not *ast.Identifier. got=%T", stmt.Expression) - } - - if ident.Value != "foobar" { - t.Errorf("ident.Value not %s. got=%s", "foobar", ident.Value) - } - - if ident.TokenLiteral() != "foobar" { - t.Errorf("ident.TokenLiteral() not %s. got=%s", "foobar", ident.TokenLiteral()) - } + testLiteralExpression(t, stmt.Expression, "foobar") } func TestIntegerLiteralExpression(t *testing.T) { @@ -123,16 +112,7 @@ func TestIntegerLiteralExpression(t *testing.T) { t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T", program.Statements[0]) } - literal, ok := stmt.Expression.(*ast.IntegerLiteral) - if !ok { - t.Fatalf("exp is not *ast.IntegerLiteral. got=%T", stmt.Expression) - } - if literal.Value != 5 { - t.Errorf("literal.Value not %d. got=%d", 5, literal.Value) - } - if literal.TokenLiteral() != "5" { - t.Errorf("literal.TokenLiteral not %s. got=%s", "5", literal.TokenLiteral()) - } + testLiteralExpression(t, stmt.Expression, 5) } func TestParsingPrefixExpressions(t *testing.T) { @@ -207,22 +187,7 @@ func TestParsingInfixExpressions(t *testing.T) { t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T\n", program.Statements[0]) } - exp, ok := stmt.Expression.(*ast.InfixExpression) - if !ok { - t.Fatalf("stmt is not ast.InfixExpression. got=%T", stmt.Expression) - } - - if !testIntegerLiteral(t, exp.Left, tt.leftValue) { - return - } - - if exp.Operator != tt.operator { - t.Fatalf("exp.Operator is not '%s'. got=%s", tt.operator, exp.Operator) - } - - if !testIntegerLiteral(t, exp.Right, tt.rightValue) { - return - } + testInfixExpression(t, stmt.Expression, tt.leftValue, tt.operator, tt.rightValue) } } @@ -339,6 +304,63 @@ func testIntegerLiteral(t *testing.T, il ast.Expression, value int64) bool { return true } +func testIdentifier(t *testing.T, exp ast.Expression, value string) bool { + ident, ok := exp.(*ast.Identifier) + if !ok { + t.Errorf("exp not *ast.Identifier. got=%T", exp) + return false + } + + if ident.Value != value { + t.Errorf("ident.Value not %s. got=%s", value, ident.Value) + return false + } + + if ident.TokenLiteral() != value { + t.Errorf("ident.TokenLiteral() not %s. got=%s", value, ident.TokenLiteral()) + return false + } + + return true +} + +func testLiteralExpression(t *testing.T, exp ast.Expression, expected interface{}) bool { + switch v := expected.(type) { + case int: + return testIntegerLiteral(t, exp, int64(v)) + case int64: + return testIntegerLiteral(t, exp, v) + case string: + return testIdentifier(t, exp, v) + } + + t.Errorf("type of exp not handled. got=%T", expected) + return false +} + +func testInfixExpression(t *testing.T, exp ast.Expression, left interface{}, operator string, right interface{}) bool { + opExp, ok := exp.(*ast.InfixExpression) + if !ok { + t.Errorf("exp is not ast.InfixExpression. got=%T(%s)", exp, exp) + return false + } + + if !testLiteralExpression(t, opExp.Left, left) { + return false + } + + if opExp.Operator != operator { + t.Errorf("exp.Operator is not '%s'. got=%q", operator, opExp.Operator) + return false + } + + if !testLiteralExpression(t, opExp.Right, right) { + return false + } + + return true +} + func checkParserErrors(t *testing.T, p *Parser) { errors := p.Errors() if len(errors) == 0 {