@@ -8539,108 +8539,46 @@ parse_write(yp_parser_t *parser, yp_node_t *target, yp_token_t *operator, yp_nod
8539
8539
// target node or a multi-target node.
8540
8540
static yp_node_t *
8541
8541
parse_targets(yp_parser_t *parser, yp_node_t *first_target, yp_binding_power_t binding_power) {
8542
- yp_token_t operator = not_provided(parser);
8543
-
8544
- // The first_target parameter can be NULL in the case that we're parsing a
8545
- // location that we know requires a multi write, as in the case of a for loop.
8546
- // In this case we will set up the parsing loop slightly differently.
8547
- if (first_target != NULL) {
8548
- first_target = parse_target(parser, first_target);
8549
-
8550
- if (!match1(parser, YP_TOKEN_COMMA)) {
8551
- return first_target;
8552
- }
8553
- }
8542
+ first_target = parse_target(parser, first_target);
8543
+ if (!match1(parser, YP_TOKEN_COMMA)) return first_target;
8554
8544
8555
8545
yp_multi_target_node_t *result = yp_multi_target_node_create(parser);
8556
- if (first_target != NULL) {
8557
- yp_multi_target_node_targets_append(result, first_target);
8558
- }
8559
-
8560
- bool has_splat = false;
8546
+ yp_multi_target_node_targets_append(result, first_target);
8547
+ bool has_splat = YP_NODE_TYPE_P(first_target, YP_SPLAT_NODE);
8561
8548
8562
- if (first_target == NULL || accept1(parser, YP_TOKEN_COMMA)) {
8563
- do {
8564
- if (accept1(parser, YP_TOKEN_USTAR)) {
8565
- // Here we have a splat operator. It can have a name or be anonymous. It
8566
- // can be the final target or be in the middle if there haven't been any
8567
- // others yet.
8568
-
8569
- if (has_splat) {
8570
- yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, YP_ERR_MULTI_ASSIGN_MULTI_SPLATS);
8571
- }
8572
-
8573
- yp_token_t star_operator = parser->previous;
8574
- yp_node_t *name = NULL;
8575
-
8576
- if (token_begins_expression_p(parser->current.type)) {
8577
- name = parse_expression(parser, binding_power, YP_ERR_EXPECT_EXPRESSION_AFTER_STAR);
8578
- name = parse_target(parser, name);
8579
- }
8580
-
8581
- yp_node_t *splat = (yp_node_t *) yp_splat_node_create(parser, &star_operator, name);
8582
- yp_multi_target_node_targets_append(result, splat);
8583
- has_splat = true;
8584
- } else if (accept1(parser, YP_TOKEN_PARENTHESIS_LEFT)) {
8585
- // Here we have a parenthesized list of targets. We'll recurse down into
8586
- // the parentheses by calling parse_targets again and then finish out
8587
- // the node when it returns.
8588
-
8589
- yp_token_t lparen = parser->previous;
8590
- yp_node_t *first_child_target = parse_expression(parser, YP_BINDING_POWER_STATEMENT, YP_ERR_EXPECT_EXPRESSION_AFTER_LPAREN);
8591
- yp_node_t *child_target = parse_targets(parser, first_child_target, YP_BINDING_POWER_STATEMENT);
8592
-
8593
- expect1(parser, YP_TOKEN_PARENTHESIS_RIGHT, YP_ERR_EXPECT_RPAREN_AFTER_MULTI);
8594
- yp_token_t rparen = parser->previous;
8595
-
8596
- if (YP_NODE_TYPE_P(child_target, YP_MULTI_TARGET_NODE) && first_target == NULL && result->targets.size == 0) {
8597
- yp_node_destroy(parser, (yp_node_t *) result);
8598
- result = (yp_multi_target_node_t *) child_target;
8599
- result->base.location.start = lparen.start;
8600
- result->base.location.end = rparen.end;
8601
- result->lparen_loc = YP_LOCATION_TOKEN_VALUE(&lparen);
8602
- result->rparen_loc = YP_LOCATION_TOKEN_VALUE(&rparen);
8603
- } else {
8604
- yp_multi_target_node_t *target;
8605
-
8606
- if (YP_NODE_TYPE_P(child_target, YP_MULTI_TARGET_NODE)) {
8607
- target = (yp_multi_target_node_t *) child_target;
8608
- } else {
8609
- target = yp_multi_target_node_create(parser);
8610
- yp_multi_target_node_targets_append(target, child_target);
8611
- }
8612
-
8613
- target->base.location.start = lparen.start;
8614
- target->base.location.end = rparen.end;
8615
- target->lparen_loc = YP_LOCATION_TOKEN_VALUE(&lparen);
8616
- target->rparen_loc = YP_LOCATION_TOKEN_VALUE(&rparen);
8549
+ while (accept1(parser, YP_TOKEN_COMMA)) {
8550
+ if (accept1(parser, YP_TOKEN_USTAR)) {
8551
+ // Here we have a splat operator. It can have a name or be
8552
+ // anonymous. It can be the final target or be in the middle if
8553
+ // there haven't been any others yet.
8554
+ if (has_splat) {
8555
+ yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, YP_ERR_MULTI_ASSIGN_MULTI_SPLATS);
8556
+ }
8617
8557
8618
- yp_multi_target_node_targets_append(result, (yp_node_t *) target);
8619
- }
8620
- } else {
8621
- if (!token_begins_expression_p(parser->current.type) && !match1(parser, YP_TOKEN_USTAR)) {
8622
- if (first_target == NULL && result->targets.size == 0) {
8623
- // If we get here, then we weren't able to parse anything at all, so
8624
- // we need to return a missing node.
8625
- yp_node_destroy(parser, (yp_node_t *) result);
8626
- yp_diagnostic_list_append(&parser->error_list, operator.start, operator.end, YP_ERR_FOR_INDEX);
8627
- return (yp_node_t *) yp_missing_node_create(parser, operator.start, operator.end);
8628
- }
8558
+ yp_token_t star_operator = parser->previous;
8559
+ yp_node_t *name = NULL;
8629
8560
8630
- // If we get here, then we have a trailing , in a multi write node.
8631
- // We need to indicate this somehow in the tree, so we'll add an
8632
- // anonymous splat.
8633
- yp_node_t *splat = (yp_node_t *) yp_splat_node_create(parser, &parser->previous, NULL);
8634
- yp_multi_target_node_targets_append(result, splat);
8635
- return (yp_node_t *) result;
8636
- }
8561
+ if (token_begins_expression_p(parser->current.type)) {
8562
+ name = parse_expression(parser, binding_power, YP_ERR_EXPECT_EXPRESSION_AFTER_STAR);
8563
+ name = parse_target(parser, name);
8564
+ }
8637
8565
8638
- yp_node_t *target = parse_expression(parser, binding_power, YP_ERR_EXPECT_EXPRESSION_AFTER_COMMA);
8639
- target = parse_target(parser, target);
8566
+ yp_node_t *splat = (yp_node_t *) yp_splat_node_create(parser, &star_operator, name);
8567
+ yp_multi_target_node_targets_append(result, splat);
8568
+ has_splat = true;
8569
+ } else if (token_begins_expression_p(parser->current.type)) {
8570
+ yp_node_t *target = parse_expression(parser, binding_power, YP_ERR_EXPECT_EXPRESSION_AFTER_COMMA);
8571
+ target = parse_target(parser, target);
8640
8572
8641
- yp_multi_target_node_targets_append(result, target);
8642
- }
8643
- } while (accept1(parser, YP_TOKEN_COMMA));
8573
+ yp_multi_target_node_targets_append(result, target);
8574
+ } else {
8575
+ // If we get here, then we have a trailing , in a multi target node.
8576
+ // We need to indicate this somehow in the tree, so we'll add an
8577
+ // anonymous splat.
8578
+ yp_node_t *splat = (yp_node_t *) yp_splat_node_create(parser, &parser->previous, NULL);
8579
+ yp_multi_target_node_targets_append(result, splat);
8580
+ break;
8581
+ }
8644
8582
}
8645
8583
8646
8584
return (yp_node_t *) result;
@@ -11301,7 +11239,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
11301
11239
// If we have a single statement and are ending on a right
11302
11240
// parenthesis, then we need to check if this is possibly a
11303
11241
// multiple target node.
11304
- if (binding_power == YP_BINDING_POWER_STATEMENT && YP_NODE_TYPE_P(statement, YP_MULTI_TARGET_NODE)) {
11242
+ if (YP_NODE_TYPE_P(statement, YP_MULTI_TARGET_NODE)) {
11305
11243
yp_multi_target_node_t *multi_target;
11306
11244
if (((yp_multi_target_node_t *) statement)->lparen_loc.start == NULL) {
11307
11245
multi_target = (yp_multi_target_node_t *) statement;
@@ -12368,8 +12306,29 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
12368
12306
case YP_TOKEN_KEYWORD_FOR: {
12369
12307
parser_lex(parser);
12370
12308
yp_token_t for_keyword = parser->previous;
12309
+ yp_node_t *index;
12310
+
12311
+ // First, parse out the first index expression.
12312
+ if (accept1(parser, YP_TOKEN_USTAR)) {
12313
+ yp_token_t star_operator = parser->previous;
12314
+ yp_node_t *name = NULL;
12315
+
12316
+ if (token_begins_expression_p(parser->current.type)) {
12317
+ name = parse_expression(parser, YP_BINDING_POWER_INDEX, YP_ERR_EXPECT_EXPRESSION_AFTER_STAR);
12318
+ name = parse_target(parser, name);
12319
+ }
12320
+
12321
+ index = (yp_node_t *) yp_splat_node_create(parser, &star_operator, name);
12322
+ } else if (token_begins_expression_p(parser->current.type)) {
12323
+ index = parse_expression(parser, YP_BINDING_POWER_INDEX, YP_ERR_EXPECT_EXPRESSION_AFTER_COMMA);
12324
+ } else {
12325
+ yp_diagnostic_list_append(&parser->error_list, for_keyword.start, for_keyword.end, YP_ERR_FOR_INDEX);
12326
+ index = (yp_node_t *) yp_missing_node_create(parser, for_keyword.start, for_keyword.end);
12327
+ }
12328
+
12329
+ // Now, if there are multiple index expressions, parse them out.
12330
+ index = parse_targets(parser, index, YP_BINDING_POWER_INDEX);
12371
12331
12372
- yp_node_t *index = parse_targets(parser, NULL, YP_BINDING_POWER_INDEX);
12373
12332
yp_do_loop_stack_push(parser, true);
12374
12333
12375
12334
expect1(parser, YP_TOKEN_KEYWORD_IN, YP_ERR_FOR_IN);
0 commit comments