umx_compiler

UMX virtual machine "Monkey" interpreter / bytecode compiler
git clone git://bsandro.tech/umx_compiler
Log | Files | Refs | README | LICENSE

parser_test.go (17790B)


      1 package parser
      2 
      3 import (
      4 	"fmt"
      5 	"umx_compiler/ast"
      6 	"umx_compiler/lexer"
      7 	"testing"
      8 )
      9 
     10 func TestLetStatements(t *testing.T) {
     11 	tests := []struct {
     12 		input              string
     13 		expectedIdentifier string
     14 		expectedValue      interface{}
     15 	}{
     16 		{"let x = 5;", "x", 5},
     17 		{"let y = true;", "y", true},
     18 		{"let foo = y;", "foo", "y"},
     19 	}
     20 
     21 	for _, tt := range tests {
     22 		l := lexer.New(tt.input)
     23 		p := New(l)
     24 		prg := p.ParseProgram()
     25 		checkParserErrors(t, p)
     26 
     27 		if prg == nil {
     28 			t.Fatalf("ParseProgram() returned nil")
     29 		}
     30 		if len(prg.Statements) != 1 {
     31 			t.Fatalf("program.Statements has not 1 elements but %d", len(prg.Statements))
     32 		}
     33 
     34 		statement := prg.Statements[0]
     35 		if !testLetStatement(t, statement, tt.expectedIdentifier) {
     36 			return
     37 		}
     38 
     39 		val := statement.(*ast.LetStatement).Value
     40 		if !testLiteralExpression(t, val, tt.expectedValue) {
     41 			return
     42 		}
     43 	}
     44 }
     45 
     46 func testLetStatement(t *testing.T, s ast.Statement, name string) bool {
     47 	if s.TokenLiteral() != "let" {
     48 		t.Errorf("s.TokenLiteral() is not 'let' but '%s' instead", s.TokenLiteral())
     49 		return false
     50 	}
     51 
     52 	letStatement, ok := s.(*ast.LetStatement)
     53 	if !ok {
     54 		t.Errorf("s is not *ast.LetStatement but %T", s)
     55 		return false
     56 	}
     57 
     58 	if letStatement.Name.Value != name {
     59 		t.Errorf("letStatement.Name.Value is not %s but %s", name, letStatement.Name.Value)
     60 		return false
     61 	}
     62 
     63 	if letStatement.Name.TokenLiteral() != name {
     64 		t.Errorf("letStatement.Name.TokenLiteral() is not %s but %s", name, letStatement.Name.TokenLiteral())
     65 		return false
     66 	}
     67 
     68 	return true
     69 }
     70 
     71 func TestReturnStatements(t *testing.T) {
     72 	input := `
     73 return 5;
     74 return 10;
     75 return 112233;
     76 `
     77 	l := lexer.New(input)
     78 	p := New(l)
     79 	program := p.ParseProgram()
     80 	checkParserErrors(t, p)
     81 
     82 	if len(program.Statements) != 3 {
     83 		t.Fatalf("program.Statements has not 3 elements but %d", len(program.Statements))
     84 	}
     85 
     86 	for _, statement := range program.Statements {
     87 		returnStatement, ok := statement.(*ast.ReturnStatement)
     88 		if !ok {
     89 			t.Errorf("statement is not *ast.ReturnStatement but %T", statement)
     90 			continue
     91 		}
     92 		if returnStatement.TokenLiteral() != "return" {
     93 			t.Errorf("returnStatement.TokenLiteral() is not 'return' but %s", returnStatement.TokenLiteral())
     94 		}
     95 	}
     96 }
     97 
     98 func checkParserErrors(t *testing.T, p *Parser) {
     99 	errors := p.Errors()
    100 	if len(errors) == 0 {
    101 		return
    102 	}
    103 
    104 	t.Errorf("%d parse errors:", len(errors))
    105 	for _, msg := range errors {
    106 		t.Errorf("%s", msg)
    107 	}
    108 	t.FailNow()
    109 }
    110 
    111 func TestIdentifierExpression(t *testing.T) {
    112 	input := "foo;"
    113 
    114 	l := lexer.New(input)
    115 	p := New(l)
    116 	prg := p.ParseProgram()
    117 	checkParserErrors(t, p)
    118 
    119 	if len(prg.Statements) != 1 {
    120 		t.Fatalf("prg.Statements has more than 1 element (%d)", len(prg.Statements))
    121 	}
    122 
    123 	statement, ok := prg.Statements[0].(*ast.ExpressionStatement)
    124 	if !ok {
    125 		t.Fatalf("prg.Statements[0] is not ast.ExpressionStatement but %T", prg.Statements[0])
    126 	}
    127 
    128 	ident, ok := statement.Expression.(*ast.Identifier)
    129 	if !ok {
    130 		t.Fatalf("expression is not *ast.Identifier but %T", statement.Expression)
    131 	}
    132 
    133 	if ident.Value != "foo" {
    134 		t.Fatalf("ident.Value is not valid: %s", ident.Value)
    135 	}
    136 
    137 	if ident.TokenLiteral() != "foo" {
    138 		t.Errorf("ident.TokenLiteral() is not 'foo' but %s", ident.TokenLiteral())
    139 	}
    140 }
    141 
    142 func TestIntegerLiteralExpression(t *testing.T) {
    143 	input := "8;"
    144 	l := lexer.New(input)
    145 	p := New(l)
    146 	prg := p.ParseProgram()
    147 	checkParserErrors(t, p)
    148 
    149 	if len(prg.Statements) != 1 {
    150 		t.Fatalf("statements count is not 1 but %d", len(prg.Statements))
    151 	}
    152 
    153 	statement, ok := prg.Statements[0].(*ast.ExpressionStatement)
    154 	if !ok {
    155 		t.Fatalf("prg.Statements[0] is not ExpressionStatement but %T", prg.Statements[0])
    156 	}
    157 
    158 	literal, ok := statement.Expression.(*ast.IntegerLiteral)
    159 	if !ok {
    160 		t.Fatalf("statement.Expression is not IntegerLiteral but %T", statement.Expression)
    161 	}
    162 
    163 	if literal.Value != 8 {
    164 		t.Errorf("literal.Value is not 8 but %d", literal.Value)
    165 	}
    166 
    167 	if literal.TokenLiteral() != "8" {
    168 		t.Errorf("literal.TokenLiteral is not '8' but %s", literal.TokenLiteral())
    169 	}
    170 }
    171 
    172 func TestParsingPrefixExpressions(t *testing.T) {
    173 	prefixTests := []struct {
    174 		input    string
    175 		operator string
    176 		value    interface{}
    177 	}{
    178 		{"!5;", "!", 5},
    179 		{"-15;", "-", 15},
    180 		{"!true;", "!", true},
    181 	}
    182 
    183 	for _, tt := range prefixTests {
    184 		l := lexer.New(tt.input)
    185 		p := New(l)
    186 		prg := p.ParseProgram()
    187 		checkParserErrors(t, p)
    188 
    189 		if len(prg.Statements) != 1 {
    190 			t.Fatalf("prg.Statements count is wrong: %d instead of 1", len(prg.Statements))
    191 		}
    192 
    193 		statement, ok := prg.Statements[0].(*ast.ExpressionStatement)
    194 		if !ok {
    195 			t.Fatalf("prg.Statements[0] is not ast.ExpressionStatement but %T", prg.Statements[0])
    196 		}
    197 
    198 		expr, ok := statement.Expression.(*ast.PrefixExpression)
    199 		if !ok {
    200 			t.Fatalf("statement.Expression is not PrefixExpression but %T", statement.Expression)
    201 		}
    202 
    203 		if expr.Operator != tt.operator {
    204 			t.Fatalf("exp.Operator is not %s but %s", tt.operator, expr.Operator)
    205 		}
    206 
    207 		if !testLiteralExpression(t, expr.Right, tt.value) {
    208 			return
    209 		}
    210 	}
    211 }
    212 
    213 func TestParsingInfixExpressions(t *testing.T) {
    214 	infixTests := []struct {
    215 		input      string
    216 		leftValue  interface{}
    217 		operator   string
    218 		rightValue interface{}
    219 	}{
    220 		{"1 + 2", 1, "+", 2},
    221 		{"3 - 4", 3, "-", 4},
    222 		{"5 * 6", 5, "*", 6},
    223 		{"7 / 8", 7, "/", 8},
    224 		{"9 > 0", 9, ">", 0},
    225 		{"1 < 2", 1, "<", 2},
    226 		{"3 == 3", 3, "==", 3},
    227 		{"4 != 5", 4, "!=", 5},
    228 		{"true == true", true, "==", true},
    229 	}
    230 
    231 	for _, tt := range infixTests {
    232 		l := lexer.New(tt.input)
    233 		p := New(l)
    234 		prg := p.ParseProgram()
    235 		checkParserErrors(t, p)
    236 
    237 		if len(prg.Statements) != 1 {
    238 			t.Fatalf("prg.Statements length is not 1 but %d", len(prg.Statements))
    239 		}
    240 
    241 		statement, ok := prg.Statements[0].(*ast.ExpressionStatement)
    242 		if !ok {
    243 			t.Fatalf("statement is not ExpressionStatement but %T", prg.Statements[0])
    244 		}
    245 
    246 		if !testInfixExpression(t, statement.Expression, tt.leftValue, tt.operator, tt.rightValue) {
    247 			return
    248 		}
    249 	}
    250 }
    251 
    252 func testIntegerLiteral(t *testing.T, il ast.Expression, value int64) bool {
    253 	integ, ok := il.(*ast.IntegerLiteral)
    254 	if !ok {
    255 		t.Errorf("il is not *ast.IntegerLiteral but %T", il)
    256 		return false
    257 	}
    258 	if integ.Value != value {
    259 		t.Errorf("integ.Value is not %d but %d", value, integ.Value)
    260 		return false
    261 	}
    262 	if integ.TokenLiteral() != fmt.Sprintf("%d", value) {
    263 		t.Errorf("integ.TokenLiteral not %d but %s", value, integ.TokenLiteral())
    264 		return false
    265 	}
    266 	return true
    267 }
    268 
    269 func testBooleanLiteral(t *testing.T, expr ast.Expression, value bool) bool {
    270 	bo, ok := expr.(*ast.Boolean)
    271 	if !ok {
    272 		t.Errorf("expr is not boolean but %T", expr)
    273 		return false
    274 	}
    275 	if bo.Value != value {
    276 		t.Errorf("bo.Value is not %t but %t", value, bo.Value)
    277 		return false
    278 	}
    279 	if bo.TokenLiteral() != fmt.Sprintf("%t", value) {
    280 		t.Errorf("bo.TokenLiteral is not %t but %s", value, bo.TokenLiteral())
    281 		return false
    282 	}
    283 	return true
    284 }
    285 
    286 func testIdentifier(t *testing.T, expr ast.Expression, value string) bool {
    287 	ident, ok := expr.(*ast.Identifier)
    288 	if !ok {
    289 		t.Errorf("expr is not *ast.Identifier but %T", expr)
    290 		return false
    291 	}
    292 	if ident.Value != value {
    293 		t.Errorf("ident.Value is not %s but %s", value, ident.Value)
    294 		return false
    295 	}
    296 	if ident.TokenLiteral() != value {
    297 		t.Errorf("ident.TokenLiteral() is not %s but %s", value, ident.TokenLiteral())
    298 		return false
    299 	}
    300 	return true
    301 }
    302 
    303 func testLiteralExpression(t *testing.T, expr ast.Expression, expected interface{}) bool {
    304 	switch v := expected.(type) {
    305 	case int:
    306 		return testIntegerLiteral(t, expr, int64(v))
    307 	case int64:
    308 		return testIntegerLiteral(t, expr, v)
    309 	case string:
    310 		return testIdentifier(t, expr, v)
    311 	case bool:
    312 		return testBooleanLiteral(t, expr, v)
    313 	}
    314 	t.Errorf("expr type is not handled: %T", expr)
    315 	return false
    316 }
    317 
    318 func testInfixExpression(t *testing.T, expr ast.Expression, left interface{}, operator string, right interface{}) bool {
    319 	opExpr, ok := expr.(*ast.InfixExpression)
    320 	if !ok {
    321 		t.Errorf("expr is not *ast.InfixExpression but %T", expr)
    322 		return false
    323 	}
    324 	if !testLiteralExpression(t, opExpr.Left, left) {
    325 		return false
    326 	}
    327 	if opExpr.Operator != operator {
    328 		t.Errorf("opExpr.Operator is not %q but %q", operator, opExpr.Operator)
    329 		return false
    330 	}
    331 	if !testLiteralExpression(t, opExpr.Right, right) {
    332 		return false
    333 	}
    334 	return true
    335 }
    336 
    337 func TestOperatorPrecedenceParsing(t *testing.T) {
    338 	tests := []struct {
    339 		input    string
    340 		expected string
    341 	}{
    342 		{"-a*b", "((-a) * b)"},
    343 		{"!-a", "(!(-a))"},
    344 		{"a+b+c", "((a + b) + c)"},
    345 		{"a*b*c", "((a * b) * c)"},
    346 		{"a*b/c", "((a * b) / c)"},
    347 		{"a+b*c+d/e-f", "(((a + (b * c)) + (d / e)) - f)"},
    348 		{"5>4==3<4", "((5 > 4) == (3 < 4))"},
    349 		{"true", "true"},
    350 		{"false", "false"},
    351 		{"3<5==true==!false", "(((3 < 5) == true) == (!false))"},
    352 		{"!(true == true)", "(!(true == true))"},
    353 		{"2/(5+5)", "(2 / (5 + 5))"},
    354 		{"-(5+5)", "(-(5 + 5))"},
    355 		{"a+add(b*c)+d", "((a + add((b * c))) + d)"},
    356 		{"add(a+b+c*d/f+g)", "add((((a + b) + ((c * d) / f)) + g))"},
    357 		{"add(a,b,1,2*3,4+5,add(6,7+8))", "add(a, b, 1, (2 * 3), (4 + 5), add(6, (7 + 8)))"},
    358 		{"a*[1,2,3,4][b*c]*d", "((a * ([1, 2, 3, 4][(b * c)])) * d)"},
    359 		{"add(a*b[2], b[1], 2*[1,2][1])", "add((a * (b[2])), (b[1]), (2 * ([1, 2][1])))"},
    360 	}
    361 
    362 	for _, tt := range tests {
    363 		l := lexer.New(tt.input)
    364 		p := New(l)
    365 		prg := p.ParseProgram()
    366 		checkParserErrors(t, p)
    367 		actual := prg.String()
    368 		if actual != tt.expected {
    369 			t.Errorf("expected %q but got %q", tt.expected, actual)
    370 		}
    371 	}
    372 }
    373 
    374 func TestBooleanExpression(t *testing.T) {
    375 	tests := []struct {
    376 		input           string
    377 		expectedBoolean bool
    378 	}{
    379 		{"true;", true},
    380 		{"false;", false},
    381 	}
    382 
    383 	for _, tt := range tests {
    384 		l := lexer.New(tt.input)
    385 		p := New(l)
    386 		program := p.ParseProgram()
    387 		checkParserErrors(t, p)
    388 
    389 		if len(program.Statements) != 1 {
    390 			t.Fatalf("program has not enough statements. got=%d",
    391 				len(program.Statements))
    392 		}
    393 
    394 		stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
    395 		if !ok {
    396 			t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T",
    397 				program.Statements[0])
    398 		}
    399 
    400 		boolean, ok := stmt.Expression.(*ast.Boolean)
    401 		if !ok {
    402 			t.Fatalf("exp not *ast.Boolean. got=%T", stmt.Expression)
    403 		}
    404 		if boolean.Value != tt.expectedBoolean {
    405 			t.Errorf("boolean.Value not %t. got=%t", tt.expectedBoolean,
    406 				boolean.Value)
    407 		}
    408 	}
    409 }
    410 
    411 func TestIfExpression(t *testing.T) {
    412 	input := "if (x<y) { x }"
    413 	l := lexer.New(input)
    414 	p := New(l)
    415 	prg := p.ParseProgram()
    416 	checkParserErrors(t, p)
    417 	if len(prg.Statements) != 1 {
    418 		t.Fatalf("len(prg.Statements) is not 1 but %d", len(prg.Statements))
    419 	}
    420 	statement, ok := prg.Statements[0].(*ast.ExpressionStatement)
    421 	if !ok {
    422 		t.Fatalf("prg.Statements[0] is not ExpressionStatement but %T", prg.Statements[0])
    423 	}
    424 	expr, ok := statement.Expression.(*ast.IfExpression)
    425 	if !ok {
    426 		t.Fatalf("statement.Expression is not IfExpression but %T", statement.Expression)
    427 	}
    428 	if !testInfixExpression(t, expr.Condition, "x", "<", "y") {
    429 		return
    430 	}
    431 	if len(expr.Consequence.Statements) != 1 {
    432 		t.Fatalf("len(expr.Consequence.Statements) is not 1 but %d", len(expr.Consequence.Statements))
    433 	}
    434 	cons, ok := expr.Consequence.Statements[0].(*ast.ExpressionStatement)
    435 	if !ok {
    436 		t.Fatalf("consequence statement is not Statement but %T", expr.Consequence.Statements[0])
    437 	}
    438 	if !testIdentifier(t, cons.Expression, "x") {
    439 		return
    440 	}
    441 	if expr.Alternative != nil {
    442 		t.Fatalf("expr alternative is not nil")
    443 	}
    444 }
    445 
    446 func TestIfElseExpression(t *testing.T) {
    447 	input := "if (x<y) { x } else { y }"
    448 	l := lexer.New(input)
    449 	p := New(l)
    450 	prg := p.ParseProgram()
    451 	checkParserErrors(t, p)
    452 	if len(prg.Statements) != 1 {
    453 		t.Fatalf("len(prg.Statements) is not 1 but %d", len(prg.Statements))
    454 	}
    455 	statement, ok := prg.Statements[0].(*ast.ExpressionStatement)
    456 	if !ok {
    457 		t.Fatalf("prg.Statements[0] is not ExpressionStatement but %T", prg.Statements[0])
    458 	}
    459 	expr, ok := statement.Expression.(*ast.IfExpression)
    460 	if !ok {
    461 		t.Fatalf("statement.Expression is not IfExpression but %T", statement.Expression)
    462 	}
    463 	if !testInfixExpression(t, expr.Condition, "x", "<", "y") {
    464 		return
    465 	}
    466 	if len(expr.Consequence.Statements) != 1 {
    467 		t.Fatalf("len(expr.Consequence.Statements) is not 1 but %d", len(expr.Consequence.Statements))
    468 	}
    469 	cons, ok := expr.Consequence.Statements[0].(*ast.ExpressionStatement)
    470 	if !ok {
    471 		t.Fatalf("consequence statement is not Statement but %T", expr.Consequence.Statements[0])
    472 	}
    473 	if !testIdentifier(t, cons.Expression, "x") {
    474 		return
    475 	}
    476 	if expr.Alternative == nil {
    477 		t.Fatalf("expr alternative cannot be empty")
    478 	}
    479 	if len(expr.Alternative.Statements) != 1 {
    480 		t.Fatalf("len(expr.Alternative.Statements) is not 1 but %d", len(expr.Alternative.Statements))
    481 	}
    482 	alt, ok := expr.Alternative.Statements[0].(*ast.ExpressionStatement)
    483 	if !ok {
    484 		t.Fatalf("alternative statement is not Statement but %T", expr.Alternative.Statements[0])
    485 	}
    486 	if !testIdentifier(t, alt.Expression, "y") {
    487 		return
    488 	}
    489 }
    490 
    491 func TestFunctionLiteralParsing(t *testing.T) {
    492 	input := "fn(x,y) { x+y; }"
    493 	l := lexer.New(input)
    494 	p := New(l)
    495 	prg := p.ParseProgram()
    496 	checkParserErrors(t, p)
    497 	if len(prg.Statements) != 1 {
    498 		t.Fatalf("prg.Statements count is wrong")
    499 	}
    500 	statement, ok := prg.Statements[0].(*ast.ExpressionStatement)
    501 	if !ok {
    502 		t.Fatalf("prg.Statement[0] is not expressionstatement but %T", prg.Statements[0])
    503 	}
    504 	function, ok := statement.Expression.(*ast.FunctionLiteral)
    505 	if !ok {
    506 		t.Fatalf("statement.Expression is not a function but %T", statement.Expression)
    507 	}
    508 	if len(function.Parameters) != 2 {
    509 		t.Fatalf("function parameters count is wrong")
    510 	}
    511 	testLiteralExpression(t, function.Parameters[0], "x")
    512 	testLiteralExpression(t, function.Parameters[1], "y")
    513 	if len(function.Body.Statements) != 1 {
    514 		t.Fatalf("function body statements count is wrong")
    515 	}
    516 	bodyStatement, ok := function.Body.Statements[0].(*ast.ExpressionStatement)
    517 	if !ok {
    518 		t.Fatalf("body statement is not an expression")
    519 	}
    520 	testInfixExpression(t, bodyStatement.Expression, "x", "+", "y")
    521 }
    522 
    523 func TestFunctionParameterParsing(t *testing.T) {
    524 	tests := []struct {
    525 		input          string
    526 		expectedParams []string
    527 	}{
    528 		{input: "fn(){};", expectedParams: []string{}},
    529 		{input: "fn(x){};", expectedParams: []string{"x"}},
    530 		{input: "fn(x,y,z){};", expectedParams: []string{"x", "y", "z"}},
    531 	}
    532 
    533 	for _, tt := range tests {
    534 		l := lexer.New(tt.input)
    535 		p := New(l)
    536 		prg := p.ParseProgram()
    537 		checkParserErrors(t, p)
    538 		statement := prg.Statements[0].(*ast.ExpressionStatement)
    539 		function := statement.Expression.(*ast.FunctionLiteral)
    540 		if len(function.Parameters) != len(tt.expectedParams) {
    541 			t.Errorf("parameters count is wrong (%d instead of %d)", len(function.Parameters), len(tt.expectedParams))
    542 		}
    543 		for i, ident := range tt.expectedParams {
    544 			testLiteralExpression(t, function.Parameters[i], ident)
    545 		}
    546 	}
    547 }
    548 
    549 func TestCallParametersParsing(t *testing.T) {
    550 	input := "add(1, 2*3, 4+5);"
    551 	l := lexer.New(input)
    552 	p := New(l)
    553 	prg := p.ParseProgram()
    554 	checkParserErrors(t, p)
    555 	if len(prg.Statements) != 1 {
    556 		t.Fatalf("prg.Statements count is wrong")
    557 	}
    558 	statement, ok := prg.Statements[0].(*ast.ExpressionStatement)
    559 	if !ok {
    560 		t.Fatalf("prg.Statements[0] is not ExpressionStatement but %T", prg.Statements[0])
    561 	}
    562 	expr, ok := statement.Expression.(*ast.CallExpression)
    563 	if !ok {
    564 		t.Fatalf("statement.Expression is not CallExpression but %T", statement.Expression)
    565 	}
    566 	if !testIdentifier(t, expr.Function, "add") {
    567 		return
    568 	}
    569 	if len(expr.Arguments) != 3 {
    570 		t.Fatalf("expr.Arguments count is wrong (%d)", len(expr.Arguments))
    571 	}
    572 	testLiteralExpression(t, expr.Arguments[0], 1)
    573 	testInfixExpression(t, expr.Arguments[1], 2, "*", 3)
    574 	testInfixExpression(t, expr.Arguments[2], 4, "+", 5)
    575 }
    576 
    577 func TestStringLiteralExpression(t *testing.T) {
    578 	input := `"ehlo world";`
    579 	l := lexer.New(input)
    580 	p := New(l)
    581 	prg := p.ParseProgram()
    582 	checkParserErrors(t, p)
    583 	statement := prg.Statements[0].(*ast.ExpressionStatement)
    584 	literal, ok := statement.Expression.(*ast.StringLiteral)
    585 	if !ok {
    586 		t.Fatalf("expression is not string literal")
    587 	}
    588 	if literal.Value != "ehlo world" {
    589 		t.Errorf("literal string value is wrong")
    590 	}
    591 }
    592 
    593 func TestParsingArrayLiterals(t *testing.T) {
    594 	input := "[10,20*30,40+50]"
    595 	l := lexer.New(input)
    596 	p := New(l)
    597 	prg := p.ParseProgram()
    598 	checkParserErrors(t, p)
    599 	statement, ok := prg.Statements[0].(*ast.ExpressionStatement)
    600 	array, ok := statement.Expression.(*ast.ArrayLiteral)
    601 	if !ok {
    602 		t.Fatalf("expression is not ArrayLiteral")
    603 	}
    604 	if len(array.Elements) != 3 {
    605 		t.Fatalf("array Elements count is wrong")
    606 	}
    607 	testIntegerLiteral(t, array.Elements[0], 10)
    608 	testInfixExpression(t, array.Elements[1], 20, "*", 30)
    609 	testInfixExpression(t, array.Elements[2], 40, "+", 50)
    610 }
    611 
    612 func TestParsingIndexExpressions(t *testing.T) {
    613 	input := "myArray[1+2]"
    614 	l := lexer.New(input)
    615 	p := New(l)
    616 	prg := p.ParseProgram()
    617 	checkParserErrors(t, p)
    618 	statement, ok := prg.Statements[0].(*ast.ExpressionStatement)
    619 	indexExp, ok := statement.Expression.(*ast.IndexExpression)
    620 	if !ok {
    621 		t.Fatalf("expression is not IndexExpression")
    622 	}
    623 	if !testIdentifier(t, indexExp.Left, "myArray") {
    624 		return
    625 	}
    626 	if !testInfixExpression(t, indexExp.Index, 1, "+", 2) {
    627 		return
    628 	}
    629 }
    630 
    631 func TestParsingHashLiteralsStringKeys(t *testing.T) {
    632 	input := `{"one": 1, "two": 2, "three": 3};`
    633 	l := lexer.New(input)
    634 	p := New(l)
    635 	prg := p.ParseProgram()
    636 	checkParserErrors(t, p)
    637 	statement := prg.Statements[0].(*ast.ExpressionStatement)
    638 	hash, ok := statement.Expression.(*ast.HashLiteral)
    639 	if !ok {
    640 		t.Fatalf("expression is not ast.HashLiteral but %T", statement.Expression)
    641 	}
    642 	if len(hash.Pairs) != 3 {
    643 		t.Fatalf("Wrong number of elements in hash")
    644 	}
    645 	expected := map[string]int64{
    646 		"one":   1,
    647 		"two":   2,
    648 		"three": 3,
    649 	}
    650 	for k, v := range hash.Pairs {
    651 		literal, ok := k.(*ast.StringLiteral)
    652 		if !ok {
    653 			t.Fatalf("key is not ast.StringLiteral")
    654 		}
    655 		expectedVal := expected[literal.String()]
    656 		testIntegerLiteral(t, v, expectedVal)
    657 	}
    658 }