| 458 | } |
| 459 | |
| 460 | statements parse_args() { |
| 461 | // comma-separated arguments list |
| 462 | expect(token::open_paren, "Expected ("); |
| 463 | statements args; |
| 464 | while (!is(token::close_paren)) { |
| 465 | statement_ptr arg; |
| 466 | // unpacking: *expr |
| 467 | if (peek().t == token::multiplicative_binary_operator && peek().value == "*") { |
| 468 | size_t start_pos = current; |
| 469 | ++current; // consume * |
| 470 | arg = mk_stmt<spread_expression>(start_pos, parse_expression()); |
| 471 | } else { |
| 472 | arg = parse_expression(); |
| 473 | if (is(token::equals)) { |
| 474 | // keyword argument |
| 475 | // e.g., func(x = 5, y = a or b) |
| 476 | size_t start_pos = current; |
| 477 | ++current; // consume equals |
| 478 | arg = mk_stmt<keyword_argument_expression>(start_pos, std::move(arg), parse_expression()); |
| 479 | } |
| 480 | } |
| 481 | args.push_back(std::move(arg)); |
| 482 | if (is(token::comma)) { |
| 483 | ++current; // consume comma |
| 484 | } |
| 485 | } |
| 486 | expect(token::close_paren, "Expected )"); |
| 487 | return args; |
| 488 | } |
| 489 | |
| 490 | statement_ptr parse_member_expression(statement_ptr object) { |
| 491 | size_t start_pos = current; |