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
|
// Grouped Expression
|
||||||
l_parser.register_prefix(token.LPAREN, l_parser.parse_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
|
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()
|
l_parser.next_token()
|
||||||
expression := l_parser.parse_expression(LOWEST)
|
expression := l_parser.parse_expression(LOWEST)
|
||||||
if !l_parser.expect_peek(token.RPAREN){
|
if !l_parser.expect_peek(token.RPAREN) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return expression
|
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
|
// Helpers
|
||||||
|
|
||||||
func check_parser_errors(l_test *testing.T, l_parser *Parser) {
|
func check_parser_errors(l_test *testing.T, l_parser *Parser) {
|
||||||
|
Loading…
Reference in New Issue
Block a user