tree-sitter-sed 0.8.0 → 0.9.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.
package/common/grammar.js CHANGED
@@ -28,6 +28,22 @@ function fileOperandForms($, name, operand) {
28
28
  ];
29
29
  }
30
30
 
31
+ function lineOperand($, first, rest) {
32
+ return prec.right(
33
+ seq(
34
+ choice(first, issueField($, "nul_character")),
35
+ repeat(choice(rest, issueField($, "nul_character"))),
36
+ ),
37
+ );
38
+ }
39
+
40
+ function commentText($) {
41
+ return choice(
42
+ namedExternal($, $._comment_text, "comment_text"),
43
+ issueField($, "nul_character"),
44
+ );
45
+ }
46
+
31
47
  function missingCommandSeparator($) {
32
48
  return choice(
33
49
  issueNode($, "missing_command_separator"),
@@ -213,11 +229,6 @@ function delimiterRules() {
213
229
  return rules;
214
230
  }
215
231
 
216
- function choiceForRules($, names) {
217
- const rules = names.map((name) => $[name]);
218
- return rules.length === 1 ? rules[0] : choice(...rules);
219
- }
220
-
221
232
  function commandListRules() {
222
233
  return {
223
234
  script: ($) => optional(alias($._script_command_list, $.command_list)),
@@ -256,7 +267,7 @@ function commandListRules() {
256
267
  "default_output_suppression",
257
268
  ),
258
269
  ),
259
- optional(namedExternal($, $._comment_text, "comment_text")),
270
+ repeat(commentText($)),
260
271
  ),
261
272
 
262
273
  _command_list: ($) =>
@@ -518,7 +529,6 @@ function addressRules(mode) {
518
529
 
519
530
  address: addressChoice,
520
531
 
521
- // Keep maximum-specific GLR paths distinct until the function verb.
522
532
  _max0_address: addressChoice,
523
533
 
524
534
  _max1_address: addressChoice,
@@ -599,10 +609,11 @@ function operandRules(mode) {
599
609
  repeat1(
600
610
  choice(
601
611
  $.replacement_literal,
612
+ issueField($, "nul_character"),
602
613
  $.matched_text_reference,
603
614
  $.replacement_backreference,
604
615
  $.replacement_escaped_delimiter,
605
- $.ambiguous_replacement_delimiter_escape,
616
+ issueField($, "replacement_ampersand_delimiter_escape"),
606
617
  $.replacement_escape,
607
618
  $.escaped_newline,
608
619
  issueField($, "unspecified_replacement_escape"),
@@ -610,45 +621,17 @@ function operandRules(mode) {
610
621
  ),
611
622
  ),
612
623
 
613
- replacement_literal: ($) =>
614
- namedExternal($, $._replacement_literal, "replacement_literal_token"),
624
+ replacement_literal: ($) => $._replacement_literal,
615
625
 
616
- matched_text_reference: ($) =>
617
- namedExternal(
618
- $,
619
- $._replacement_match_reference,
620
- "matched_text_reference_token",
621
- ),
626
+ matched_text_reference: ($) => $._replacement_match_reference,
622
627
 
623
- replacement_backreference: ($) =>
624
- namedExternal(
625
- $,
626
- $._replacement_backreference,
627
- "replacement_backreference_token",
628
- ),
629
-
630
- replacement_escaped_delimiter: ($) =>
631
- field(
632
- "token",
633
- namedExternal(
634
- $,
635
- $._replacement_escaped_delimiter,
636
- "escaped_delimiter_token",
637
- ),
638
- ),
628
+ replacement_backreference: ($) => $._replacement_backreference,
639
629
 
640
- ambiguous_replacement_delimiter_escape: ($) =>
641
- issueField($, "replacement_ampersand_delimiter_escape"),
630
+ replacement_escaped_delimiter: ($) => $._replacement_escaped_delimiter,
642
631
 
643
- replacement_escape: ($) =>
644
- namedExternal(
645
- $,
646
- $._replacement_escape_sequence,
647
- "replacement_escape_token",
648
- ),
632
+ replacement_escape: ($) => $._replacement_escape_sequence,
649
633
 
650
- escaped_newline: ($) =>
651
- namedExternal($, $._replacement_escaped_newline, "escaped_newline_token"),
634
+ escaped_newline: ($) => $._replacement_escaped_newline,
652
635
 
653
636
  _substitution_flags: ($) =>
654
637
  choice(
@@ -704,6 +687,7 @@ function operandRules(mode) {
704
687
  repeat1(
705
688
  choice(
706
689
  $.translation_literal,
690
+ issueField($, "nul_character"),
707
691
  $.translation_escape,
708
692
  $.translation_escaped_delimiter,
709
693
  issueField($, "undefined_translation_escape"),
@@ -711,18 +695,11 @@ function operandRules(mode) {
711
695
  ),
712
696
  ),
713
697
 
714
- translation_literal: ($) =>
715
- namedExternal($, $._translate_literal, "translation_literal_token"),
698
+ translation_literal: ($) => $._translate_literal,
716
699
 
717
- translation_escape: ($) =>
718
- namedExternal($, $._translate_escape, "translation_escape_token"),
700
+ translation_escape: ($) => $._translate_escape,
719
701
 
720
- translation_escaped_delimiter: ($) =>
721
- namedExternal(
722
- $,
723
- $._translate_escaped_delimiter,
724
- "escaped_delimiter_token",
725
- ),
702
+ translation_escaped_delimiter: ($) => $._translate_escaped_delimiter,
726
703
  };
727
704
  }
728
705
 
@@ -737,6 +714,7 @@ function functionRules() {
737
714
  repeat1(
738
715
  choice(
739
716
  $.text_literal,
717
+ issueField($, "nul_character"),
740
718
  $.text_backslash_escape,
741
719
  $.text_escaped_newline,
742
720
  issueField($, "unspecified_text_escape"),
@@ -750,14 +728,11 @@ function functionRules() {
750
728
 
751
729
  _text_end: ($) => choice($._text_line_end, $._text_eof),
752
730
 
753
- text_literal: ($) =>
754
- namedExternal($, $._text_literal, "text_literal_token"),
731
+ text_literal: ($) => $._text_literal,
755
732
 
756
- text_backslash_escape: ($) =>
757
- namedExternal($, $._text_backslash_escape, "text_backslash_escape_token"),
733
+ text_backslash_escape: ($) => $._text_backslash_escape,
758
734
 
759
- text_escaped_newline: ($) =>
760
- namedExternal($, $._text_escaped_newline, "text_escaped_newline_token"),
735
+ text_escaped_newline: ($) => $._text_escaped_newline,
761
736
 
762
737
  text_introducer: ($) =>
763
738
  namedExternal($, $._text_command_start, "text_introducer_token"),
@@ -765,22 +740,32 @@ function functionRules() {
765
740
  _incomplete_text_introducer: ($) =>
766
741
  issueField($, "incomplete_text_introducer"),
767
742
 
768
- rfile: ($) => namedExternal($, $._file_argument, "rfile_token"),
743
+ rfile: ($) => lineOperand($, $._file_argument, $._line_word),
769
744
 
770
- wfile: ($) => namedExternal($, $._file_argument, "wfile_token"),
745
+ wfile: ($) => lineOperand($, $._file_argument, $._line_word),
771
746
 
772
747
  _substitution_wfile: ($) =>
773
- namedExternal($, $._substitution_wfile_argument, "wfile_token"),
748
+ lineOperand(
749
+ $,
750
+ $._substitution_wfile_argument,
751
+ $._substitution_wfile_continuation,
752
+ ),
774
753
 
775
- label: ($) => namedExternal($, $._line_word, "label_token"),
754
+ label: ($) =>
755
+ prec.right(repeat1(choice($._line_word, issueField($, "nul_character")))),
776
756
 
777
- comment: ($) => namedExternal($, $._comment_text, "comment_text"),
757
+ comment: ($) => prec.right(repeat1(commentText($))),
778
758
 
779
- closing_brace: ($) =>
780
- choice(
781
- namedExternal($, $._right_brace, "closing_brace_token"),
782
- issueField($, "missing_closing_brace"),
759
+ comment_function: ($) =>
760
+ prec.right(
761
+ seq(functionVerb($, "#"), optional(field("comment", $.comment))),
783
762
  ),
763
+
764
+ closing_brace: ($) =>
765
+ choice($._present_closing_brace, issueField($, "missing_closing_brace")),
766
+
767
+ _present_closing_brace: ($) =>
768
+ namedExternal($, $._right_brace, "closing_brace_token"),
784
769
  };
785
770
 
786
771
  function fileForm(form) {
@@ -827,7 +812,6 @@ function functionRules() {
827
812
  ],
828
813
  rfile: fileForm("rfile"),
829
814
  wfile: fileForm("wfile"),
830
- comment: ($) => [optional(field("comment", $.comment))],
831
815
  };
832
816
 
833
817
  for (const { rule, spelling } of noArgumentDefinitions) {
@@ -852,8 +836,8 @@ function editingCommandRules() {
852
836
  2: ($) => $.address_clause,
853
837
  };
854
838
 
855
- // One wrapper rule per (chainable or line-terminated) kind and address
856
- // maximum keeps the maximum-specific GLR paths distinct until the verb.
839
+ // Keep address, issue, and function rules separate by address maximum so
840
+ // GLR paths cannot merge before the function verb.
857
841
  const wrappers = [];
858
842
  for (const [kind, isLineTerminated] of [
859
843
  ["chainable", false],
@@ -977,7 +961,7 @@ function editingCommandRules() {
977
961
  };
978
962
 
979
963
  for (const { name, names } of wrappers) {
980
- rules[name] = ($) => choiceForRules($, names);
964
+ rules[name] = ($) => choice(...names.map((name) => $[name]));
981
965
  }
982
966
 
983
967
  return rules;
@@ -1049,15 +1033,31 @@ function issueDefinitions(mode) {
1049
1033
  outcome: "undefined_syntax",
1050
1034
  rule: ($) => $._regex_malformed_bracket_term,
1051
1035
  },
1036
+ {
1037
+ id: "invalid_character_class_name",
1038
+ reason: "malformed_bracket_term",
1039
+ outcome: "undefined_syntax",
1040
+ rule: ($) => namedExternal($, $._regex_invalid_class_name, "class_name"),
1041
+ },
1042
+ {
1043
+ reason: "nul_character",
1044
+ outcome: "nonconforming_syntax",
1045
+ rule: ($) => $._nul_character,
1046
+ },
1047
+ {
1048
+ reason: "invalid_regular_expression_character",
1049
+ outcome: "invalid_syntax",
1050
+ rule: ($) => $._invalid_character,
1051
+ },
1052
1052
  {
1053
1053
  reason: "character_class_range_start",
1054
1054
  outcome: "undefined_syntax",
1055
- rule: ($) => $._nonportable_range_start_marker,
1055
+ rule: ($) => seq($.character_class, $._nonportable_range_start_marker),
1056
1056
  },
1057
1057
  {
1058
1058
  reason: "character_class_range_end",
1059
1059
  outcome: "undefined_syntax",
1060
- rule: ($) => $._nonportable_range_end_marker,
1060
+ rule: ($) => seq($._nonportable_range_end_marker, $.character_class),
1061
1061
  },
1062
1062
  {
1063
1063
  reason: "shared_range_endpoint",
@@ -1081,7 +1081,6 @@ function issueDefinitions(mode) {
1081
1081
  outcome: "undefined_syntax",
1082
1082
  rule: missing("omitted_first_address"),
1083
1083
  },
1084
- // The marker is shared, but maximum-specific reductions must not merge.
1085
1084
  ...[0, 1].map((maximum) => ({
1086
1085
  id: `omitted_first_address_unit${maximum}`,
1087
1086
  reason: "omitted_address",
@@ -1130,17 +1129,39 @@ function issueDefinitions(mode) {
1130
1129
  {
1131
1130
  reason: "malformed_interval",
1132
1131
  outcome: "undefined_syntax",
1133
- rule: ($) => $._regex_invalid_interval,
1132
+ rule: ($) =>
1133
+ prec.right(
1134
+ repeat1(
1135
+ choice(
1136
+ $._regex_invalid_interval,
1137
+ issueField($, "invalid_regular_expression_character"),
1138
+ ),
1139
+ ),
1140
+ ),
1134
1141
  },
1135
1142
  {
1136
1143
  reason: "leading_duplication_symbol",
1137
1144
  outcome: "undefined_syntax",
1138
- rule: ($) => $._regex_leading_duplication_marker,
1145
+ rule: ($) =>
1146
+ seq(
1147
+ $._regex_leading_duplication_marker,
1148
+ field(
1149
+ "operator",
1150
+ mode === "bre" ? $.bre_dupl_symbol : $.ere_dupl_symbol,
1151
+ ),
1152
+ ),
1139
1153
  },
1140
1154
  {
1141
1155
  reason: "adjacent_duplication_symbol",
1142
1156
  outcome: "undefined_syntax",
1143
- rule: ($) => $._regex_adjacent_duplication_marker,
1157
+ rule: ($) =>
1158
+ seq(
1159
+ $._regex_adjacent_duplication_marker,
1160
+ field(
1161
+ "operator",
1162
+ mode === "bre" ? $.bre_dupl_symbol : $.ere_dupl_symbol,
1163
+ ),
1164
+ ),
1144
1165
  },
1145
1166
  ...(mode === "ere"
1146
1167
  ? [
@@ -1164,22 +1185,26 @@ function issueDefinitions(mode) {
1164
1185
  {
1165
1186
  reason: "undefined_translation_escape",
1166
1187
  outcome: "undefined_syntax",
1167
- rule: ($) => $._translate_nonportable_escape,
1188
+ rule: ($) =>
1189
+ choice(
1190
+ $._translate_nonportable_escape,
1191
+ seq($._escape_prefix, issueField($, "nul_character")),
1192
+ ),
1168
1193
  },
1169
1194
  {
1170
1195
  reason: "equivalence_class_range_start",
1171
1196
  outcome: "unspecified_syntax",
1172
- rule: ($) => $._nonportable_range_start_marker,
1197
+ rule: ($) => seq($.equivalence_class, $._nonportable_range_start_marker),
1173
1198
  },
1174
1199
  {
1175
1200
  reason: "equivalence_class_range_end",
1176
1201
  outcome: "unspecified_syntax",
1177
- rule: ($) => $._nonportable_range_end_marker,
1202
+ rule: ($) => seq($._nonportable_range_end_marker, $.equivalence_class),
1178
1203
  },
1179
1204
  {
1180
1205
  reason: "ambiguous_bracket_expression",
1181
1206
  outcome: "unspecified_syntax",
1182
- rule: ($) => $._ambiguous_bracket_expression_marker,
1207
+ rule: ($) => alias($._ambiguous_bracket_expression, $.bracket_expression),
1183
1208
  },
1184
1209
  {
1185
1210
  reason: "blanks_after_negation",
@@ -1189,7 +1214,11 @@ function issueDefinitions(mode) {
1189
1214
  {
1190
1215
  reason: "unspecified_replacement_escape",
1191
1216
  outcome: "unspecified_syntax",
1192
- rule: ($) => $._replacement_nonportable_escape,
1217
+ rule: ($) =>
1218
+ choice(
1219
+ $._replacement_nonportable_escape,
1220
+ seq($._escape_prefix, issueField($, "nul_character")),
1221
+ ),
1193
1222
  },
1194
1223
  {
1195
1224
  reason: "special_delimiter_escape",
@@ -1204,33 +1233,49 @@ function issueDefinitions(mode) {
1204
1233
  {
1205
1234
  reason: "unspecified_text_escape",
1206
1235
  outcome: "unspecified_syntax",
1207
- rule: ($) => $._text_unspecified_escape,
1236
+ rule: ($) =>
1237
+ choice(
1238
+ $._text_unspecified_escape,
1239
+ seq($._escape_prefix, issueField($, "nul_character")),
1240
+ ),
1208
1241
  },
1209
1242
  ...(mode === "bre"
1210
1243
  ? [
1211
1244
  {
1212
1245
  reason: "bre_vertical_line_escape",
1213
1246
  outcome: "implementation_defined_syntax",
1214
- rule: ($) => $._bre_vertical_line_escape_marker,
1247
+ rule: ($) =>
1248
+ field(
1249
+ "token",
1250
+ namedExternal($, $._regex_bre_vertical_line_escape, "back_bar"),
1251
+ ),
1215
1252
  },
1216
1253
  {
1217
1254
  reason: "bre_question_mark_escape",
1218
1255
  outcome: "implementation_defined_syntax",
1219
- rule: ($) => $._bre_question_mark_escape_marker,
1256
+ rule: ($) =>
1257
+ field(
1258
+ "token",
1259
+ namedExternal($, $._regex_bre_question_mark_escape, "back_qm"),
1260
+ ),
1220
1261
  },
1221
1262
  {
1222
1263
  reason: "bre_plus_escape",
1223
1264
  outcome: "implementation_defined_syntax",
1224
- rule: ($) => $._bre_plus_escape_marker,
1265
+ rule: ($) =>
1266
+ field(
1267
+ "token",
1268
+ namedExternal($, $._regex_bre_plus_escape, "back_plus"),
1269
+ ),
1225
1270
  },
1226
1271
  {
1227
1272
  reason: "bre_subexpression_left_anchor",
1228
- outcome: "invalid_syntax",
1273
+ outcome: "nonconforming_syntax",
1229
1274
  rule: ($) => $._regex_bre_subexpression_caret,
1230
1275
  },
1231
1276
  {
1232
1277
  reason: "bre_subexpression_right_anchor",
1233
- outcome: "invalid_syntax",
1278
+ outcome: "nonconforming_syntax",
1234
1279
  rule: ($) => $._regex_bre_subexpression_dollar,
1235
1280
  },
1236
1281
  ]
@@ -1270,7 +1315,8 @@ function issueDefinitions(mode) {
1270
1315
  {
1271
1316
  reason: "unknown_function",
1272
1317
  outcome: "nonconforming_syntax",
1273
- rule: () => token(prec(-2, unknownFunctionCharacter)),
1318
+ rule: ($) =>
1319
+ choice(token(prec(-2, unknownFunctionCharacter)), $._invalid_character),
1274
1320
  },
1275
1321
  {
1276
1322
  id: "reserved_unknown_function",
@@ -1281,10 +1327,17 @@ function issueDefinitions(mode) {
1281
1327
  {
1282
1328
  reason: "unexpected_command_text",
1283
1329
  outcome: "nonconforming_syntax",
1284
- rule: () =>
1285
- choice(
1286
- token.immediate(prec(-10, /[[:blank:]]+/)),
1287
- token.immediate(prec(-10, /[[:blank:]]*[^[:blank:];}\n][^;}\n]*/)),
1330
+ rule: ($) =>
1331
+ repeat1(
1332
+ choice(
1333
+ token.immediate(prec(-10, /[[:blank:]]+/)),
1334
+ token.immediate(
1335
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: NUL must remain a separate syntax issue.
1336
+ prec(-10, /[[:blank:]]*[^[:blank:];}\n\x00][^;}\n\x00]*/),
1337
+ ),
1338
+ issueField($, "nul_character"),
1339
+ $._invalid_character,
1340
+ ),
1288
1341
  ),
1289
1342
  },
1290
1343
  {
@@ -1310,7 +1363,7 @@ function issueDefinitions(mode) {
1310
1363
  {
1311
1364
  reason: "unmatched_closing_brace",
1312
1365
  outcome: "nonconforming_syntax",
1313
- rule: ($) => $._right_brace,
1366
+ rule: ($) => alias($._present_closing_brace, $.closing_brace),
1314
1367
  },
1315
1368
  {
1316
1369
  reason: "missing_command_separator",
@@ -1337,7 +1390,11 @@ function issueDefinitions(mode) {
1337
1390
  {
1338
1391
  reason: "invalid_delimiter",
1339
1392
  outcome: "nonconforming_syntax",
1340
- rule: ($) => field("token", alias("\\", $.delimiter_token)),
1393
+ rule: ($) =>
1394
+ field(
1395
+ "token",
1396
+ alias(choice("\\", $._invalid_character), $.delimiter_token),
1397
+ ),
1341
1398
  },
1342
1399
  {
1343
1400
  reason: "unterminated_regular_expression",
@@ -1516,10 +1573,13 @@ function externalTokens($, mode) {
1516
1573
  $._translate_middle,
1517
1574
  $._translate_end,
1518
1575
  $._regex_literal,
1576
+ $._invalid_character,
1577
+ $._nul_character,
1519
1578
  $._regex_beginning_anchor,
1520
1579
  $._regex_end_anchor,
1521
1580
  $._regex_period,
1522
1581
  $._regex_quoted_escape,
1582
+ $._escape_prefix,
1523
1583
  $._regex_newline_escape,
1524
1584
  $._regex_escaped_delimiter,
1525
1585
  $._regex_special_escaped_delimiter,
@@ -1534,9 +1594,6 @@ function externalTokens($, mode) {
1534
1594
  $._regex_bre_plus_escape,
1535
1595
  $._regex_bre_subexpression_caret,
1536
1596
  $._regex_bre_subexpression_dollar,
1537
- $._bre_vertical_line_escape_marker,
1538
- $._bre_question_mark_escape_marker,
1539
- $._bre_plus_escape_marker,
1540
1597
  $._regex_unmatched_interval_close,
1541
1598
  ]
1542
1599
  : []),
@@ -1568,6 +1625,7 @@ function externalTokens($, mode) {
1568
1625
  $._regex_bracket_trailing_hyphen,
1569
1626
  $._regex_open_colon,
1570
1627
  $._regex_class_name,
1628
+ $._regex_invalid_class_name,
1571
1629
  $._regex_colon_close,
1572
1630
  $._regex_open_dot,
1573
1631
  $._regex_coll_elem_single,
@@ -1616,6 +1674,7 @@ function externalTokens($, mode) {
1616
1674
  $._comment_text,
1617
1675
  $._file_argument,
1618
1676
  $._substitution_wfile_argument,
1677
+ $._substitution_wfile_continuation,
1619
1678
  $._line_word,
1620
1679
  $._argument_separator,
1621
1680
  $._right_brace,