Test for IfExpressions, and IfElseExpression
git-svn-id: https://svn.tlawal.org/svn/monkey@36 f6afcba9-9ef1-4bdd-9b72-7484f5705bac
This commit is contained in:
parent
5d1197160d
commit
1ac48b0cad
@ -103,6 +103,9 @@ func New(l_lexer *lexer.Lexer) *Parser {
|
||||
// Grouped Expression
|
||||
l_parser.register_prefix(token.LPAREN, l_parser.parse_grouped_expression)
|
||||
|
||||
// IF Expression
|
||||
l_parser.register_prefix(token.IF, l_parser.parse_if_expression)
|
||||
|
||||
return l_parser
|
||||
}
|
||||
|
||||
@ -282,11 +285,62 @@ func (l_parser *Parser) parse_boolean() ast.Expression {
|
||||
}
|
||||
}
|
||||
|
||||
func (l_parser *Parser) parse_grouped_expression() ast.Expression{
|
||||
func (l_parser *Parser) parse_grouped_expression() ast.Expression {
|
||||
defer untrace(trace("parse_grouped_expression"))
|
||||
l_parser.next_token()
|
||||
expression := l_parser.parse_expression(LOWEST)
|
||||
if !l_parser.expect_peek(token.RPAREN){
|
||||
if !l_parser.expect_peek(token.RPAREN) {
|
||||
return nil
|
||||
}
|
||||
return expression
|
||||
}
|
||||
|
||||
func (l_parser *Parser) parse_if_expression() ast.Expression {
|
||||
defer untrace(trace("parse_if_expression"))
|
||||
expression := &ast.IfExpression{
|
||||
Token: l_parser.current_token,
|
||||
}
|
||||
|
||||
if !l_parser.expect_peek(token.LPAREN) {
|
||||
return nil
|
||||
}
|
||||
|
||||
l_parser.next_token()
|
||||
expression.Condition = l_parser.parse_expression(LOWEST)
|
||||
|
||||
if !l_parser.expect_peek(token.RPAREN) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !l_parser.expect_peek(token.LBRACE) {
|
||||
return nil
|
||||
}
|
||||
|
||||
expression.Consequence = l_parser.parse_block_statement()
|
||||
|
||||
if l_parser.peek_token_is(token.ELSE) {
|
||||
l_parser.next_token()
|
||||
if !l_parser.expect_peek(token.LBRACE) {
|
||||
return nil
|
||||
}
|
||||
expression.Alternative = l_parser.parse_block_statement()
|
||||
}
|
||||
|
||||
return expression
|
||||
}
|
||||
|
||||
func (l_parser *Parser) parse_block_statement() *ast.BlockStatement {
|
||||
block := &ast.BlockStatement{Token: l_parser.current_token}
|
||||
block.Statements = []ast.Statement{}
|
||||
|
||||
l_parser.next_token()
|
||||
|
||||
for !l_parser.current_token_is(token.RBRACE) && !l_parser.current_token_is(token.EOF) {
|
||||
statement := l_parser.parse_statement()
|
||||
if statement != nil {
|
||||
block.Statements = append(block.Statements, statement)
|
||||
}
|
||||
l_parser.next_token()
|
||||
}
|
||||
return block
|
||||
}
|
||||
|
@ -359,6 +359,100 @@ func TestBooleanExpression(l_test *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIfExpression(l_test *testing.T) {
|
||||
input := `if (x < y) { x }`
|
||||
|
||||
l_lexer := lexer.New(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 contain %d statements, got=%d\n", 1, 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])
|
||||
}
|
||||
expression, ok := statement.Expression.(*ast.IfExpression)
|
||||
if !ok {
|
||||
l_test.Fatalf("statement.Expression is not ast.IfExpression, got=%T", statement.Expression)
|
||||
}
|
||||
|
||||
if !testInfixExpression(l_test, expression.Condition, "x", "<", "y") {
|
||||
return
|
||||
}
|
||||
if len(expression.Consequence.Statements) != 1 {
|
||||
l_test.Errorf("consequence is not 1 statements, got=%d\n", len(expression.Consequence.Statements))
|
||||
}
|
||||
|
||||
consequence, ok := expression.Consequence.Statements[0].(*ast.ExpressionStatement)
|
||||
if !ok {
|
||||
l_test.Fatalf("Statements[0] is not ast.ExpressionStatement, got=%T", expression.Consequence.Statements[0])
|
||||
}
|
||||
|
||||
if !testIdentifier(l_test, consequence.Expression, "x") {
|
||||
return
|
||||
}
|
||||
|
||||
if expression.Alternative != nil {
|
||||
l_test.Errorf("expression.Alternative.Statements was not nil, got=%+v", expression.Alternative)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIfElseExpression(l_test *testing.T) {
|
||||
input := `if (x < y) { x } else { y }`
|
||||
|
||||
l_lexer := lexer.New(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 contain %d statements, got=%d\n", 1, len(program.Statements))
|
||||
}
|
||||
|
||||
statement, ok := program.Statements[0].(*ast.ExpressionStatement)
|
||||
if !ok {
|
||||
l_test.Fatalf("program.Statements[0] is not an ast.ExpressionStatement, got=%T", program.Statements[0])
|
||||
}
|
||||
|
||||
expression, ok := statement.Expression.(*ast.IfExpression)
|
||||
if !ok {
|
||||
l_test.Fatalf("statement.Expression is not ast.IfExpression, got=%T", statement.Expression)
|
||||
}
|
||||
|
||||
if !testInfixExpression(l_test, expression.Condition, "x", "<", "y") {
|
||||
return
|
||||
}
|
||||
|
||||
if len(expression.Consequence.Statements) != 1 {
|
||||
l_test.Errorf("consequence is not 1 statements, got=%d\n", len(expression.Consequence.Statements))
|
||||
}
|
||||
|
||||
consequence, ok := expression.Consequence.Statements[0].(*ast.ExpressionStatement)
|
||||
if !ok {
|
||||
l_test.Fatalf("Statements[0] is not ast.ExpressionStatement, got=%T", expression.Consequence.Statements[0])
|
||||
}
|
||||
if !testIdentifier(l_test, consequence.Expression, "x") {
|
||||
return
|
||||
}
|
||||
|
||||
if len(expression.Alternative.Statements) != 1 {
|
||||
l_test.Errorf("expression.Alterative.Statements does not contain 1 statement, got=%d\n", len(expression.Alternative.Statements))
|
||||
}
|
||||
|
||||
alternative, ok := expression.Alternative.Statements[0].(*ast.ExpressionStatement)
|
||||
if !ok {
|
||||
l_test.Fatalf("Statements[0] is not ast.ExpressionStatement, got=%T", expression.Alternative.Statements[0])
|
||||
}
|
||||
|
||||
if !testIdentifier(l_test, alternative.Expression, "y") {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
func check_parser_errors(l_test *testing.T, l_parser *Parser) {
|
||||
|
Loading…
Reference in New Issue
Block a user