diff --git a/ast/ast.go b/ast/ast.go index b4b3374..2fedfc8 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -71,6 +71,11 @@ type InfixExpression struct { Right Expression } +type Boolean struct { + Token token.Token + Value bool +} + // Let Statements func (ls *LetStatement) statement_node() {} @@ -182,3 +187,8 @@ func (ie *InfixExpression) String() string { return out.String() } + +// Booleans +func (b *Boolean) expression_node() {} +func (b *Boolean) TokenLiteral() string { return b.Token.Literal } +func (b *Boolean) String() string { return b.Token.Literal } diff --git a/parser/parser.go b/parser/parser.go index 004daf2..ebab816 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -96,6 +96,10 @@ func New(l_lexer *lexer.Lexer) *Parser { l_parser.register_infix(token.LT, l_parser.parse_infix_expression) l_parser.register_infix(token.GT, l_parser.parse_infix_expression) + // Boolean + l_parser.register_prefix(token.TRUE, l_parser.parse_boolean) + l_parser.register_prefix(token.FALSE, l_parser.parse_boolean) + return l_parser } @@ -266,3 +270,12 @@ func (l_parser *Parser) no_prefix_parse_function_error(l_token_type token.TokenT message := fmt.Sprintf("no prefix parse function for %s, found", l_token_type) l_parser.errors = append(l_parser.errors, message) } + + +func (l_parser *Parser) parse_boolean() ast.Expression { + defer untrace(trace("parse_boolean")) + return &ast.Boolean{ + Token: l_parser.current_token, + Value: l_parser.current_token_is(token.TRUE), + } +} diff --git a/parser/parser_test.go b/parser/parser_test.go index 1af6fc1..2ca5a16 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -210,7 +210,7 @@ func TestParsingInfixExpressions(l_test *testing.T) { l_test.Fatalf("program.Statements[0] is not ast.ExpressionStatement, got=%T", program.Statements[0]) } - if !testInfixExpression(l_test, statement.Expression, tt.left_value, tt.operator, tt.right_value){ + if !testInfixExpression(l_test, statement.Expression, tt.left_value, tt.operator, tt.right_value) { return } } @@ -283,6 +283,41 @@ func TestOperatorPrecedenceParsing(l_test *testing.T) { } } +func TestBooleanExpression(l_test *testing.T) { + tests := []struct { + input string + expected_boolean bool + }{ + {"true;", true}, + {"false;", false}, + } + + for _, tt := range tests { + l_lexer := lexer.New(tt.input) + l_parser := New(l_lexer) + + program := l_parser.ParseProgram() + check_parser_errors(l_test, l_parser) + + if len(program.Statements) != 1 { + l_test.Fatalf("program.Statements does not have enough statements, got=%d", len(program.Statements)) + } + + statement, ok := program.Statements[0].(*ast.ExpressionStatement) + if !ok { + l_test.Fatalf("program.Statements[0] is not ast.ExpressionStatement, got=%T", program.Statements[0]) + } + + boolean, ok := statement.Expression.(*ast.Boolean) + if !ok { + l_test.Fatalf("exp not *ast.Boolean, got=%T", statement.Expression) + } + if boolean.Value != tt.expected_boolean { + l_test.Errorf("boolean.Value not %t, got=%t", tt.expected_boolean, boolean.Value) + } + } +} + // Helpers func check_parser_errors(l_test *testing.T, l_parser *Parser) { @@ -377,14 +412,14 @@ func testLiteralExpression(l_test *testing.T, exp ast.Expression, expected inter return false } -func testInfixExpression(l_test *testing.T, exp ast.Expression, left interface{}, operator string, right interface{}) bool{ +func testInfixExpression(l_test *testing.T, exp ast.Expression, left interface{}, operator string, right interface{}) bool { operator_expression, ok := exp.(*ast.InfixExpression) if !ok { l_test.Errorf("exp is not ast.InfixExpression, got=%T(%s)", exp, exp) return false } - if !testLiteralExpression(l_test, operator_expression.Left, left){ + if !testLiteralExpression(l_test, operator_expression.Left, left) { return false } @@ -393,7 +428,7 @@ func testInfixExpression(l_test *testing.T, exp ast.Expression, left interface{} return false } - if !testLiteralExpression(l_test, operator_expression.Right, right){ + if !testLiteralExpression(l_test, operator_expression.Right, right) { return false } return true