Changes:
- Boolean expression can now be parsed. - Formatting git-svn-id: https://svn.tlawal.org/svn/monkey@32 f6afcba9-9ef1-4bdd-9b72-7484f5705bac
This commit is contained in:
parent
6597024fff
commit
628a604701
10
ast/ast.go
10
ast/ast.go
@ -71,6 +71,11 @@ type InfixExpression struct {
|
|||||||
Right Expression
|
Right Expression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Boolean struct {
|
||||||
|
Token token.Token
|
||||||
|
Value bool
|
||||||
|
}
|
||||||
|
|
||||||
// Let Statements
|
// Let Statements
|
||||||
func (ls *LetStatement) statement_node() {}
|
func (ls *LetStatement) statement_node() {}
|
||||||
|
|
||||||
@ -182,3 +187,8 @@ func (ie *InfixExpression) String() string {
|
|||||||
|
|
||||||
return out.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 }
|
||||||
|
@ -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.LT, l_parser.parse_infix_expression)
|
||||||
l_parser.register_infix(token.GT, 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
|
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)
|
message := fmt.Sprintf("no prefix parse function for %s, found", l_token_type)
|
||||||
l_parser.errors = append(l_parser.errors, message)
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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])
|
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
|
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
|
// Helpers
|
||||||
|
|
||||||
func check_parser_errors(l_test *testing.T, l_parser *Parser) {
|
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
|
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)
|
operator_expression, ok := exp.(*ast.InfixExpression)
|
||||||
if !ok {
|
if !ok {
|
||||||
l_test.Errorf("exp is not ast.InfixExpression, got=%T(%s)", exp, exp)
|
l_test.Errorf("exp is not ast.InfixExpression, got=%T(%s)", exp, exp)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !testLiteralExpression(l_test, operator_expression.Left, left){
|
if !testLiteralExpression(l_test, operator_expression.Left, left) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +428,7 @@ func testInfixExpression(l_test *testing.T, exp ast.Expression, left interface{}
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !testLiteralExpression(l_test, operator_expression.Right, right){
|
if !testLiteralExpression(l_test, operator_expression.Right, right) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
Loading…
Reference in New Issue
Block a user