yarp 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/src/yarp.c CHANGED
@@ -450,8 +450,8 @@ yp_flip_flop(yp_node_t *node) {
450
450
  case YP_NODE_PARENTHESES_NODE: {
451
451
  yp_parentheses_node_t *cast = (yp_parentheses_node_t *) node;
452
452
 
453
- if ((cast->statements != NULL) && YP_NODE_TYPE_P(cast->statements, YP_NODE_STATEMENTS_NODE)) {
454
- yp_statements_node_t *statements = (yp_statements_node_t *) cast->statements;
453
+ if ((cast->body != NULL) && YP_NODE_TYPE_P(cast->body, YP_NODE_STATEMENTS_NODE)) {
454
+ yp_statements_node_t *statements = (yp_statements_node_t *) cast->body;
455
455
  if (statements->body.size == 1) yp_flip_flop(statements->body.nodes[0]);
456
456
  }
457
457
 
@@ -459,8 +459,12 @@ yp_flip_flop(yp_node_t *node) {
459
459
  }
460
460
  case YP_NODE_RANGE_NODE: {
461
461
  yp_range_node_t *cast = (yp_range_node_t *) node;
462
- yp_flip_flop(cast->left);
463
- yp_flip_flop(cast->right);
462
+ if (cast->left) {
463
+ yp_flip_flop(cast->left);
464
+ }
465
+ if (cast->right) {
466
+ yp_flip_flop(cast->right);
467
+ }
464
468
 
465
469
  // Here we change the range node into a flip flop node. We can do
466
470
  // this since the nodes are exactly the same except for the type.
@@ -654,6 +658,27 @@ yp_and_node_create(yp_parser_t *parser, yp_node_t *left, const yp_token_t *opera
654
658
  return node;
655
659
  }
656
660
 
661
+ // Allocate and initialize a new AndWriteNode.
662
+ static yp_and_write_node_t *
663
+ yp_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
664
+ yp_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_and_write_node_t);
665
+
666
+ *node = (yp_and_write_node_t) {
667
+ {
668
+ .type = YP_NODE_AND_WRITE_NODE,
669
+ .location = {
670
+ .start = target->location.start,
671
+ .end = value->location.end
672
+ },
673
+ },
674
+ .target = target,
675
+ .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
676
+ .value = value
677
+ };
678
+
679
+ return node;
680
+ }
681
+
657
682
  // Allocate an initialize a new arguments node.
658
683
  static yp_arguments_node_t *
659
684
  yp_arguments_node_create(yp_parser_t *parser) {
@@ -993,7 +1018,7 @@ yp_block_argument_node_create(yp_parser_t *parser, const yp_token_t *operator, y
993
1018
 
994
1019
  // Allocate and initialize a new BlockNode node.
995
1020
  static yp_block_node_t *
996
- yp_block_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *opening, yp_block_parameters_node_t *parameters, yp_node_t *statements, const yp_token_t *closing) {
1021
+ yp_block_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *opening, yp_block_parameters_node_t *parameters, yp_node_t *body, const yp_token_t *closing) {
997
1022
  yp_block_node_t *node = YP_ALLOC_NODE(parser, yp_block_node_t);
998
1023
 
999
1024
  *node = (yp_block_node_t) {
@@ -1003,7 +1028,7 @@ yp_block_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const y
1003
1028
  },
1004
1029
  .locals = *locals,
1005
1030
  .parameters = parameters,
1006
- .statements = statements,
1031
+ .body = body,
1007
1032
  .opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
1008
1033
  .closing_loc = YP_LOCATION_TOKEN_VALUE(closing)
1009
1034
  };
@@ -1461,7 +1486,7 @@ yp_case_node_end_keyword_loc_set(yp_case_node_t *node, const yp_token_t *end_key
1461
1486
 
1462
1487
  // Allocate a new ClassNode node.
1463
1488
  static yp_class_node_t *
1464
- yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, yp_node_t *constant_path, const yp_token_t *inheritance_operator, yp_node_t *superclass, yp_node_t *statements, const yp_token_t *end_keyword) {
1489
+ yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, yp_node_t *constant_path, const yp_token_t *inheritance_operator, yp_node_t *superclass, yp_node_t *body, const yp_token_t *end_keyword) {
1465
1490
  yp_class_node_t *node = YP_ALLOC_NODE(parser, yp_class_node_t);
1466
1491
 
1467
1492
  *node = (yp_class_node_t) {
@@ -1474,81 +1499,13 @@ yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const y
1474
1499
  .constant_path = constant_path,
1475
1500
  .inheritance_operator_loc = YP_OPTIONAL_LOCATION_TOKEN_VALUE(inheritance_operator),
1476
1501
  .superclass = superclass,
1477
- .statements = statements,
1502
+ .body = body,
1478
1503
  .end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword)
1479
1504
  };
1480
1505
 
1481
1506
  return node;
1482
1507
  }
1483
1508
 
1484
- // Allocate and initialize a new ClassVariableOperatorAndWriteNode node.
1485
- static yp_class_variable_operator_and_write_node_t *
1486
- yp_class_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1487
- assert(YP_NODE_TYPE_P(target, YP_NODE_CLASS_VARIABLE_READ_NODE));
1488
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
1489
- yp_class_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_class_variable_operator_and_write_node_t);
1490
-
1491
- *node = (yp_class_variable_operator_and_write_node_t) {
1492
- {
1493
- .type = YP_NODE_CLASS_VARIABLE_OPERATOR_AND_WRITE_NODE,
1494
- .location = {
1495
- .start = target->location.start,
1496
- .end = value->location.end
1497
- }
1498
- },
1499
- .name_loc = target->location,
1500
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1501
- .value = value
1502
- };
1503
-
1504
- return node;
1505
- }
1506
-
1507
- // Allocate and initialize a new ClassVariableOperatorWriteNode node.
1508
- static yp_class_variable_operator_write_node_t *
1509
- yp_class_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1510
- yp_class_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_class_variable_operator_write_node_t);
1511
-
1512
- *node = (yp_class_variable_operator_write_node_t) {
1513
- {
1514
- .type = YP_NODE_CLASS_VARIABLE_OPERATOR_WRITE_NODE,
1515
- .location = {
1516
- .start = target->location.start,
1517
- .end = value->location.end
1518
- }
1519
- },
1520
- .name_loc = target->location,
1521
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1522
- .value = value,
1523
- .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
1524
- };
1525
-
1526
- return node;
1527
- }
1528
-
1529
- // Allocate and initialize a new ClassVariableOperatorOrWriteNode node.
1530
- static yp_class_variable_operator_or_write_node_t *
1531
- yp_class_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1532
- assert(YP_NODE_TYPE_P(target, YP_NODE_CLASS_VARIABLE_READ_NODE));
1533
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
1534
- yp_class_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_class_variable_operator_or_write_node_t);
1535
-
1536
- *node = (yp_class_variable_operator_or_write_node_t) {
1537
- {
1538
- .type = YP_NODE_CLASS_VARIABLE_OPERATOR_OR_WRITE_NODE,
1539
- .location = {
1540
- .start = target->location.start,
1541
- .end = value->location.end
1542
- }
1543
- },
1544
- .name_loc = target->location,
1545
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1546
- .value = value
1547
- };
1548
-
1549
- return node;
1550
- }
1551
-
1552
1509
  // Allocate and initialize a new ClassVariableReadNode node.
1553
1510
  static yp_class_variable_read_node_t *
1554
1511
  yp_class_variable_read_node_create(yp_parser_t *parser, const yp_token_t *token) {
@@ -1579,72 +1536,6 @@ yp_class_variable_read_node_to_class_variable_write_node(yp_parser_t *parser, yp
1579
1536
  return node;
1580
1537
  }
1581
1538
 
1582
- // Allocate and initialize a new ConstantPathOperatorAndWriteNode node.
1583
- static yp_constant_path_operator_and_write_node_t *
1584
- yp_constant_path_operator_and_write_node_create(yp_parser_t *parser, yp_constant_path_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1585
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
1586
- yp_constant_path_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_path_operator_and_write_node_t);
1587
-
1588
- *node = (yp_constant_path_operator_and_write_node_t) {
1589
- {
1590
- .type = YP_NODE_CONSTANT_PATH_OPERATOR_AND_WRITE_NODE,
1591
- .location = {
1592
- .start = target->base.location.start,
1593
- .end = value->location.end
1594
- }
1595
- },
1596
- .target = target,
1597
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1598
- .value = value
1599
- };
1600
-
1601
- return node;
1602
- }
1603
-
1604
- // Allocate and initialize a new ConstantPathOperatorWriteNode node.
1605
- static yp_constant_path_operator_write_node_t *
1606
- yp_constant_path_operator_write_node_create(yp_parser_t *parser, yp_constant_path_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1607
- yp_constant_path_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_path_operator_write_node_t);
1608
-
1609
- *node = (yp_constant_path_operator_write_node_t) {
1610
- {
1611
- .type = YP_NODE_CONSTANT_PATH_OPERATOR_WRITE_NODE,
1612
- .location = {
1613
- .start = target->base.location.start,
1614
- .end = value->location.end
1615
- }
1616
- },
1617
- .target = target,
1618
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1619
- .value = value,
1620
- .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
1621
- };
1622
-
1623
- return node;
1624
- }
1625
-
1626
- // Allocate and initialize a new ConstantPathOperatorOrWriteNode node.
1627
- static yp_constant_path_operator_or_write_node_t *
1628
- yp_constant_path_operator_or_write_node_create(yp_parser_t *parser, yp_constant_path_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1629
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
1630
- yp_constant_path_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_path_operator_or_write_node_t);
1631
-
1632
- *node = (yp_constant_path_operator_or_write_node_t) {
1633
- {
1634
- .type = YP_NODE_CONSTANT_PATH_OPERATOR_OR_WRITE_NODE,
1635
- .location = {
1636
- .start = target->base.location.start,
1637
- .end = value->location.end
1638
- }
1639
- },
1640
- .target = target,
1641
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1642
- .value = value
1643
- };
1644
-
1645
- return node;
1646
- }
1647
-
1648
1539
  // Allocate and initialize a new ConstantPathNode node.
1649
1540
  static yp_constant_path_node_t *
1650
1541
  yp_constant_path_node_create(yp_parser_t *parser, yp_node_t *parent, const yp_token_t *delimiter, yp_node_t *child) {
@@ -1687,74 +1578,6 @@ yp_constant_path_write_node_create(yp_parser_t *parser, yp_constant_path_node_t
1687
1578
  return node;
1688
1579
  }
1689
1580
 
1690
- // Allocate and initialize a new ConstantOperatorAndWriteNode node.
1691
- static yp_constant_operator_and_write_node_t *
1692
- yp_constant_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1693
- assert(YP_NODE_TYPE_P(target, YP_NODE_CONSTANT_READ_NODE));
1694
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
1695
- yp_constant_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_operator_and_write_node_t);
1696
-
1697
- *node = (yp_constant_operator_and_write_node_t) {
1698
- {
1699
- .type = YP_NODE_CONSTANT_OPERATOR_AND_WRITE_NODE,
1700
- .location = {
1701
- .start = target->location.start,
1702
- .end = value->location.end
1703
- }
1704
- },
1705
- .name_loc = target->location,
1706
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1707
- .value = value
1708
- };
1709
-
1710
- return node;
1711
- }
1712
-
1713
- // Allocate and initialize a new ConstantOperatorWriteNode node.
1714
- static yp_constant_operator_write_node_t *
1715
- yp_constant_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1716
- yp_constant_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_operator_write_node_t);
1717
-
1718
- *node = (yp_constant_operator_write_node_t) {
1719
- {
1720
- .type = YP_NODE_CONSTANT_OPERATOR_WRITE_NODE,
1721
- .location = {
1722
- .start = target->location.start,
1723
- .end = value->location.end
1724
- }
1725
- },
1726
- .name_loc = target->location,
1727
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1728
- .value = value,
1729
- .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
1730
- };
1731
-
1732
- return node;
1733
- }
1734
-
1735
- // Allocate and initialize a new ConstantOperatorOrWriteNode node.
1736
- static yp_constant_operator_or_write_node_t *
1737
- yp_constant_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
1738
- assert(YP_NODE_TYPE_P(target, YP_NODE_CONSTANT_READ_NODE));
1739
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
1740
- yp_constant_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_operator_or_write_node_t);
1741
-
1742
- *node = (yp_constant_operator_or_write_node_t) {
1743
- {
1744
- .type = YP_NODE_CONSTANT_OPERATOR_OR_WRITE_NODE,
1745
- .location = {
1746
- .start = target->location.start,
1747
- .end = value->location.end
1748
- }
1749
- },
1750
- .name_loc = target->location,
1751
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
1752
- .value = value
1753
- };
1754
-
1755
- return node;
1756
- }
1757
-
1758
1581
  // Allocate and initialize a new ConstantReadNode node.
1759
1582
  static yp_constant_read_node_t *
1760
1583
  yp_constant_read_node_create(yp_parser_t *parser, const yp_token_t *name) {
@@ -1793,7 +1616,7 @@ yp_def_node_create(
1793
1616
  const yp_token_t *name,
1794
1617
  yp_node_t *receiver,
1795
1618
  yp_parameters_node_t *parameters,
1796
- yp_node_t *statements,
1619
+ yp_node_t *body,
1797
1620
  yp_constant_id_list_t *locals,
1798
1621
  const yp_token_t *def_keyword,
1799
1622
  const yp_token_t *operator,
@@ -1806,7 +1629,7 @@ yp_def_node_create(
1806
1629
  const char *end;
1807
1630
 
1808
1631
  if (end_keyword->type == YP_TOKEN_NOT_PROVIDED) {
1809
- end = statements->location.end;
1632
+ end = body->location.end;
1810
1633
  } else {
1811
1634
  end = end_keyword->end;
1812
1635
  }
@@ -1819,7 +1642,7 @@ yp_def_node_create(
1819
1642
  .name_loc = YP_LOCATION_TOKEN_VALUE(name),
1820
1643
  .receiver = receiver,
1821
1644
  .parameters = parameters,
1822
- .statements = statements,
1645
+ .body = body,
1823
1646
  .locals = *locals,
1824
1647
  .def_keyword_loc = YP_LOCATION_TOKEN_VALUE(def_keyword),
1825
1648
  .operator_loc = YP_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
@@ -2189,74 +2012,6 @@ yp_hash_pattern_node_node_list_create(yp_parser_t *parser, yp_node_list_t *assoc
2189
2012
  return node;
2190
2013
  }
2191
2014
 
2192
- // Allocate and initialize a new GlobalVariableOperatorAndWriteNode node.
2193
- static yp_global_variable_operator_and_write_node_t *
2194
- yp_global_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2195
- assert(YP_NODE_TYPE_P(target, YP_NODE_GLOBAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_BACK_REFERENCE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_NUMBERED_REFERENCE_READ_NODE));
2196
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
2197
- yp_global_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_global_variable_operator_and_write_node_t);
2198
-
2199
- *node = (yp_global_variable_operator_and_write_node_t) {
2200
- {
2201
- .type = YP_NODE_GLOBAL_VARIABLE_OPERATOR_AND_WRITE_NODE,
2202
- .location = {
2203
- .start = target->location.start,
2204
- .end = value->location.end
2205
- }
2206
- },
2207
- .name_loc = target->location,
2208
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2209
- .value = value
2210
- };
2211
-
2212
- return node;
2213
- }
2214
-
2215
- // Allocate and initialize a new GlobalVariableOperatorWriteNode node.
2216
- static yp_global_variable_operator_write_node_t *
2217
- yp_global_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2218
- yp_global_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_global_variable_operator_write_node_t);
2219
-
2220
- *node = (yp_global_variable_operator_write_node_t) {
2221
- {
2222
- .type = YP_NODE_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE,
2223
- .location = {
2224
- .start = target->location.start,
2225
- .end = value->location.end
2226
- }
2227
- },
2228
- .name_loc = target->location,
2229
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2230
- .value = value,
2231
- .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
2232
- };
2233
-
2234
- return node;
2235
- }
2236
-
2237
- // Allocate and initialize a new GlobalVariableOperatorOrWriteNode node.
2238
- static yp_global_variable_operator_or_write_node_t *
2239
- yp_global_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2240
- assert(YP_NODE_TYPE_P(target, YP_NODE_GLOBAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_BACK_REFERENCE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_NUMBERED_REFERENCE_READ_NODE));
2241
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
2242
- yp_global_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_global_variable_operator_or_write_node_t);
2243
-
2244
- *node = (yp_global_variable_operator_or_write_node_t) {
2245
- {
2246
- .type = YP_NODE_GLOBAL_VARIABLE_OPERATOR_OR_WRITE_NODE,
2247
- .location = {
2248
- .start = target->location.start,
2249
- .end = value->location.end
2250
- }
2251
- },
2252
- .name_loc = target->location,
2253
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2254
- .value = value
2255
- };
2256
-
2257
- return node;
2258
- }
2259
-
2260
2015
  // Allocate a new GlobalVariableReadNode node.
2261
2016
  static yp_global_variable_read_node_t *
2262
2017
  yp_global_variable_read_node_create(yp_parser_t *parser, const yp_token_t *name) {
@@ -2547,74 +2302,6 @@ yp_in_node_create(yp_parser_t *parser, yp_node_t *pattern, yp_statements_node_t
2547
2302
  return node;
2548
2303
  }
2549
2304
 
2550
- // Allocate and initialize a new InstanceVariableOperatorAndWriteNode node.
2551
- static yp_instance_variable_operator_and_write_node_t *
2552
- yp_instance_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2553
- assert(YP_NODE_TYPE_P(target, YP_NODE_INSTANCE_VARIABLE_READ_NODE));
2554
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
2555
- yp_instance_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_instance_variable_operator_and_write_node_t);
2556
-
2557
- *node = (yp_instance_variable_operator_and_write_node_t) {
2558
- {
2559
- .type = YP_NODE_INSTANCE_VARIABLE_OPERATOR_AND_WRITE_NODE,
2560
- .location = {
2561
- .start = target->location.start,
2562
- .end = value->location.end
2563
- }
2564
- },
2565
- .name_loc = target->location,
2566
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2567
- .value = value
2568
- };
2569
-
2570
- return node;
2571
- }
2572
-
2573
- // Allocate and initialize a new InstanceVariableOperatorWriteNode node.
2574
- static yp_instance_variable_operator_write_node_t *
2575
- yp_instance_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2576
- yp_instance_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_instance_variable_operator_write_node_t);
2577
-
2578
- *node = (yp_instance_variable_operator_write_node_t) {
2579
- {
2580
- .type = YP_NODE_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE,
2581
- .location = {
2582
- .start = target->location.start,
2583
- .end = value->location.end
2584
- }
2585
- },
2586
- .name_loc = target->location,
2587
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2588
- .value = value,
2589
- .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
2590
- };
2591
-
2592
- return node;
2593
- }
2594
-
2595
- // Allocate and initialize a new InstanceVariableOperatorOrWriteNode node.
2596
- static yp_instance_variable_operator_or_write_node_t *
2597
- yp_instance_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2598
- assert(YP_NODE_TYPE_P(target, YP_NODE_INSTANCE_VARIABLE_READ_NODE));
2599
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
2600
- yp_instance_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_instance_variable_operator_or_write_node_t);
2601
-
2602
- *node = (yp_instance_variable_operator_or_write_node_t) {
2603
- {
2604
- .type = YP_NODE_INSTANCE_VARIABLE_OPERATOR_OR_WRITE_NODE,
2605
- .location = {
2606
- .start = target->location.start,
2607
- .end = value->location.end
2608
- }
2609
- },
2610
- .name_loc = target->location,
2611
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2612
- .value = value
2613
- };
2614
-
2615
- return node;
2616
- }
2617
-
2618
2305
  // Allocate and initialize a new InstanceVariableReadNode node.
2619
2306
  static yp_instance_variable_read_node_t *
2620
2307
  yp_instance_variable_read_node_create(yp_parser_t *parser, const yp_token_t *token) {
@@ -2706,6 +2393,10 @@ yp_interpolated_string_node_create(yp_parser_t *parser, const yp_token_t *openin
2706
2393
  // Append a part to an InterpolatedStringNode node.
2707
2394
  static inline void
2708
2395
  yp_interpolated_string_node_append(yp_interpolated_string_node_t *node, yp_node_t *part) {
2396
+ if (node->parts.size == 0 && node->opening_loc.start == NULL) {
2397
+ node->base.location.start = part->location.start;
2398
+ }
2399
+
2709
2400
  yp_node_list_append(&node->parts, part);
2710
2401
  node->base.location.end = part->location.end;
2711
2402
  }
@@ -2862,7 +2553,7 @@ yp_lambda_node_create(
2862
2553
  yp_constant_id_list_t *locals,
2863
2554
  const yp_token_t *opening,
2864
2555
  yp_block_parameters_node_t *parameters,
2865
- yp_node_t *statements,
2556
+ yp_node_t *body,
2866
2557
  const yp_token_t *closing
2867
2558
  ) {
2868
2559
  yp_lambda_node_t *node = YP_ALLOC_NODE(parser, yp_lambda_node_t);
@@ -2878,78 +2569,7 @@ yp_lambda_node_create(
2878
2569
  .locals = *locals,
2879
2570
  .opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
2880
2571
  .parameters = parameters,
2881
- .statements = statements
2882
- };
2883
-
2884
- return node;
2885
- }
2886
-
2887
- // Allocate and initialize a new LocalVariableOperatorAndWriteNode node.
2888
- static yp_local_variable_operator_and_write_node_t *
2889
- yp_local_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value, yp_constant_id_t constant_id) {
2890
- assert(YP_NODE_TYPE_P(target, YP_NODE_LOCAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_CALL_NODE));
2891
- assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
2892
- yp_local_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_local_variable_operator_and_write_node_t);
2893
-
2894
- *node = (yp_local_variable_operator_and_write_node_t) {
2895
- {
2896
- .type = YP_NODE_LOCAL_VARIABLE_OPERATOR_AND_WRITE_NODE,
2897
- .location = {
2898
- .start = target->location.start,
2899
- .end = value->location.end
2900
- }
2901
- },
2902
- .name_loc = target->location,
2903
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2904
- .value = value,
2905
- .constant_id = constant_id
2906
- };
2907
-
2908
- return node;
2909
- }
2910
-
2911
- // Allocate and initialize a new LocalVariableOperatorWriteNode node.
2912
- static yp_local_variable_operator_write_node_t *
2913
- yp_local_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value, yp_constant_id_t constant_id) {
2914
- yp_local_variable_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_local_variable_operator_write_node_t);
2915
-
2916
- *node = (yp_local_variable_operator_write_node_t) {
2917
- {
2918
- .type = YP_NODE_LOCAL_VARIABLE_OPERATOR_WRITE_NODE,
2919
- .location = {
2920
- .start = target->location.start,
2921
- .end = value->location.end
2922
- }
2923
- },
2924
- .name_loc = target->location,
2925
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2926
- .value = value,
2927
- .constant_id = constant_id,
2928
- .operator_id = yp_parser_constant_id_location(parser, operator->start, operator->end - 1)
2929
- };
2930
-
2931
- return node;
2932
- }
2933
-
2934
- // Allocate and initialize a new LocalVariableOperatorOrWriteNode node.
2935
- static yp_local_variable_operator_or_write_node_t *
2936
- yp_local_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value, yp_constant_id_t constant_id) {
2937
- assert(YP_NODE_TYPE_P(target, YP_NODE_LOCAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_CALL_NODE));
2938
- assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL);
2939
- yp_local_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_local_variable_operator_or_write_node_t);
2940
-
2941
- *node = (yp_local_variable_operator_or_write_node_t) {
2942
- {
2943
- .type = YP_NODE_LOCAL_VARIABLE_OPERATOR_OR_WRITE_NODE,
2944
- .location = {
2945
- .start = target->location.start,
2946
- .end = value->location.end
2947
- }
2948
- },
2949
- .name_loc = target->location,
2950
- .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2951
- .value = value,
2952
- .constant_id = constant_id
2572
+ .body = body
2953
2573
  };
2954
2574
 
2955
2575
  return node;
@@ -3059,7 +2679,7 @@ yp_match_required_node_create(yp_parser_t *parser, yp_node_t *value, yp_node_t *
3059
2679
 
3060
2680
  // Allocate a new ModuleNode node.
3061
2681
  static yp_module_node_t *
3062
- yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *module_keyword, yp_node_t *constant_path, yp_node_t *statements, const yp_token_t *end_keyword) {
2682
+ yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *module_keyword, yp_node_t *constant_path, yp_node_t *body, const yp_token_t *end_keyword) {
3063
2683
  yp_module_node_t *node = YP_ALLOC_NODE(parser, yp_module_node_t);
3064
2684
 
3065
2685
  *node = (yp_module_node_t) {
@@ -3073,7 +2693,7 @@ yp_module_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const
3073
2693
  .locals = (locals == NULL ? ((yp_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals),
3074
2694
  .module_keyword_loc = YP_LOCATION_TOKEN_VALUE(module_keyword),
3075
2695
  .constant_path = constant_path,
3076
- .statements = statements,
2696
+ .body = body,
3077
2697
  .end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword)
3078
2698
  };
3079
2699
 
@@ -3188,6 +2808,28 @@ yp_numbered_reference_read_node_create(yp_parser_t *parser, const yp_token_t *na
3188
2808
  return node;
3189
2809
  }
3190
2810
 
2811
+ // Allocate and initialize a new OperatorWriteNode.
2812
+ static yp_operator_write_node_t *
2813
+ yp_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2814
+ yp_operator_write_node_t *node = YP_ALLOC_NODE(parser, yp_operator_write_node_t);
2815
+
2816
+ *node = (yp_operator_write_node_t) {
2817
+ {
2818
+ .type = YP_NODE_OPERATOR_WRITE_NODE,
2819
+ .location = {
2820
+ .start = target->location.start,
2821
+ .end = value->location.end
2822
+ },
2823
+ },
2824
+ .target = target,
2825
+ .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2826
+ .operator = yp_parser_constant_id_location(parser, operator->start, operator->end - 1),
2827
+ .value = value
2828
+ };
2829
+
2830
+ return node;
2831
+ }
2832
+
3191
2833
  // Allocate a new OptionalParameterNode node.
3192
2834
  static yp_optional_parameter_node_t *
3193
2835
  yp_optional_parameter_node_create(yp_parser_t *parser, const yp_token_t *name, const yp_token_t *operator, yp_node_t *value) {
@@ -3231,6 +2873,27 @@ yp_or_node_create(yp_parser_t *parser, yp_node_t *left, const yp_token_t *operat
3231
2873
  return node;
3232
2874
  }
3233
2875
 
2876
+ // Allocate and initialize a new OrWriteNode.
2877
+ static yp_or_write_node_t *
2878
+ yp_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) {
2879
+ yp_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_or_write_node_t);
2880
+
2881
+ *node = (yp_or_write_node_t) {
2882
+ {
2883
+ .type = YP_NODE_OR_WRITE_NODE,
2884
+ .location = {
2885
+ .start = target->location.start,
2886
+ .end = value->location.end
2887
+ },
2888
+ },
2889
+ .target = target,
2890
+ .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
2891
+ .value = value
2892
+ };
2893
+
2894
+ return node;
2895
+ }
2896
+
3234
2897
  // Allocate and initialize a new ParametersNode node.
3235
2898
  static yp_parameters_node_t *
3236
2899
  yp_parameters_node_create(yp_parser_t *parser) {
@@ -3343,7 +3006,7 @@ yp_program_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, yp_st
3343
3006
 
3344
3007
  // Allocate and initialize new ParenthesesNode node.
3345
3008
  static yp_parentheses_node_t *
3346
- yp_parentheses_node_create(yp_parser_t *parser, const yp_token_t *opening, yp_node_t *statements, const yp_token_t *closing) {
3009
+ yp_parentheses_node_create(yp_parser_t *parser, const yp_token_t *opening, yp_node_t *body, const yp_token_t *closing) {
3347
3010
  yp_parentheses_node_t *node = YP_ALLOC_NODE(parser, yp_parentheses_node_t);
3348
3011
 
3349
3012
  *node = (yp_parentheses_node_t) {
@@ -3354,7 +3017,7 @@ yp_parentheses_node_create(yp_parser_t *parser, const yp_token_t *opening, yp_no
3354
3017
  .end = closing->end
3355
3018
  }
3356
3019
  },
3357
- .statements = statements,
3020
+ .body = body,
3358
3021
  .opening_loc = YP_LOCATION_TOKEN_VALUE(opening),
3359
3022
  .closing_loc = YP_LOCATION_TOKEN_VALUE(closing)
3360
3023
  };
@@ -3700,7 +3363,7 @@ yp_self_node_create(yp_parser_t *parser, const yp_token_t *token) {
3700
3363
 
3701
3364
  // Allocate a new SingletonClassNode node.
3702
3365
  static yp_singleton_class_node_t *
3703
- yp_singleton_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, const yp_token_t *operator, yp_node_t *expression, yp_node_t *statements, const yp_token_t *end_keyword) {
3366
+ yp_singleton_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const yp_token_t *class_keyword, const yp_token_t *operator, yp_node_t *expression, yp_node_t *body, const yp_token_t *end_keyword) {
3704
3367
  yp_singleton_class_node_t *node = YP_ALLOC_NODE(parser, yp_singleton_class_node_t);
3705
3368
 
3706
3369
  *node = (yp_singleton_class_node_t) {
@@ -3715,7 +3378,7 @@ yp_singleton_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *local
3715
3378
  .class_keyword_loc = YP_LOCATION_TOKEN_VALUE(class_keyword),
3716
3379
  .operator_loc = YP_LOCATION_TOKEN_VALUE(operator),
3717
3380
  .expression = expression,
3718
- .statements = statements,
3381
+ .body = body,
3719
3382
  .end_keyword_loc = YP_LOCATION_TOKEN_VALUE(end_keyword)
3720
3383
  };
3721
3384
 
@@ -3934,10 +3597,10 @@ yp_symbol_node_label_create(yp_parser_t *parser, const yp_token_t *token) {
3934
3597
  yp_token_t label = { .type = YP_TOKEN_LABEL, .start = token->start, .end = token->end - 1 };
3935
3598
  node = yp_symbol_node_create(parser, &opening, &label, &closing);
3936
3599
 
3937
- ptrdiff_t length = label.end - label.start;
3938
- assert(length >= 0);
3600
+ assert((label.end - label.start) >= 0);
3601
+ yp_string_shared_init(&node->unescaped, label.start, label.end);
3939
3602
 
3940
- yp_unescape_manipulate_string(parser, label.start, (size_t) length, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list);
3603
+ yp_unescape_manipulate_string(parser, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list);
3941
3604
  break;
3942
3605
  }
3943
3606
  case YP_TOKEN_MISSING: {
@@ -5645,13 +5308,23 @@ parser_lex(yp_parser_t *parser) {
5645
5308
  break;
5646
5309
  case '\\':
5647
5310
  if (peek_at(parser, 1) == '\n') {
5648
- yp_newline_list_append(&parser->newline_list, parser->current.end + 1);
5649
- parser->current.end += 2;
5650
- space_seen = true;
5651
- } else if (parser->current.end + 2 < parser->end && peek_at(parser, 1) == '\r' && peek_at(parser, 2) == '\n') {
5652
- yp_newline_list_append(&parser->newline_list, parser->current.end + 2);
5653
- parser->current.end += 3;
5654
- space_seen = true;
5311
+ if (parser->heredoc_end) {
5312
+ parser->current.end = parser->heredoc_end;
5313
+ parser->heredoc_end = NULL;
5314
+ } else {
5315
+ yp_newline_list_append(&parser->newline_list, parser->current.end + 1);
5316
+ parser->current.end += 2;
5317
+ space_seen = true;
5318
+ }
5319
+ } else if (peek_at(parser, 1) == '\r' && peek_at(parser, 2) == '\n') {
5320
+ if (parser->heredoc_end) {
5321
+ parser->current.end = parser->heredoc_end;
5322
+ parser->heredoc_end = NULL;
5323
+ } else {
5324
+ yp_newline_list_append(&parser->newline_list, parser->current.end + 2);
5325
+ parser->current.end += 3;
5326
+ space_seen = true;
5327
+ }
5655
5328
  } else if (yp_char_is_inline_whitespace(*parser->current.end)) {
5656
5329
  parser->current.end += 2;
5657
5330
  } else {
@@ -6486,13 +6159,11 @@ parser_lex(yp_parser_t *parser) {
6486
6159
 
6487
6160
  // % %= %i %I %q %Q %w %W
6488
6161
  case '%': {
6489
- // In a BEG state, if you encounter a % then you must be
6490
- // starting something. In this case if there is no
6491
- // subsequent character then we have an invalid token. We're
6492
- // going to say it's the percent operator because we don't
6493
- // want to move into the string lex mode unnecessarily.
6494
- if (lex_state_beg_p(parser) && (parser->current.end >= parser->end)) {
6495
- yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, "unexpected end of input");
6162
+ // If there is no subsequent character then we have an invalid token. We're
6163
+ // going to say it's the percent operator because we don't want to move into the
6164
+ // string lex mode unnecessarily.
6165
+ if ((lex_state_beg_p(parser) || lex_state_arg_p(parser)) && (parser->current.end >= parser->end)) {
6166
+ yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, "Unexpected end of input");
6496
6167
  LEX(YP_TOKEN_PERCENT);
6497
6168
  }
6498
6169
 
@@ -6665,7 +6336,7 @@ parser_lex(yp_parser_t *parser) {
6665
6336
  ((parser->current.end - parser->current.start) == 7) &&
6666
6337
  current_token_starts_line(parser) &&
6667
6338
  (strncmp(parser->current.start, "__END__", 7) == 0) &&
6668
- (*parser->current.end == '\n' || (*parser->current.end == '\r' && parser->current.end[1] == '\n'))
6339
+ (parser->current.end == parser->end || *parser->current.end == '\n' || (*parser->current.end == '\r' && parser->current.end[1] == '\n'))
6669
6340
  ) {
6670
6341
  parser->current.end = parser->end;
6671
6342
  parser->current.type = YP_TOKEN___END__;
@@ -7082,6 +6753,7 @@ parser_lex(yp_parser_t *parser) {
7082
6753
  } else {
7083
6754
  parser->current.start = parser->next_start;
7084
6755
  parser->current.end = parser->next_start;
6756
+ parser->heredoc_end = NULL;
7085
6757
  parser->next_start = NULL;
7086
6758
  }
7087
6759
 
@@ -7203,11 +6875,16 @@ parser_lex(yp_parser_t *parser) {
7203
6875
  break;
7204
6876
  }
7205
6877
  case '\\': {
7206
- // If we hit escapes, then we need to treat the next token
7207
- // literally. In this case we'll skip past the next character and
7208
- // find the next breakpoint.
7209
- if (breakpoint[1] == '\n') {
6878
+ // If we hit an escape, then we need to skip past
6879
+ // however many characters the escape takes up. However
6880
+ // it's important that if \n or \r\n are escaped that we
6881
+ // stop looping before the newline and not after the
6882
+ // newline so that we can still potentially find the
6883
+ // terminator of the heredoc.
6884
+ if (breakpoint + 1 < parser->end && breakpoint[1] == '\n') {
7210
6885
  breakpoint++;
6886
+ } else if (breakpoint + 2 < parser->end && breakpoint[1] == '\r' && breakpoint[2] == '\n') {
6887
+ breakpoint += 2;
7211
6888
  } else {
7212
6889
  yp_unescape_type_t unescape_type = (quote == YP_HEREDOC_QUOTE_SINGLE) ? YP_UNESCAPE_MINIMAL : YP_UNESCAPE_ALL;
7213
6890
  size_t difference = yp_unescape_calculate_difference(breakpoint, parser->end, unescape_type, false, &parser->error_list);
@@ -7218,6 +6895,7 @@ parser_lex(yp_parser_t *parser) {
7218
6895
 
7219
6896
  breakpoint = yp_strpbrk(parser, breakpoint + difference, breakpoints, parser->end - (breakpoint + difference));
7220
6897
  }
6898
+
7221
6899
  break;
7222
6900
  }
7223
6901
  case '#': {
@@ -7264,10 +6942,10 @@ static yp_regular_expression_node_t *
7264
6942
  yp_regular_expression_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) {
7265
6943
  yp_regular_expression_node_t *node = yp_regular_expression_node_create(parser, opening, content, closing);
7266
6944
 
7267
- ptrdiff_t length = content->end - content->start;
7268
- assert(length >= 0);
6945
+ assert((content->end - content->start) >= 0);
6946
+ yp_string_shared_init(&node->unescaped, content->start, content->end);
7269
6947
 
7270
- yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, unescape_type, &parser->error_list);
6948
+ yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list);
7271
6949
  return node;
7272
6950
  }
7273
6951
 
@@ -7275,10 +6953,10 @@ static yp_symbol_node_t *
7275
6953
  yp_symbol_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) {
7276
6954
  yp_symbol_node_t *node = yp_symbol_node_create(parser, opening, content, closing);
7277
6955
 
7278
- ptrdiff_t length = content->end - content->start;
7279
- assert(length >= 0);
6956
+ assert((content->end - content->start) >= 0);
6957
+ yp_string_shared_init(&node->unescaped, content->start, content->end);
7280
6958
 
7281
- yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, unescape_type, &parser->error_list);
6959
+ yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list);
7282
6960
  return node;
7283
6961
  }
7284
6962
 
@@ -7286,10 +6964,10 @@ static yp_string_node_t *
7286
6964
  yp_string_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) {
7287
6965
  yp_string_node_t *node = yp_string_node_create(parser, opening, content, closing);
7288
6966
 
7289
- ptrdiff_t length = content->end - content->start;
7290
- assert(length >= 0);
6967
+ assert((content->end - content->start) >= 0);
6968
+ yp_string_shared_init(&node->unescaped, content->start, content->end);
7291
6969
 
7292
- yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, unescape_type, &parser->error_list);
6970
+ yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list);
7293
6971
  return node;
7294
6972
  }
7295
6973
 
@@ -7297,10 +6975,10 @@ static yp_x_string_node_t *
7297
6975
  yp_xstring_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing) {
7298
6976
  yp_x_string_node_t *node = yp_xstring_node_create(parser, opening, content, closing);
7299
6977
 
7300
- ptrdiff_t length = content->end - content->start;
7301
- assert(length >= 0);
6978
+ assert((content->end - content->start) >= 0);
6979
+ yp_string_shared_init(&node->unescaped, content->start, content->end);
7302
6980
 
7303
- yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list);
6981
+ yp_unescape_manipulate_string(parser, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list);
7304
6982
  return node;
7305
6983
  }
7306
6984
 
@@ -8999,7 +8677,7 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) {
8999
8677
  }
9000
8678
 
9001
8679
  yp_token_t end_keyword = not_provided(parser);
9002
- yp_node_t *parent;
8680
+ yp_node_t *parent = NULL;
9003
8681
 
9004
8682
  switch (context) {
9005
8683
  case YP_CONTEXT_IF:
@@ -9009,7 +8687,6 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) {
9009
8687
  parent = (yp_node_t *) yp_unless_node_create(parser, &keyword, predicate, statements);
9010
8688
  break;
9011
8689
  default:
9012
- parent = NULL;
9013
8690
  assert(false && "unreachable");
9014
8691
  break;
9015
8692
  }
@@ -9055,50 +8732,49 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) {
9055
8732
  switch (context) {
9056
8733
  case YP_CONTEXT_IF:
9057
8734
  ((yp_if_node_t *) current)->consequent = (yp_node_t *) else_node;
9058
- // Recurse down if nodes setting the appropriate end location in
9059
- // all cases.
9060
- yp_node_t *recursing_node = parent;
9061
- bool recursing = true;
9062
-
9063
- while (recursing) {
9064
- switch (YP_NODE_TYPE(recursing_node)) {
9065
- case YP_NODE_IF_NODE:
9066
- yp_if_node_end_keyword_loc_set((yp_if_node_t *) recursing_node, &parser->previous);
9067
- recursing_node = ((yp_if_node_t *) recursing_node)->consequent;
9068
- break;
9069
- case YP_NODE_ELSE_NODE:
9070
- yp_else_node_end_keyword_loc_set((yp_else_node_t *) recursing_node, &parser->previous);
9071
- recursing = false;
9072
- break;
9073
- default: {
9074
- recursing = false;
9075
- break;
9076
- }
9077
- }
9078
- }
9079
8735
  break;
9080
8736
  case YP_CONTEXT_UNLESS:
9081
8737
  ((yp_unless_node_t *) parent)->consequent = else_node;
9082
- yp_unless_node_end_keyword_loc_set((yp_unless_node_t *) parent, &parser->previous);
9083
8738
  break;
9084
8739
  default:
9085
8740
  assert(false && "unreachable");
9086
8741
  break;
9087
8742
  }
9088
8743
  } else {
9089
- expect(parser, YP_TOKEN_KEYWORD_END, "Expected `end` to close `if` statement.");
8744
+ expect(parser, YP_TOKEN_KEYWORD_END, "Expected `end` to close conditional statement.");
8745
+ }
9090
8746
 
9091
- switch (context) {
9092
- case YP_CONTEXT_IF:
9093
- yp_if_node_end_keyword_loc_set((yp_if_node_t *) parent, &parser->previous);
9094
- break;
9095
- case YP_CONTEXT_UNLESS:
9096
- yp_unless_node_end_keyword_loc_set((yp_unless_node_t *) parent, &parser->previous);
9097
- break;
9098
- default:
9099
- assert(false && "unreachable");
9100
- break;
8747
+ // Set the appropriate end location for all of the nodes in the subtree.
8748
+ switch (context) {
8749
+ case YP_CONTEXT_IF: {
8750
+ yp_node_t *current = parent;
8751
+ bool recursing = true;
8752
+
8753
+ while (recursing) {
8754
+ switch (YP_NODE_TYPE(current)) {
8755
+ case YP_NODE_IF_NODE:
8756
+ yp_if_node_end_keyword_loc_set((yp_if_node_t *) current, &parser->previous);
8757
+ current = ((yp_if_node_t *) current)->consequent;
8758
+ recursing = current != NULL;
8759
+ break;
8760
+ case YP_NODE_ELSE_NODE:
8761
+ yp_else_node_end_keyword_loc_set((yp_else_node_t *) current, &parser->previous);
8762
+ recursing = false;
8763
+ break;
8764
+ default: {
8765
+ recursing = false;
8766
+ break;
8767
+ }
8768
+ }
8769
+ }
8770
+ break;
9101
8771
  }
8772
+ case YP_CONTEXT_UNLESS:
8773
+ yp_unless_node_end_keyword_loc_set((yp_unless_node_t *) parent, &parser->previous);
8774
+ break;
8775
+ default:
8776
+ assert(false && "unreachable");
8777
+ break;
9102
8778
  }
9103
8779
 
9104
8780
  return parent;
@@ -9172,7 +8848,12 @@ parse_string_part(yp_parser_t *parser) {
9172
8848
  yp_unescape_type_t unescape_type = YP_UNESCAPE_ALL;
9173
8849
 
9174
8850
  if (parser->lex_modes.current->mode == YP_LEX_HEREDOC) {
9175
- if (parser->lex_modes.current->as.heredoc.quote == YP_HEREDOC_QUOTE_SINGLE) {
8851
+ if (parser->lex_modes.current->as.heredoc.indent == YP_HEREDOC_INDENT_TILDE) {
8852
+ // If we're in a tilde heredoc, we want to unescape it later
8853
+ // because we don't want unescaped newlines to disappear
8854
+ // before we handle them in the dedent.
8855
+ unescape_type = YP_UNESCAPE_NONE;
8856
+ } else if (parser->lex_modes.current->as.heredoc.quote == YP_HEREDOC_QUOTE_SINGLE) {
9176
8857
  unescape_type = YP_UNESCAPE_MINIMAL;
9177
8858
  }
9178
8859
  }
@@ -9545,14 +9226,30 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
9545
9226
  int common_whitespace;
9546
9227
  if ((common_whitespace = parse_heredoc_common_whitespace(parser, nodes)) <= 0) return;
9547
9228
 
9548
- // Iterate over all nodes, and trim whitespace accordingly.
9549
- for (size_t index = 0; index < nodes->size; index++) {
9550
- yp_node_t *node = nodes->nodes[index];
9551
- if (!YP_NODE_TYPE_P(node, YP_NODE_STRING_NODE)) continue;
9229
+ // The next node should be dedented if it's the first node in the list or if
9230
+ // if follows a string node.
9231
+ bool dedent_next = true;
9232
+
9233
+ // Iterate over all nodes, and trim whitespace accordingly. We're going to
9234
+ // keep around two indices: a read and a write. If we end up trimming all of
9235
+ // the whitespace from a node, then we'll drop it from the list entirely.
9236
+ size_t write_index = 0;
9237
+
9238
+ for (size_t read_index = 0; read_index < nodes->size; read_index++) {
9239
+ yp_node_t *node = nodes->nodes[read_index];
9240
+
9241
+ // We're not manipulating child nodes that aren't strings. In this case
9242
+ // we'll skip past it and indicate that the subsequent node should not
9243
+ // be dedented.
9244
+ if (!YP_NODE_TYPE_P(node, YP_NODE_STRING_NODE)) {
9245
+ nodes->nodes[write_index++] = node;
9246
+ dedent_next = false;
9247
+ continue;
9248
+ }
9552
9249
 
9553
9250
  // Get a reference to the string struct that is being held by the string
9554
9251
  // node. This is the value we're going to actual manipulate.
9555
- yp_string_t *string = &((yp_string_node_t *) node)->unescaped;
9252
+ yp_string_t *string = &(((yp_string_node_t *) node)->unescaped);
9556
9253
  yp_string_ensure_owned(string);
9557
9254
 
9558
9255
  // Now get the bounds of the existing string. We'll use this as a
@@ -9568,7 +9265,6 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
9568
9265
  // whitespace, so we'll maintain a pointer to the current position in the
9569
9266
  // string that we're writing to.
9570
9267
  char *dest_cursor = source_start;
9571
- bool dedent_next = (index == 0) || YP_NODE_TYPE_P(nodes->nodes[index - 1], YP_NODE_STRING_NODE);
9572
9268
 
9573
9269
  while (source_cursor < source_end) {
9574
9270
  // If we need to dedent the next element within the heredoc or the next
@@ -9613,8 +9309,20 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
9613
9309
  dedent_next = true;
9614
9310
  }
9615
9311
 
9616
- string->length = dest_length;
9312
+ // We only want to write this node into the list if it has any content.
9313
+ if (dest_length == 0) {
9314
+ yp_node_destroy(parser, node);
9315
+ } else {
9316
+ string->length = dest_length;
9317
+ yp_unescape_manipulate_string(parser, string, (quote == YP_HEREDOC_QUOTE_SINGLE) ? YP_UNESCAPE_MINIMAL : YP_UNESCAPE_ALL, &parser->error_list);
9318
+ nodes->nodes[write_index++] = node;
9319
+ }
9320
+
9321
+ // We always dedent the next node if it follows a string node.
9322
+ dedent_next = true;
9617
9323
  }
9324
+
9325
+ nodes->size = write_index;
9618
9326
  }
9619
9327
 
9620
9328
  static yp_node_t *
@@ -10673,12 +10381,15 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
10673
10381
 
10674
10382
  lex_state_set(parser, YP_LEX_STATE_END);
10675
10383
  expect(parser, YP_TOKEN_HEREDOC_END, "Expected a closing delimiter for heredoc.");
10384
+
10676
10385
  if (quote == YP_HEREDOC_QUOTE_BACKTICK) {
10677
10386
  assert(YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_X_STRING_NODE));
10678
10387
  yp_interpolated_xstring_node_closing_set(((yp_interpolated_x_string_node_t *) node), &parser->previous);
10388
+ node->location = ((yp_interpolated_x_string_node_t *) node)->opening_loc;
10679
10389
  } else {
10680
10390
  assert(YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_STRING_NODE));
10681
10391
  yp_interpolated_string_node_closing_set((yp_interpolated_string_node_t *) node, &parser->previous);
10392
+ node->location = ((yp_interpolated_string_node_t *) node)->opening_loc;
10682
10393
  }
10683
10394
 
10684
10395
  // If this is a heredoc that is indented with a ~, then we need to dedent
@@ -12394,14 +12105,19 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12394
12105
  case YP_NODE_NUMBERED_REFERENCE_READ_NODE:
12395
12106
  yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable");
12396
12107
  /* fallthrough */
12397
- case YP_NODE_GLOBAL_VARIABLE_READ_NODE: {
12108
+ case YP_NODE_CLASS_VARIABLE_READ_NODE:
12109
+ case YP_NODE_CONSTANT_PATH_NODE:
12110
+ case YP_NODE_CONSTANT_READ_NODE:
12111
+ case YP_NODE_GLOBAL_VARIABLE_READ_NODE:
12112
+ case YP_NODE_INSTANCE_VARIABLE_READ_NODE:
12113
+ case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12398
12114
  parser_lex(parser);
12399
12115
 
12400
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12401
- yp_node_t *result = (yp_node_t *) yp_global_variable_operator_and_write_node_create(parser, node, &token, value);
12116
+ yp_token_t operator = not_provided(parser);
12117
+ node = parse_target(parser, node, &operator, NULL);
12402
12118
 
12403
- yp_node_destroy(parser, node);
12404
- return result;
12119
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12120
+ return (yp_node_t *) yp_and_write_node_create(parser, node, &token, value);
12405
12121
  }
12406
12122
  case YP_NODE_CALL_NODE: {
12407
12123
  yp_call_node_t *call_node = (yp_call_node_t *) node;
@@ -12419,12 +12135,11 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12419
12135
 
12420
12136
  parser_lex(parser);
12421
12137
 
12422
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12423
- yp_constant_id_t constant_id = yp_parser_constant_id_location(parser, message_loc.start, message_loc.end);
12424
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_and_write_node_create(parser, node, &token, value, constant_id);
12138
+ yp_token_t operator = not_provided(parser);
12139
+ node = parse_target(parser, node, &operator, NULL);
12425
12140
 
12426
- yp_node_destroy(parser, node);
12427
- return result;
12141
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12142
+ return (yp_node_t *) yp_and_write_node_create(parser, node, &token, value);
12428
12143
  }
12429
12144
 
12430
12145
  parser_lex(parser);
@@ -12435,49 +12150,6 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12435
12150
  yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12436
12151
  return (yp_node_t *) yp_call_operator_and_write_node_create(parser, (yp_call_node_t *) node, &token, value);
12437
12152
  }
12438
- case YP_NODE_CLASS_VARIABLE_READ_NODE: {
12439
- parser_lex(parser);
12440
-
12441
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12442
- yp_node_t *result = (yp_node_t *) yp_class_variable_operator_and_write_node_create(parser, node, &token, value);
12443
-
12444
- yp_node_destroy(parser, node);
12445
- return result;
12446
- }
12447
- case YP_NODE_CONSTANT_PATH_NODE: {
12448
- parser_lex(parser);
12449
-
12450
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12451
- return (yp_node_t *) yp_constant_path_operator_and_write_node_create(parser, (yp_constant_path_node_t *) node, &token, value);
12452
- }
12453
- case YP_NODE_CONSTANT_READ_NODE: {
12454
- parser_lex(parser);
12455
-
12456
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12457
- yp_node_t *result = (yp_node_t *) yp_constant_operator_and_write_node_create(parser, node, &token, value);
12458
-
12459
- yp_node_destroy(parser, node);
12460
- return result;
12461
- }
12462
- case YP_NODE_INSTANCE_VARIABLE_READ_NODE: {
12463
- parser_lex(parser);
12464
-
12465
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12466
- yp_node_t *result = (yp_node_t *) yp_instance_variable_operator_and_write_node_create(parser, node, &token, value);
12467
-
12468
- yp_node_destroy(parser, node);
12469
- return result;
12470
- }
12471
- case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12472
- parser_lex(parser);
12473
-
12474
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12475
- yp_constant_id_t constant_id = ((yp_local_variable_read_node_t *) node)->constant_id;
12476
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_and_write_node_create(parser, node, &token, value, constant_id);
12477
-
12478
- yp_node_destroy(parser, node);
12479
- return result;
12480
- }
12481
12153
  case YP_NODE_MULTI_WRITE_NODE: {
12482
12154
  parser_lex(parser);
12483
12155
  yp_diagnostic_list_append(&parser->error_list, token.start, token.end, "Cannot use `&&=' on a multi-write.");
@@ -12499,14 +12171,19 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12499
12171
  case YP_NODE_NUMBERED_REFERENCE_READ_NODE:
12500
12172
  yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable");
12501
12173
  /* fallthrough */
12502
- case YP_NODE_GLOBAL_VARIABLE_READ_NODE: {
12174
+ case YP_NODE_CLASS_VARIABLE_READ_NODE:
12175
+ case YP_NODE_CONSTANT_PATH_NODE:
12176
+ case YP_NODE_CONSTANT_READ_NODE:
12177
+ case YP_NODE_GLOBAL_VARIABLE_READ_NODE:
12178
+ case YP_NODE_INSTANCE_VARIABLE_READ_NODE:
12179
+ case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12503
12180
  parser_lex(parser);
12504
12181
 
12505
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12506
- yp_node_t *result = (yp_node_t *) yp_global_variable_operator_or_write_node_create(parser, node, &token, value);
12182
+ yp_token_t operator = not_provided(parser);
12183
+ node = parse_target(parser, node, &operator, NULL);
12507
12184
 
12508
- yp_node_destroy(parser, node);
12509
- return result;
12185
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12186
+ return (yp_node_t *) yp_or_write_node_create(parser, node, &token, value);
12510
12187
  }
12511
12188
  case YP_NODE_CALL_NODE: {
12512
12189
  yp_call_node_t *call_node = (yp_call_node_t *) node;
@@ -12524,12 +12201,11 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12524
12201
 
12525
12202
  parser_lex(parser);
12526
12203
 
12527
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12528
- yp_constant_id_t constant_id = yp_parser_constant_id_location(parser, message_loc.start, message_loc.end);
12529
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_or_write_node_create(parser, node, &token, value, constant_id);
12204
+ yp_token_t operator = not_provided(parser);
12205
+ node = parse_target(parser, node, &operator, NULL);
12530
12206
 
12531
- yp_node_destroy(parser, node);
12532
- return result;
12207
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12208
+ return (yp_node_t *) yp_or_write_node_create(parser, node, &token, value);
12533
12209
  }
12534
12210
 
12535
12211
  parser_lex(parser);
@@ -12540,49 +12216,6 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12540
12216
  yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12541
12217
  return (yp_node_t *) yp_call_operator_or_write_node_create(parser, (yp_call_node_t *) node, &token, value);
12542
12218
  }
12543
- case YP_NODE_CLASS_VARIABLE_READ_NODE: {
12544
- parser_lex(parser);
12545
-
12546
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12547
- yp_node_t *result = (yp_node_t *) yp_class_variable_operator_or_write_node_create(parser, node, &token, value);
12548
-
12549
- yp_node_destroy(parser, node);
12550
- return result;
12551
- }
12552
- case YP_NODE_CONSTANT_PATH_NODE: {
12553
- parser_lex(parser);
12554
-
12555
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12556
- return (yp_node_t *) yp_constant_path_operator_or_write_node_create(parser, (yp_constant_path_node_t *) node, &token, value);
12557
- }
12558
- case YP_NODE_CONSTANT_READ_NODE: {
12559
- parser_lex(parser);
12560
-
12561
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12562
- yp_node_t *result = (yp_node_t *) yp_constant_operator_or_write_node_create(parser, node, &token, value);
12563
-
12564
- yp_node_destroy(parser, node);
12565
- return result;
12566
- }
12567
- case YP_NODE_INSTANCE_VARIABLE_READ_NODE: {
12568
- parser_lex(parser);
12569
-
12570
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12571
- yp_node_t *result = (yp_node_t *) yp_instance_variable_operator_or_write_node_create(parser, node, &token, value);
12572
-
12573
- yp_node_destroy(parser, node);
12574
- return result;
12575
- }
12576
- case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12577
- parser_lex(parser);
12578
-
12579
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||=");
12580
- yp_constant_id_t constant_id = ((yp_local_variable_read_node_t *) node)->constant_id;
12581
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_or_write_node_create(parser, node, &token, value, constant_id);
12582
-
12583
- yp_node_destroy(parser, node);
12584
- return result;
12585
- }
12586
12219
  case YP_NODE_MULTI_WRITE_NODE: {
12587
12220
  parser_lex(parser);
12588
12221
  yp_diagnostic_list_append(&parser->error_list, token.start, token.end, "Cannot use `||=' on a multi-write.");
@@ -12614,14 +12247,19 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12614
12247
  case YP_NODE_NUMBERED_REFERENCE_READ_NODE:
12615
12248
  yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable");
12616
12249
  /* fallthrough */
12617
- case YP_NODE_GLOBAL_VARIABLE_READ_NODE: {
12250
+ case YP_NODE_CLASS_VARIABLE_READ_NODE:
12251
+ case YP_NODE_CONSTANT_PATH_NODE:
12252
+ case YP_NODE_CONSTANT_READ_NODE:
12253
+ case YP_NODE_GLOBAL_VARIABLE_READ_NODE:
12254
+ case YP_NODE_INSTANCE_VARIABLE_READ_NODE:
12255
+ case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12618
12256
  parser_lex(parser);
12619
12257
 
12620
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator");
12621
- yp_node_t *result = (yp_node_t *) yp_global_variable_operator_write_node_create(parser, node, &token, value);
12258
+ yp_token_t operator = not_provided(parser);
12259
+ node = parse_target(parser, node, &operator, NULL);
12622
12260
 
12623
- yp_node_destroy(parser, node);
12624
- return result;
12261
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator");
12262
+ return (yp_node_t *) yp_operator_write_node_create(parser, node, &token, value);
12625
12263
  }
12626
12264
  case YP_NODE_CALL_NODE: {
12627
12265
  yp_call_node_t *call_node = (yp_call_node_t *) node;
@@ -12639,12 +12277,11 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12639
12277
 
12640
12278
  parser_lex(parser);
12641
12279
 
12642
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12643
- yp_constant_id_t constant_id = yp_parser_constant_id_location(parser, message_loc.start, message_loc.end);
12644
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_write_node_create(parser, node, &token, value, constant_id);
12280
+ yp_token_t operator = not_provided(parser);
12281
+ node = parse_target(parser, node, &operator, NULL);
12645
12282
 
12646
- yp_node_destroy(parser, node);
12647
- return result;
12283
+ yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&=");
12284
+ return (yp_node_t *) yp_operator_write_node_create(parser, node, &token, value);
12648
12285
  }
12649
12286
 
12650
12287
  yp_token_t operator = not_provided(parser);
@@ -12654,49 +12291,6 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
12654
12291
  yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12655
12292
  return (yp_node_t *) yp_call_operator_write_node_create(parser, (yp_call_node_t *) node, &token, value);
12656
12293
  }
12657
- case YP_NODE_CLASS_VARIABLE_READ_NODE: {
12658
- parser_lex(parser);
12659
-
12660
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12661
- yp_node_t *result = (yp_node_t *) yp_class_variable_operator_write_node_create(parser, node, &token, value);
12662
-
12663
- yp_node_destroy(parser, node);
12664
- return result;
12665
- }
12666
- case YP_NODE_CONSTANT_PATH_NODE: {
12667
- parser_lex(parser);
12668
-
12669
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12670
- return (yp_node_t *) yp_constant_path_operator_write_node_create(parser, (yp_constant_path_node_t *) node, &token, value);
12671
- }
12672
- case YP_NODE_CONSTANT_READ_NODE: {
12673
- parser_lex(parser);
12674
-
12675
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12676
- yp_node_t *result = (yp_node_t *) yp_constant_operator_write_node_create(parser, node, &token, value);
12677
-
12678
- yp_node_destroy(parser, node);
12679
- return result;
12680
- }
12681
- case YP_NODE_INSTANCE_VARIABLE_READ_NODE: {
12682
- parser_lex(parser);
12683
-
12684
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12685
- yp_node_t *result = (yp_node_t *) yp_instance_variable_operator_write_node_create(parser, node, &token, value);
12686
-
12687
- yp_node_destroy(parser, node);
12688
- return result;
12689
- }
12690
- case YP_NODE_LOCAL_VARIABLE_READ_NODE: {
12691
- parser_lex(parser);
12692
-
12693
- yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator.");
12694
- yp_constant_id_t constant_id = ((yp_local_variable_read_node_t *) node)->constant_id;
12695
- yp_node_t *result = (yp_node_t *) yp_local_variable_operator_write_node_create(parser, node, &token, value, constant_id);
12696
-
12697
- yp_node_destroy(parser, node);
12698
- return result;
12699
- }
12700
12294
  case YP_NODE_MULTI_WRITE_NODE: {
12701
12295
  parser_lex(parser);
12702
12296
  yp_diagnostic_list_append(&parser->error_list, token.start, token.end, "Unexpected operator.");
@@ -13190,6 +12784,8 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char
13190
12784
  .enclosure_nesting = 0,
13191
12785
  .lambda_enclosure_nesting = -1,
13192
12786
  .brace_nesting = 0,
12787
+ .do_loop_stack = YP_STATE_STACK_EMPTY,
12788
+ .accepts_block_stack = YP_STATE_STACK_EMPTY,
13193
12789
  .lex_modes = {
13194
12790
  .index = 0,
13195
12791
  .stack = {{ .mode = YP_LEX_DEFAULT }},
@@ -13201,6 +12797,9 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char
13201
12797
  .current = { .type = YP_TOKEN_EOF, .start = source, .end = source },
13202
12798
  .next_start = NULL,
13203
12799
  .heredoc_end = NULL,
12800
+ .comment_list = YP_LIST_EMPTY,
12801
+ .warning_list = YP_LIST_EMPTY,
12802
+ .error_list = YP_LIST_EMPTY,
13204
12803
  .current_scope = NULL,
13205
12804
  .current_context = NULL,
13206
12805
  .recovering = false,
@@ -13213,16 +12812,12 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char
13213
12812
  .pattern_matching_newlines = false,
13214
12813
  .in_keyword_arg = false,
13215
12814
  .filepath_string = filepath_string,
12815
+ .constant_pool = YP_CONSTANT_POOL_EMPTY,
12816
+ .newline_list = YP_NEWLINE_LIST_EMPTY
13216
12817
  };
13217
12818
 
13218
- yp_state_stack_init(&parser->do_loop_stack);
13219
- yp_state_stack_init(&parser->accepts_block_stack);
13220
12819
  yp_accepts_block_stack_push(parser, true);
13221
12820
 
13222
- yp_list_init(&parser->warning_list);
13223
- yp_list_init(&parser->error_list);
13224
- yp_list_init(&parser->comment_list);
13225
-
13226
12821
  // Initialize the constant pool. We're going to completely guess as to the
13227
12822
  // number of constants that we'll need based on the size of the input. The
13228
12823
  // ratio we chose here is actually less arbitrary than you might think.