prism 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/src/prism.c CHANGED
@@ -492,7 +492,8 @@ pm_parser_err(pm_parser_t *parser, const uint8_t *start, const uint8_t *end, pm_
492
492
  /**
493
493
  * Append an error to the list of errors on the parser using a format string.
494
494
  */
495
- #define PM_PARSER_ERR_FORMAT(parser, start, end, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, start, end, diag_id, __VA_ARGS__)
495
+ #define PM_PARSER_ERR_FORMAT(parser, start, end, diag_id, ...) \
496
+ pm_diagnostic_list_append_format(&parser->error_list, start, end, diag_id, __VA_ARGS__)
496
497
 
497
498
  /**
498
499
  * Append an error to the list of errors on the parser using the location of the
@@ -507,7 +508,8 @@ pm_parser_err_current(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
507
508
  * Append an error to the list of errors on the parser using the given location
508
509
  * using a format string.
509
510
  */
510
- #define PM_PARSER_ERR_LOCATION_FORMAT(parser, location, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, (location)->start, (location)->end, diag_id, __VA_ARGS__)
511
+ #define PM_PARSER_ERR_LOCATION_FORMAT(parser, location, diag_id, ...) \
512
+ PM_PARSER_ERR_FORMAT(parser, (location)->start, (location)->end, diag_id, __VA_ARGS__)
511
513
 
512
514
  /**
513
515
  * Append an error to the list of errors on the parser using the location of the
@@ -522,7 +524,15 @@ pm_parser_err_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id_
522
524
  * Append an error to the list of errors on the parser using the location of the
523
525
  * given node and a format string.
524
526
  */
525
- #define PM_PARSER_ERR_NODE_FORMAT(parser, node, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, node->location.start, node->location.end, diag_id, __VA_ARGS__)
527
+ #define PM_PARSER_ERR_NODE_FORMAT(parser, node, diag_id, ...) \
528
+ PM_PARSER_ERR_FORMAT(parser, (node)->location.start, (node)->location.end, diag_id, __VA_ARGS__)
529
+
530
+ /**
531
+ * Append an error to the list of errors on the parser using the location of the
532
+ * given node and a format string, and add on the content of the node.
533
+ */
534
+ #define PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, node, diag_id) \
535
+ PM_PARSER_ERR_NODE_FORMAT(parser, node, diag_id, (int) ((node)->location.end - (node)->location.start), (const char *) (node)->location.start)
526
536
 
527
537
  /**
528
538
  * Append an error to the list of errors on the parser using the location of the
@@ -546,7 +556,15 @@ pm_parser_err_token(pm_parser_t *parser, const pm_token_t *token, pm_diagnostic_
546
556
  * Append an error to the list of errors on the parser using the location of the
547
557
  * given token and a format string.
548
558
  */
549
- #define PM_PARSER_ERR_TOKEN_FORMAT(parser, token, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, (token).start, (token).end, diag_id, __VA_ARGS__)
559
+ #define PM_PARSER_ERR_TOKEN_FORMAT(parser, token, diag_id, ...) \
560
+ PM_PARSER_ERR_FORMAT(parser, (token).start, (token).end, diag_id, __VA_ARGS__)
561
+
562
+ /**
563
+ * Append an error to the list of errors on the parser using the location of the
564
+ * given token and a format string, and add on the content of the token.
565
+ */
566
+ #define PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, token, diag_id) \
567
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, token, diag_id, (int) ((token).end - (token).start), (const char *) (token).start)
550
568
 
551
569
  /**
552
570
  * Append a warning to the list of warnings on the parser.
@@ -2890,7 +2908,8 @@ pm_def_node_receiver_check(pm_parser_t *parser, const pm_node_t *node) {
2890
2908
  static pm_def_node_t *
2891
2909
  pm_def_node_create(
2892
2910
  pm_parser_t *parser,
2893
- const pm_token_t *name,
2911
+ pm_constant_id_t name,
2912
+ const pm_token_t *name_loc,
2894
2913
  pm_node_t *receiver,
2895
2914
  pm_parameters_node_t *parameters,
2896
2915
  pm_node_t *body,
@@ -2920,8 +2939,8 @@ pm_def_node_create(
2920
2939
  .type = PM_DEF_NODE,
2921
2940
  .location = { .start = def_keyword->start, .end = end },
2922
2941
  },
2923
- .name = pm_parser_constant_id_token(parser, name),
2924
- .name_loc = PM_LOCATION_TOKEN_VALUE(name),
2942
+ .name = name,
2943
+ .name_loc = PM_LOCATION_TOKEN_VALUE(name_loc),
2925
2944
  .receiver = receiver,
2926
2945
  .parameters = parameters,
2927
2946
  .body = body,
@@ -4642,13 +4661,20 @@ pm_multi_target_node_create(pm_parser_t *parser) {
4642
4661
  */
4643
4662
  static void
4644
4663
  pm_multi_target_node_targets_append(pm_parser_t *parser, pm_multi_target_node_t *node, pm_node_t *target) {
4645
- if (PM_NODE_TYPE_P(target, PM_SPLAT_NODE) || PM_NODE_TYPE_P(target, PM_IMPLICIT_REST_NODE)) {
4664
+ if (PM_NODE_TYPE_P(target, PM_SPLAT_NODE)) {
4646
4665
  if (node->rest == NULL) {
4647
4666
  node->rest = target;
4648
4667
  } else {
4649
4668
  pm_parser_err_node(parser, target, PM_ERR_MULTI_ASSIGN_MULTI_SPLATS);
4650
4669
  pm_node_list_append(&node->rights, target);
4651
4670
  }
4671
+ } else if (PM_NODE_TYPE_P(target, PM_IMPLICIT_REST_NODE)) {
4672
+ if (node->rest == NULL) {
4673
+ node->rest = target;
4674
+ } else {
4675
+ PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->current, PM_ERR_MULTI_ASSIGN_UNEXPECTED_REST);
4676
+ pm_node_list_append(&node->rights, target);
4677
+ }
4652
4678
  } else if (node->rest == NULL) {
4653
4679
  pm_node_list_append(&node->lefts, target);
4654
4680
  } else {
@@ -7172,7 +7198,7 @@ lex_numeric(pm_parser_t *parser) {
7172
7198
  static pm_token_type_t
7173
7199
  lex_global_variable(pm_parser_t *parser) {
7174
7200
  if (parser->current.end >= parser->end) {
7175
- pm_parser_err_current(parser, PM_ERR_INVALID_VARIABLE_GLOBAL);
7201
+ PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->current, PM_ERR_INVALID_VARIABLE_GLOBAL);
7176
7202
  return PM_TOKEN_GLOBAL_VARIABLE;
7177
7203
  }
7178
7204
 
@@ -7213,7 +7239,7 @@ lex_global_variable(pm_parser_t *parser) {
7213
7239
  } while (parser->current.end < parser->end && (width = char_is_identifier(parser, parser->current.end)) > 0);
7214
7240
 
7215
7241
  // $0 isn't allowed to be followed by anything.
7216
- pm_parser_err_current(parser, PM_ERR_INVALID_VARIABLE_GLOBAL);
7242
+ PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->current, PM_ERR_INVALID_VARIABLE_GLOBAL);
7217
7243
  }
7218
7244
 
7219
7245
  return PM_TOKEN_GLOBAL_VARIABLE;
@@ -7244,7 +7270,7 @@ lex_global_variable(pm_parser_t *parser) {
7244
7270
  } else {
7245
7271
  // If we get here, then we have a $ followed by something that isn't
7246
7272
  // recognized as a global variable.
7247
- pm_parser_err_current(parser, PM_ERR_INVALID_VARIABLE_GLOBAL);
7273
+ PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->current, PM_ERR_INVALID_VARIABLE_GLOBAL);
7248
7274
  }
7249
7275
 
7250
7276
  return PM_TOKEN_GLOBAL_VARIABLE;
@@ -8148,10 +8174,10 @@ lex_at_variable(pm_parser_t *parser) {
8148
8174
  while (parser->current.end < parser->end && (width = char_is_identifier(parser, parser->current.end)) > 0) {
8149
8175
  parser->current.end += width;
8150
8176
  }
8151
- } else if (type == PM_TOKEN_CLASS_VARIABLE) {
8152
- pm_parser_err_current(parser, PM_ERR_INCOMPLETE_VARIABLE_CLASS);
8153
8177
  } else {
8154
- pm_parser_err_current(parser, PM_ERR_INCOMPLETE_VARIABLE_INSTANCE);
8178
+ pm_diagnostic_id_t diag_id = (type == PM_TOKEN_CLASS_VARIABLE) ? PM_ERR_INCOMPLETE_VARIABLE_CLASS : PM_ERR_INCOMPLETE_VARIABLE_INSTANCE;
8179
+ size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
8180
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, diag_id, (int) ((parser->current.end + width) - parser->current.start), (const char *) parser->current.start);
8155
8181
  }
8156
8182
 
8157
8183
  // If we're lexing an embedded variable, then we need to pop back into the
@@ -9590,11 +9616,21 @@ parser_lex(pm_parser_t *parser) {
9590
9616
  if (*parser->current.start != '_') {
9591
9617
  size_t width = char_is_identifier_start(parser, parser->current.start);
9592
9618
 
9593
- // If this isn't the beginning of an identifier, then it's an invalid
9594
- // token as we've exhausted all of the other options. We'll skip past
9595
- // it and return the next token.
9619
+ // If this isn't the beginning of an identifier, then
9620
+ // it's an invalid token as we've exhausted all of the
9621
+ // other options. We'll skip past it and return the next
9622
+ // token after adding an appropriate error message.
9596
9623
  if (!width) {
9597
- pm_parser_err_current(parser, PM_ERR_INVALID_TOKEN);
9624
+ pm_diagnostic_id_t diag_id;
9625
+ if (*parser->current.start >= 0x80) {
9626
+ diag_id = PM_ERR_INVALID_MULTIBYTE_CHARACTER;
9627
+ } else if (char_is_ascii_printable(*parser->current.start) || (*parser->current.start == '\\')) {
9628
+ diag_id = PM_ERR_INVALID_PRINTABLE_CHARACTER;
9629
+ } else {
9630
+ diag_id = PM_ERR_INVALID_CHARACTER;
9631
+ }
9632
+
9633
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, diag_id, *parser->current.start);
9598
9634
  goto lex_next_token;
9599
9635
  }
9600
9636
 
@@ -9701,7 +9737,7 @@ parser_lex(pm_parser_t *parser) {
9701
9737
  // and then find the first one.
9702
9738
  pm_lex_mode_t *lex_mode = parser->lex_modes.current;
9703
9739
  const uint8_t *breakpoints = lex_mode->as.list.breakpoints;
9704
- const uint8_t *breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
9740
+ const uint8_t *breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
9705
9741
 
9706
9742
  // If we haven't found an escape yet, then this buffer will be
9707
9743
  // unallocated since we can refer directly to the source string.
@@ -9710,7 +9746,7 @@ parser_lex(pm_parser_t *parser) {
9710
9746
  while (breakpoint != NULL) {
9711
9747
  // If we hit a null byte, skip directly past it.
9712
9748
  if (*breakpoint == '\0') {
9713
- breakpoint = pm_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1));
9749
+ breakpoint = pm_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1), true);
9714
9750
  continue;
9715
9751
  }
9716
9752
 
@@ -9729,7 +9765,7 @@ parser_lex(pm_parser_t *parser) {
9729
9765
  // we need to continue on past it.
9730
9766
  if (lex_mode->as.list.nesting > 0) {
9731
9767
  parser->current.end = breakpoint + 1;
9732
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
9768
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
9733
9769
  lex_mode->as.list.nesting--;
9734
9770
  continue;
9735
9771
  }
@@ -9814,7 +9850,7 @@ parser_lex(pm_parser_t *parser) {
9814
9850
  }
9815
9851
 
9816
9852
  token_buffer.cursor = parser->current.end;
9817
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
9853
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
9818
9854
  continue;
9819
9855
  }
9820
9856
 
@@ -9827,7 +9863,7 @@ parser_lex(pm_parser_t *parser) {
9827
9863
  // that looked like an interpolated class or instance variable
9828
9864
  // like "#@" but wasn't actually. In this case we'll just skip
9829
9865
  // to the next breakpoint.
9830
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
9866
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
9831
9867
  continue;
9832
9868
  }
9833
9869
 
@@ -9842,7 +9878,7 @@ parser_lex(pm_parser_t *parser) {
9842
9878
  // and find the next breakpoint.
9843
9879
  assert(*breakpoint == lex_mode->as.list.incrementor);
9844
9880
  parser->current.end = breakpoint + 1;
9845
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
9881
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
9846
9882
  lex_mode->as.list.nesting++;
9847
9883
  continue;
9848
9884
  }
@@ -9881,14 +9917,14 @@ parser_lex(pm_parser_t *parser) {
9881
9917
  // regular expression. We'll use strpbrk to find the first of these
9882
9918
  // characters.
9883
9919
  const uint8_t *breakpoints = lex_mode->as.regexp.breakpoints;
9884
- const uint8_t *breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
9920
+ const uint8_t *breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false);
9885
9921
  pm_token_buffer_t token_buffer = { { 0 }, 0 };
9886
9922
 
9887
9923
  while (breakpoint != NULL) {
9888
9924
  // If we hit a null byte, skip directly past it.
9889
9925
  if (*breakpoint == '\0') {
9890
9926
  parser->current.end = breakpoint + 1;
9891
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
9927
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false);
9892
9928
  continue;
9893
9929
  }
9894
9930
 
@@ -9910,7 +9946,7 @@ parser_lex(pm_parser_t *parser) {
9910
9946
  // If the terminator is not a newline, then we can set
9911
9947
  // the next breakpoint and continue.
9912
9948
  parser->current.end = breakpoint + 1;
9913
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
9949
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false);
9914
9950
  continue;
9915
9951
  }
9916
9952
  }
@@ -9920,7 +9956,7 @@ parser_lex(pm_parser_t *parser) {
9920
9956
  if (*breakpoint == lex_mode->as.regexp.terminator) {
9921
9957
  if (lex_mode->as.regexp.nesting > 0) {
9922
9958
  parser->current.end = breakpoint + 1;
9923
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
9959
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false);
9924
9960
  lex_mode->as.regexp.nesting--;
9925
9961
  continue;
9926
9962
  }
@@ -10019,7 +10055,7 @@ parser_lex(pm_parser_t *parser) {
10019
10055
  }
10020
10056
 
10021
10057
  token_buffer.cursor = parser->current.end;
10022
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10058
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false);
10023
10059
  continue;
10024
10060
  }
10025
10061
 
@@ -10032,7 +10068,7 @@ parser_lex(pm_parser_t *parser) {
10032
10068
  // something that looked like an interpolated class or
10033
10069
  // instance variable like "#@" but wasn't actually. In
10034
10070
  // this case we'll just skip to the next breakpoint.
10035
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10071
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false);
10036
10072
  continue;
10037
10073
  }
10038
10074
 
@@ -10047,7 +10083,7 @@ parser_lex(pm_parser_t *parser) {
10047
10083
  // and find the next breakpoint.
10048
10084
  assert(*breakpoint == lex_mode->as.regexp.incrementor);
10049
10085
  parser->current.end = breakpoint + 1;
10050
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10086
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false);
10051
10087
  lex_mode->as.regexp.nesting++;
10052
10088
  continue;
10053
10089
  }
@@ -10083,7 +10119,7 @@ parser_lex(pm_parser_t *parser) {
10083
10119
  // string. We'll use strpbrk to find the first of these characters.
10084
10120
  pm_lex_mode_t *lex_mode = parser->lex_modes.current;
10085
10121
  const uint8_t *breakpoints = lex_mode->as.string.breakpoints;
10086
- const uint8_t *breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10122
+ const uint8_t *breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10087
10123
 
10088
10124
  // If we haven't found an escape yet, then this buffer will be
10089
10125
  // unallocated since we can refer directly to the source string.
@@ -10095,7 +10131,7 @@ parser_lex(pm_parser_t *parser) {
10095
10131
  if (lex_mode->as.string.incrementor != '\0' && *breakpoint == lex_mode->as.string.incrementor) {
10096
10132
  lex_mode->as.string.nesting++;
10097
10133
  parser->current.end = breakpoint + 1;
10098
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10134
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10099
10135
  continue;
10100
10136
  }
10101
10137
 
@@ -10107,7 +10143,7 @@ parser_lex(pm_parser_t *parser) {
10107
10143
  // to continue on past it.
10108
10144
  if (lex_mode->as.string.nesting > 0) {
10109
10145
  parser->current.end = breakpoint + 1;
10110
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10146
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10111
10147
  lex_mode->as.string.nesting--;
10112
10148
  continue;
10113
10149
  }
@@ -10149,7 +10185,7 @@ parser_lex(pm_parser_t *parser) {
10149
10185
  if (parser->heredoc_end == NULL) {
10150
10186
  pm_newline_list_append(&parser->newline_list, breakpoint);
10151
10187
  parser->current.end = breakpoint + 1;
10152
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10188
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10153
10189
  continue;
10154
10190
  } else {
10155
10191
  parser->current.end = breakpoint + 1;
@@ -10163,7 +10199,7 @@ parser_lex(pm_parser_t *parser) {
10163
10199
  case '\0':
10164
10200
  // Skip directly past the null character.
10165
10201
  parser->current.end = breakpoint + 1;
10166
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10202
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10167
10203
  break;
10168
10204
  case '\\': {
10169
10205
  // Here we hit escapes.
@@ -10232,7 +10268,7 @@ parser_lex(pm_parser_t *parser) {
10232
10268
  }
10233
10269
 
10234
10270
  token_buffer.cursor = parser->current.end;
10235
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10271
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10236
10272
  break;
10237
10273
  }
10238
10274
  case '#': {
@@ -10243,7 +10279,7 @@ parser_lex(pm_parser_t *parser) {
10243
10279
  // looked like an interpolated class or instance variable like "#@"
10244
10280
  // but wasn't actually. In this case we'll just skip to the next
10245
10281
  // breakpoint.
10246
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10282
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10247
10283
  break;
10248
10284
  }
10249
10285
 
@@ -10371,7 +10407,7 @@ parser_lex(pm_parser_t *parser) {
10371
10407
  breakpoints[2] = '\0';
10372
10408
  }
10373
10409
 
10374
- const uint8_t *breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10410
+ const uint8_t *breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10375
10411
  pm_token_buffer_t token_buffer = { { 0 }, 0 };
10376
10412
  bool was_escaped_newline = false;
10377
10413
 
@@ -10380,7 +10416,7 @@ parser_lex(pm_parser_t *parser) {
10380
10416
  case '\0':
10381
10417
  // Skip directly past the null character.
10382
10418
  parser->current.end = breakpoint + 1;
10383
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10419
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10384
10420
  break;
10385
10421
  case '\n': {
10386
10422
  if (parser->heredoc_end != NULL && (parser->heredoc_end > breakpoint)) {
@@ -10455,7 +10491,7 @@ parser_lex(pm_parser_t *parser) {
10455
10491
  // Otherwise we hit a newline and it wasn't followed by
10456
10492
  // a terminator, so we can continue parsing.
10457
10493
  parser->current.end = breakpoint + 1;
10458
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10494
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10459
10495
  break;
10460
10496
  }
10461
10497
  case '\\': {
@@ -10519,7 +10555,7 @@ parser_lex(pm_parser_t *parser) {
10519
10555
  }
10520
10556
 
10521
10557
  token_buffer.cursor = parser->current.end;
10522
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10558
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10523
10559
  break;
10524
10560
  }
10525
10561
  case '#': {
@@ -10531,7 +10567,7 @@ parser_lex(pm_parser_t *parser) {
10531
10567
  // or instance variable like "#@" but wasn't
10532
10568
  // actually. In this case we'll just skip to the
10533
10569
  // next breakpoint.
10534
- breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end);
10570
+ breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true);
10535
10571
  break;
10536
10572
  }
10537
10573
 
@@ -11044,7 +11080,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target) {
11044
11080
  return target;
11045
11081
  case PM_BACK_REFERENCE_READ_NODE:
11046
11082
  case PM_NUMBERED_REFERENCE_READ_NODE:
11047
- pm_parser_err_node(parser, target, PM_ERR_WRITE_TARGET_READONLY);
11083
+ PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, target, PM_ERR_WRITE_TARGET_READONLY);
11048
11084
  return target;
11049
11085
  case PM_GLOBAL_VARIABLE_READ_NODE:
11050
11086
  assert(sizeof(pm_global_variable_target_node_t) == sizeof(pm_global_variable_read_node_t));
@@ -11182,7 +11218,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
11182
11218
  }
11183
11219
  case PM_BACK_REFERENCE_READ_NODE:
11184
11220
  case PM_NUMBERED_REFERENCE_READ_NODE:
11185
- pm_parser_err_node(parser, target, PM_ERR_WRITE_TARGET_READONLY);
11221
+ PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, target, PM_ERR_WRITE_TARGET_READONLY);
11186
11222
  /* fallthrough */
11187
11223
  case PM_GLOBAL_VARIABLE_READ_NODE: {
11188
11224
  pm_global_variable_write_node_t *node = pm_global_variable_write_node_create(parser, target, operator, value);
@@ -11357,7 +11393,7 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b
11357
11393
  pm_multi_target_node_targets_append(parser, result, target);
11358
11394
  } else if (!match1(parser, PM_TOKEN_EOF)) {
11359
11395
  // If we get here, then we have a trailing , in a multi target node.
11360
- // We'll set the implicit rest flag to indicate this.
11396
+ // We'll add an implicit rest node to represent this.
11361
11397
  pm_node_t *rest = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
11362
11398
  pm_multi_target_node_targets_append(parser, result, rest);
11363
11399
  break;
@@ -11447,8 +11483,13 @@ parse_statements(pm_parser_t *parser, pm_context_t context) {
11447
11483
 
11448
11484
  while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON));
11449
11485
  if (context_terminator(context, &parser->current)) break;
11450
- } else {
11451
- expect1(parser, PM_TOKEN_NEWLINE, PM_ERR_EXPECT_EOL_AFTER_STATEMENT);
11486
+ } else if (!accept1(parser, PM_TOKEN_NEWLINE)) {
11487
+ // This is an inlined version of accept1 because the error that we
11488
+ // want to add has varargs. If this happens again, we should
11489
+ // probably extract a helper function.
11490
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type));
11491
+ parser->previous.start = parser->previous.end;
11492
+ parser->previous.type = PM_TOKEN_MISSING;
11452
11493
  }
11453
11494
  }
11454
11495
 
@@ -12377,25 +12418,10 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, bool def_p) {
12377
12418
  }
12378
12419
 
12379
12420
  static inline pm_begin_node_t *
12380
- parse_rescues_as_begin(pm_parser_t *parser, pm_statements_node_t *statements, bool def_p) {
12421
+ parse_rescues_as_begin(pm_parser_t *parser, const uint8_t *start, pm_statements_node_t *statements, bool def_p) {
12381
12422
  pm_token_t no_begin_token = not_provided(parser);
12382
12423
  pm_begin_node_t *begin_node = pm_begin_node_create(parser, &no_begin_token, statements);
12383
12424
  parse_rescues(parser, begin_node, def_p);
12384
-
12385
- // All nodes within a begin node are optional, so we look
12386
- // for the earliest possible node that we can use to set
12387
- // the BeginNode's start location
12388
- const uint8_t *start = begin_node->base.location.start;
12389
- if (begin_node->statements) {
12390
- start = begin_node->statements->base.location.start;
12391
- } else if (begin_node->rescue_clause) {
12392
- start = begin_node->rescue_clause->base.location.start;
12393
- } else if (begin_node->else_clause) {
12394
- start = begin_node->else_clause->base.location.start;
12395
- } else if (begin_node->ensure_clause) {
12396
- start = begin_node->ensure_clause->base.location.start;
12397
- }
12398
-
12399
12425
  begin_node->base.location.start = start;
12400
12426
  return begin_node;
12401
12427
  }
@@ -12490,7 +12516,7 @@ parse_block(pm_parser_t *parser) {
12490
12516
 
12491
12517
  if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
12492
12518
  assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
12493
- statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false);
12519
+ statements = (pm_node_t *) parse_rescues_as_begin(parser, opening.start, (pm_statements_node_t *) statements, false);
12494
12520
  }
12495
12521
  }
12496
12522
 
@@ -13857,7 +13883,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
13857
13883
  pm_constant_id_t name_id = pm_parser_constant_id_constant(parser, "0it", 3);
13858
13884
  variable = (pm_node_t *) pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0);
13859
13885
  } else {
13860
- PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_NO_LOCAL_VARIABLE, (int) (parser->previous.end - parser->previous.start), parser->previous.start);
13886
+ PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->previous, PM_ERR_NO_LOCAL_VARIABLE);
13861
13887
  variable = (pm_node_t *) pm_local_variable_read_node_create(parser, &parser->previous, 0);
13862
13888
  }
13863
13889
  }
@@ -14166,7 +14192,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
14166
14192
  parser_lex(parser);
14167
14193
 
14168
14194
  if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
14169
- expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_TERM);
14195
+ expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF);
14170
14196
  // If we get here, then we have an end immediately after a
14171
14197
  // start. In that case we'll create an empty content token and
14172
14198
  // return an uninterpolated string.
@@ -14223,15 +14249,19 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
14223
14249
  parser_lex(parser);
14224
14250
  } while (match1(parser, PM_TOKEN_STRING_CONTENT));
14225
14251
 
14226
- expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_TERM);
14252
+ expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF);
14227
14253
  node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous);
14228
14254
  } else if (accept1(parser, PM_TOKEN_LABEL_END) && !state_is_arg_labeled) {
14229
14255
  node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &unescaped));
14230
14256
  } else if (match1(parser, PM_TOKEN_EOF)) {
14231
- pm_parser_err_token(parser, &opening, PM_ERR_STRING_LITERAL_TERM);
14257
+ pm_parser_err_token(parser, &opening, PM_ERR_STRING_LITERAL_EOF);
14232
14258
  node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
14259
+ } else if (accept1(parser, PM_TOKEN_STRING_END)) {
14260
+ node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
14233
14261
  } else {
14234
- expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_TERM);
14262
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_STRING_LITERAL_TERM, pm_token_type_human(parser->previous.type));
14263
+ parser->previous.start = parser->previous.end;
14264
+ parser->previous.type = PM_TOKEN_MISSING;
14235
14265
  node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
14236
14266
  }
14237
14267
  } else if (match1(parser, PM_TOKEN_STRING_CONTENT)) {
@@ -14246,7 +14276,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
14246
14276
  if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
14247
14277
  node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
14248
14278
  pm_node_flag_set(node, parse_unescaped_encoding(parser));
14249
- expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_TERM);
14279
+ expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF);
14250
14280
  } else if (accept1(parser, PM_TOKEN_LABEL_END)) {
14251
14281
  node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &unescaped));
14252
14282
  } else {
@@ -14337,6 +14367,29 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
14337
14367
  return current;
14338
14368
  }
14339
14369
 
14370
+ /**
14371
+ * Append an error to the error list on the parser using the given diagnostic
14372
+ * ID. This function is a specialization that handles formatting the specific
14373
+ * kind of error that is being appended.
14374
+ */
14375
+ static void
14376
+ pm_parser_err_prefix(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
14377
+ switch (diag_id) {
14378
+ case PM_ERR_HASH_KEY: {
14379
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, diag_id, pm_token_type_human(parser->previous.type));
14380
+ break;
14381
+ }
14382
+ case PM_ERR_UNARY_RECEIVER: {
14383
+ const char *human = (parser->current.type == PM_TOKEN_EOF ? "end-of-input" : pm_token_type_human(parser->current.type));
14384
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, diag_id, human, parser->previous.start[0]);
14385
+ break;
14386
+ }
14387
+ default:
14388
+ pm_parser_err_previous(parser, diag_id);
14389
+ break;
14390
+ }
14391
+ }
14392
+
14340
14393
  /**
14341
14394
  * Parse an expression that begins with the previous node that we just lexed.
14342
14395
  */
@@ -14521,7 +14574,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
14521
14574
  // If we didn't find a terminator and we didn't find a right
14522
14575
  // parenthesis, then this is a syntax error.
14523
14576
  if (!terminator_found) {
14524
- pm_parser_err(parser, parser->current.start, parser->current.start, PM_ERR_EXPECT_EOL_AFTER_STATEMENT);
14577
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type));
14525
14578
  }
14526
14579
 
14527
14580
  // Parse each statement within the parentheses.
@@ -14550,7 +14603,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
14550
14603
  } else if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
14551
14604
  break;
14552
14605
  } else {
14553
- pm_parser_err(parser, parser->current.start, parser->current.start, PM_ERR_EXPECT_EOL_AFTER_STATEMENT);
14606
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type));
14554
14607
  }
14555
14608
  }
14556
14609
 
@@ -15290,7 +15343,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
15290
15343
 
15291
15344
  if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
15292
15345
  assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
15293
- statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false);
15346
+ statements = (pm_node_t *) parse_rescues_as_begin(parser, class_keyword.start, (pm_statements_node_t *) statements, false);
15294
15347
  }
15295
15348
 
15296
15349
  expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM);
@@ -15343,7 +15396,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
15343
15396
 
15344
15397
  if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
15345
15398
  assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
15346
- statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false);
15399
+ statements = (pm_node_t *) parse_rescues_as_begin(parser, class_keyword.start, (pm_statements_node_t *) statements, false);
15347
15400
  }
15348
15401
 
15349
15402
  expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM);
@@ -15612,7 +15665,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
15612
15665
 
15613
15666
  if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
15614
15667
  assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
15615
- statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, true);
15668
+ statements = (pm_node_t *) parse_rescues_as_begin(parser, def_keyword.start, (pm_statements_node_t *) statements, true);
15616
15669
  }
15617
15670
 
15618
15671
  pm_accepts_block_stack_pop(parser);
@@ -15631,10 +15684,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
15631
15684
  * methods to override the unary operators, we should ignore
15632
15685
  * the @ in the same way we do for symbols.
15633
15686
  */
15634
- name.end = parse_operator_symbol_name(&name);
15687
+ pm_constant_id_t name_id = pm_parser_constant_id_location(parser, name.start, parse_operator_symbol_name(&name));
15635
15688
 
15636
15689
  return (pm_node_t *) pm_def_node_create(
15637
15690
  parser,
15691
+ name_id,
15638
15692
  &name,
15639
15693
  receiver,
15640
15694
  params,
@@ -15872,7 +15926,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
15872
15926
 
15873
15927
  if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
15874
15928
  assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
15875
- statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false);
15929
+ statements = (pm_node_t *) parse_rescues_as_begin(parser, module_keyword.start, (pm_statements_node_t *) statements, false);
15876
15930
  }
15877
15931
 
15878
15932
  pm_constant_id_list_t locals = parser->current_scope->locals;
@@ -16463,7 +16517,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
16463
16517
  // context of a multiple assignment. We enforce that here. We'll
16464
16518
  // still lex past it though and create a missing node place.
16465
16519
  if (binding_power != PM_BINDING_POWER_STATEMENT) {
16466
- pm_parser_err_previous(parser, diag_id);
16520
+ pm_parser_err_prefix(parser, diag_id);
16467
16521
  return (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
16468
16522
  }
16469
16523
 
@@ -16486,7 +16540,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
16486
16540
  parser_lex(parser);
16487
16541
 
16488
16542
  pm_token_t operator = parser->previous;
16489
- pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, binding_power < PM_BINDING_POWER_MATCH, PM_ERR_UNARY_RECEIVER_BANG);
16543
+ pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, binding_power < PM_BINDING_POWER_MATCH, PM_ERR_UNARY_RECEIVER);
16490
16544
  pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "!");
16491
16545
 
16492
16546
  pm_conditional_predicate(receiver);
@@ -16496,7 +16550,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
16496
16550
  parser_lex(parser);
16497
16551
 
16498
16552
  pm_token_t operator = parser->previous;
16499
- pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_TILDE);
16553
+ pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER);
16500
16554
  pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "~");
16501
16555
 
16502
16556
  return (pm_node_t *) node;
@@ -16505,7 +16559,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
16505
16559
  parser_lex(parser);
16506
16560
 
16507
16561
  pm_token_t operator = parser->previous;
16508
- pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_MINUS);
16562
+ pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER);
16509
16563
  pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "-@");
16510
16564
 
16511
16565
  return (pm_node_t *) node;
@@ -16514,7 +16568,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
16514
16568
  parser_lex(parser);
16515
16569
 
16516
16570
  pm_token_t operator = parser->previous;
16517
- pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_MINUS);
16571
+ pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER);
16518
16572
 
16519
16573
  if (accept1(parser, PM_TOKEN_STAR_STAR)) {
16520
16574
  pm_token_t exponent_operator = parser->previous;
@@ -16605,7 +16659,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
16605
16659
 
16606
16660
  if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
16607
16661
  assert(body == NULL || PM_NODE_TYPE_P(body, PM_STATEMENTS_NODE));
16608
- body = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) body, false);
16662
+ body = (pm_node_t *) parse_rescues_as_begin(parser, opening.start, (pm_statements_node_t *) body, false);
16609
16663
  }
16610
16664
 
16611
16665
  expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_LAMBDA_TERM_END);
@@ -16630,7 +16684,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
16630
16684
  parser_lex(parser);
16631
16685
 
16632
16686
  pm_token_t operator = parser->previous;
16633
- pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_PLUS);
16687
+ pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER);
16634
16688
  pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "+@");
16635
16689
 
16636
16690
  return (pm_node_t *) node;
@@ -16653,7 +16707,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
16653
16707
  // here because it will provide more context in addition to the
16654
16708
  // recoverable error that we will also add.
16655
16709
  if (diag_id != PM_ERR_CANNOT_PARSE_EXPRESSION) {
16656
- pm_parser_err_previous(parser, diag_id);
16710
+ pm_parser_err_prefix(parser, diag_id);
16657
16711
  }
16658
16712
 
16659
16713
  // If we get here, then we are assuming this token is closing a
@@ -16666,7 +16720,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
16666
16720
  // have an unexpected token.
16667
16721
  PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_UNEXPECTED_TOKEN_IGNORE, pm_token_type_human(parser->current.type));
16668
16722
  } else {
16669
- pm_parser_err_previous(parser, diag_id);
16723
+ pm_parser_err_prefix(parser, diag_id);
16670
16724
  }
16671
16725
 
16672
16726
  return (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
@@ -16900,7 +16954,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
16900
16954
  switch (PM_NODE_TYPE(node)) {
16901
16955
  case PM_BACK_REFERENCE_READ_NODE:
16902
16956
  case PM_NUMBERED_REFERENCE_READ_NODE:
16903
- pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_READONLY);
16957
+ PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, node, PM_ERR_WRITE_TARGET_READONLY);
16904
16958
  /* fallthrough */
16905
16959
  case PM_GLOBAL_VARIABLE_READ_NODE: {
16906
16960
  parser_lex(parser);
@@ -17011,7 +17065,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
17011
17065
  switch (PM_NODE_TYPE(node)) {
17012
17066
  case PM_BACK_REFERENCE_READ_NODE:
17013
17067
  case PM_NUMBERED_REFERENCE_READ_NODE:
17014
- pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_READONLY);
17068
+ PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, node, PM_ERR_WRITE_TARGET_READONLY);
17015
17069
  /* fallthrough */
17016
17070
  case PM_GLOBAL_VARIABLE_READ_NODE: {
17017
17071
  parser_lex(parser);
@@ -17132,7 +17186,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
17132
17186
  switch (PM_NODE_TYPE(node)) {
17133
17187
  case PM_BACK_REFERENCE_READ_NODE:
17134
17188
  case PM_NUMBERED_REFERENCE_READ_NODE:
17135
- pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_READONLY);
17189
+ PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, node, PM_ERR_WRITE_TARGET_READONLY);
17136
17190
  /* fallthrough */
17137
17191
  case PM_GLOBAL_VARIABLE_READ_NODE: {
17138
17192
  parser_lex(parser);
@@ -17796,6 +17850,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
17796
17850
  .current = { .type = PM_TOKEN_EOF, .start = source, .end = source },
17797
17851
  .next_start = NULL,
17798
17852
  .heredoc_end = NULL,
17853
+ .data_loc = { .start = NULL, .end = NULL },
17799
17854
  .comment_list = { 0 },
17800
17855
  .magic_comment_list = { 0 },
17801
17856
  .warning_list = { 0 },