diff options
Diffstat (limited to 'parser/parser_test.go')
| -rw-r--r-- | parser/parser_test.go | 132 |
1 files changed, 110 insertions, 22 deletions
diff --git a/parser/parser_test.go b/parser/parser_test.go index 4d76935..d2a8c8f 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -154,13 +154,14 @@ func testLiteralExpression( 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) + case bool: + return testBooleanLiteral(t, exp, v) } - + t.Errorf("type of exp not handled. got=%T", exp) return false } @@ -175,7 +176,7 @@ func testInfixExpression( opExp, ok := exp.(*ast.InfixExpression) if !ok { - t.Errorf("exp is not ast.InfixExpression. got =%T(%s)", exp, exp) + t.Errorf("exp is not ast.InfixExpression. got =%T(%s)", exp, exp) return false } @@ -263,16 +264,56 @@ func TestIntegerLiteralExpression(t *testing.T) { } } -// Prefix expression tests. +// Boolean expression tests. + +func TestBooleanExpression(t *testing.T) { + tests := []struct { + input string + expectedBoolean bool + }{ + {"true;", true}, + {"false;", false}, + } + + for _, tt := range tests { + var l *lexer.Lexer = lexer.New(tt.input) + var p *Parser = New(l) + var program *ast.Program = p.ParseProgram() + checkParserErrors(t, p) + if len(program.Statements) != 1 { + t.Fatalf("program has not enough statements. got=%d", len(program.Statements)) + } + + stmt, ok := program.Statements[0].(*ast.ExpressionStatement) + + if !ok { + t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T", program.Statements[0]) + } + + boolean, ok := stmt.Expression.(*ast.Boolean) + + if !ok { + t.Fatalf("exp not *ast.Boolean. got=%T", stmt.Expression) + } + + if boolean.Value != tt.expectedBoolean { + t.Errorf("boolean.Value not %t. got=%t", tt.expectedBoolean, boolean.Value) + } + } +} + +// Prefix expression tests. func TestParsingPrefixExpressions(t *testing.T) { var prefixTests = []struct { input string operator string - integerValue int64 + value interface{} }{ {"!5;", "!", 5}, {"-15;", "-", 15}, + {"!true;", "!", true}, + {"!false;", "!", false}, } for _, tt := range prefixTests { @@ -301,7 +342,11 @@ func TestParsingPrefixExpressions(t *testing.T) { t.Fatalf("exp.Operator is not '%s'. got=%s", tt.operator, exp.Operator) } - if !testIntegerLiteral(t, exp.Right, tt.integerValue) { + // if !testIntegerLiteral(t, exp.Right, tt.integerValue) { + // return + // } + + if !testLiteralExpression(t, exp.Right, tt.value) { return } } @@ -335,10 +380,10 @@ func testIntegerLiteral(t *testing.T, il ast.Expression, value int64) bool { func TestParsingInfixExpressions(t *testing.T) { var infixTests = []struct { - input string - leftValue int64 - operator string - rightValue int64 + input string + leftValue interface{} + operator string + rightValue interface{} }{ {"5 + 5;", 5, "+", 5}, {"5 - 5;", 5, "-", 5}, @@ -348,6 +393,9 @@ func TestParsingInfixExpressions(t *testing.T) { {"5 < 5;", 5, "<", 5}, {"5 == 5;", 5, "==", 5}, {"5 != 5;", 5, "!=", 5}, + {"true == true", true, "==", true}, + {"true != false", true, "!=", false}, + {"false == false", false, "==", false}, } for _, tt := range infixTests { @@ -357,7 +405,6 @@ func TestParsingInfixExpressions(t *testing.T) { var program *ast.Program = p.ParseProgram() checkParserErrors(t, p) - if len(program.Statements) != 1 { t.Fatalf("program.Statements does not contain %d statements, got=%d\n", 1, len(program.Statements)) } @@ -368,21 +415,25 @@ func TestParsingInfixExpressions(t *testing.T) { t.Fatalf("program.Statements[0] is not ast.ExpressionStatement, got=%T", program.Statements[0]) } - exp, ok := stmt.Expression.(*ast.InfixExpression) + // exp, ok := stmt.Expression.(*ast.InfixExpression) - if !ok { - t.Fatalf("exp is not ast.InfixExpression. got=%T", stmt.Expression) - } + // if !ok { + // t.Fatalf("exp is not ast.InfixExpression. got=%T", stmt.Expression) + // } - if !testIntegerLiteral(t, exp.Left, tt.leftValue) { - return - } + // 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 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 + // } - if !testIntegerLiteral(t, exp.Right, tt.rightValue) { + if !testInfixExpression(t, stmt.Expression, tt.leftValue, tt.operator, tt.rightValue) { return } } @@ -443,6 +494,22 @@ func TestOperatorPrecedenceParsing(t *testing.T) { "3 + 4 * 5 == 3 * 1 + 4 * 5", "((3 + (4 * 5)) == ((3 * 1) + (4 * 5)))", }, + { + "true", + "true", + }, + { + "false", + "false", + }, + { + "3 > 5 == false", + "((3 > 5) == false)", + }, + { + "3 < 5 == true", + "((3 < 5) == true)", + }, } for _, tt := range tests { @@ -458,3 +525,24 @@ func TestOperatorPrecedenceParsing(t *testing.T) { } } } + +func testBooleanLiteral(t *testing.T, exp ast.Expression, value bool) bool { + boo, ok := exp.(*ast.Boolean) + + if !ok { + t.Errorf("exp not *ast.Boolean. got=%T", exp) + return false + } + + if boo.Value != value { + t.Errorf("boo.Value not %t. got=%t", value, boo.Value) + return false + } + + if boo.TokenLiteral() != fmt.Sprintf("%t", value) { + t.Errorf("boo.TokenLiteral not %t. got=%s", value, boo.TokenLiteral()) + return false + } + + return true +} |
