@@ -450,48 +450,72 @@ yp_parser_optional_constant_id_token(yp_parser_t *parser, const yp_token_t *toke
450
450
return token->type == YP_TOKEN_NOT_PROVIDED ? 0 : yp_parser_constant_id_token(parser, token);
451
451
}
452
452
453
- // Mark any range nodes in this subtree as flipflops.
453
+ // The predicate of conditional nodes can change what would otherwise be regular
454
+ // nodes into specialized nodes. For example:
455
+ //
456
+ // if foo .. bar => RangeNode becomes FlipFlopNode
457
+ // if foo and bar .. baz => RangeNode becomes FlipFlopNode
458
+ // if /foo/ => RegularExpressionNode becomes MatchLastLineNode
459
+ // if /foo #{bar}/ => InterpolatedRegularExpressionNode becomes InterpolatedMatchLastLineNode
460
+ //
454
461
static void
455
- yp_flip_flop (yp_node_t *node) {
462
+ yp_conditional_predicate (yp_node_t *node) {
456
463
switch (YP_NODE_TYPE(node)) {
457
464
case YP_AND_NODE: {
458
465
yp_and_node_t *cast = (yp_and_node_t *) node;
459
- yp_flip_flop (cast->left);
460
- yp_flip_flop (cast->right);
466
+ yp_conditional_predicate (cast->left);
467
+ yp_conditional_predicate (cast->right);
461
468
break;
462
469
}
463
470
case YP_OR_NODE: {
464
471
yp_or_node_t *cast = (yp_or_node_t *) node;
465
- yp_flip_flop (cast->left);
466
- yp_flip_flop (cast->right);
472
+ yp_conditional_predicate (cast->left);
473
+ yp_conditional_predicate (cast->right);
467
474
break;
468
475
}
469
476
case YP_PARENTHESES_NODE: {
470
477
yp_parentheses_node_t *cast = (yp_parentheses_node_t *) node;
471
478
472
479
if ((cast->body != NULL) && YP_NODE_TYPE_P(cast->body, YP_STATEMENTS_NODE)) {
473
480
yp_statements_node_t *statements = (yp_statements_node_t *) cast->body;
474
- if (statements->body.size == 1) yp_flip_flop (statements->body.nodes[0]);
481
+ if (statements->body.size == 1) yp_conditional_predicate (statements->body.nodes[0]);
475
482
}
476
483
477
484
break;
478
485
}
479
486
case YP_RANGE_NODE: {
480
487
yp_range_node_t *cast = (yp_range_node_t *) node;
481
488
if (cast->left) {
482
- yp_flip_flop (cast->left);
489
+ yp_conditional_predicate (cast->left);
483
490
}
484
491
if (cast->right) {
485
- yp_flip_flop (cast->right);
492
+ yp_conditional_predicate (cast->right);
486
493
}
487
494
488
495
// Here we change the range node into a flip flop node. We can do
489
496
// this since the nodes are exactly the same except for the type.
497
+ // We're only asserting against the size when we should probably
498
+ // assert against the entire layout, but we'll assume tests will
499
+ // catch this.
490
500
assert(sizeof(yp_range_node_t) == sizeof(yp_flip_flop_node_t));
491
501
node->type = YP_FLIP_FLOP_NODE;
492
502
493
503
break;
494
504
}
505
+ case YP_REGULAR_EXPRESSION_NODE:
506
+ // Here we change the regular expression node into a match last line
507
+ // node. We can do this since the nodes are exactly the same except
508
+ // for the type.
509
+ assert(sizeof(yp_regular_expression_node_t) == sizeof(yp_match_last_line_node_t));
510
+ node->type = YP_MATCH_LAST_LINE_NODE;
511
+ break;
512
+ case YP_INTERPOLATED_REGULAR_EXPRESSION_NODE:
513
+ // Here we change the interpolated regular expression node into an
514
+ // interpolated match last line node. We can do this since the nodes
515
+ // are exactly the same except for the type.
516
+ assert(sizeof(yp_interpolated_regular_expression_node_t) == sizeof(yp_interpolated_match_last_line_node_t));
517
+ node->type = YP_INTERPOLATED_MATCH_LAST_LINE_NODE;
518
+ break;
495
519
default:
496
520
break;
497
521
}
@@ -2562,7 +2586,7 @@ yp_if_node_create(yp_parser_t *parser,
2562
2586
yp_node_t *consequent,
2563
2587
const yp_token_t *end_keyword
2564
2588
) {
2565
- yp_flip_flop (predicate);
2589
+ yp_conditional_predicate (predicate);
2566
2590
yp_if_node_t *node = YP_ALLOC_NODE(parser, yp_if_node_t);
2567
2591
2568
2592
const uint8_t *end;
@@ -2598,7 +2622,7 @@ yp_if_node_create(yp_parser_t *parser,
2598
2622
// Allocate and initialize new IfNode node in the modifier form.
2599
2623
static yp_if_node_t *
2600
2624
yp_if_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_token_t *if_keyword, yp_node_t *predicate) {
2601
- yp_flip_flop (predicate);
2625
+ yp_conditional_predicate (predicate);
2602
2626
yp_if_node_t *node = YP_ALLOC_NODE(parser, yp_if_node_t);
2603
2627
2604
2628
yp_statements_node_t *statements = yp_statements_node_create(parser);
@@ -2626,7 +2650,7 @@ yp_if_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_t
2626
2650
// Allocate and initialize an if node from a ternary expression.
2627
2651
static yp_if_node_t *
2628
2652
yp_if_node_ternary_create(yp_parser_t *parser, yp_node_t *predicate, yp_node_t *true_expression, const yp_token_t *colon, yp_node_t *false_expression) {
2629
- yp_flip_flop (predicate);
2653
+ yp_conditional_predicate (predicate);
2630
2654
2631
2655
yp_statements_node_t *if_statements = yp_statements_node_create(parser);
2632
2656
yp_statements_node_body_append(if_statements, true_expression);
@@ -4326,7 +4350,7 @@ yp_undef_node_append(yp_undef_node_t *node, yp_node_t *name) {
4326
4350
// Allocate a new UnlessNode node.
4327
4351
static yp_unless_node_t *
4328
4352
yp_unless_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *predicate, yp_statements_node_t *statements) {
4329
- yp_flip_flop (predicate);
4353
+ yp_conditional_predicate (predicate);
4330
4354
yp_unless_node_t *node = YP_ALLOC_NODE(parser, yp_unless_node_t);
4331
4355
4332
4356
const uint8_t *end;
@@ -4358,7 +4382,7 @@ yp_unless_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t
4358
4382
// Allocate and initialize new UnlessNode node in the modifier form.
4359
4383
static yp_unless_node_t *
4360
4384
yp_unless_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_token_t *unless_keyword, yp_node_t *predicate) {
4361
- yp_flip_flop (predicate);
4385
+ yp_conditional_predicate (predicate);
4362
4386
yp_unless_node_t *node = YP_ALLOC_NODE(parser, yp_unless_node_t);
4363
4387
4364
4388
yp_statements_node_t *statements = yp_statements_node_create(parser);
@@ -12027,7 +12051,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
12027
12051
arguments.closing_loc = YP_LOCATION_TOKEN_VALUE(&parser->previous);
12028
12052
} else {
12029
12053
receiver = parse_expression(parser, YP_BINDING_POWER_COMPOSITION, YP_ERR_NOT_EXPRESSION);
12030
- yp_flip_flop (receiver);
12054
+ yp_conditional_predicate (receiver);
12031
12055
12032
12056
if (!parser->recovering) {
12033
12057
accept(parser, YP_TOKEN_NEWLINE);
@@ -12037,7 +12061,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
12037
12061
}
12038
12062
} else {
12039
12063
receiver = parse_expression(parser, YP_BINDING_POWER_DEFINED, YP_ERR_NOT_EXPRESSION);
12040
- yp_flip_flop (receiver);
12064
+ yp_conditional_predicate (receiver);
12041
12065
}
12042
12066
12043
12067
return (yp_node_t *) yp_call_node_not_create(parser, receiver, &message, &arguments);
@@ -12633,7 +12657,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
12633
12657
yp_node_t *receiver = parse_expression(parser, yp_binding_powers[parser->previous.type].right, YP_ERR_UNARY_RECEIVER_BANG);
12634
12658
yp_call_node_t *node = yp_call_node_unary_create(parser, &operator, receiver, "!");
12635
12659
12636
- yp_flip_flop (receiver);
12660
+ yp_conditional_predicate (receiver);
12637
12661
return (yp_node_t *) node;
12638
12662
}
12639
12663
case YP_TOKEN_TILDE: {
0 commit comments