tree-sitter-sed 0.19.0 → 0.20.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
@@ -1,6 +1,3 @@
1
- import { defineIssueRules, issueField, namedExternal } from "./dsl.js";
2
- import { breRules, ereRules } from "./regex.js";
3
-
4
1
  const functionDefinitions = [
5
2
  { rule: "block_function", spelling: "{", form: "block" },
6
3
  {
@@ -96,6 +93,20 @@ const unknownFunctionCharacter = new RegExp(
96
93
  .join("")}]`,
97
94
  );
98
95
 
96
+ function defineIssueRules(definitions) {
97
+ const rules = {};
98
+ for (const { reason, id = reason, outcome, rule } of definitions) {
99
+ rules[`_${id}_reason`] = rule;
100
+ rules[`_${id}_outcome`] = ($) => alias($[`_${id}_reason`], $[reason]);
101
+ rules[`_${id}_issue`] = ($) => alias($[`_${id}_outcome`], $[outcome]);
102
+ }
103
+ return rules;
104
+ }
105
+
106
+ function issueField($, id) {
107
+ return field("issue", alias($[`_${id}_issue`], $.syntax_issue));
108
+ }
109
+
99
110
  function missingAtEndOrBoundary($, reason) {
100
111
  return choice(
101
112
  issueField($, reason),
@@ -120,7 +131,7 @@ function fileOperandForms($, name, operand) {
120
131
 
121
132
  function sourcePiece($, external, leaf) {
122
133
  return choice(
123
- namedExternal($, external, leaf),
134
+ alias(external, $[leaf]),
124
135
  issueField($, "nul_character"),
125
136
  issueField($, "invalid_encoding"),
126
137
  );
@@ -158,15 +169,18 @@ function functionVerb($, spelling) {
158
169
  return field("verb", alias(spelling, $.function_verb));
159
170
  }
160
171
 
161
- function substitutionFlag($, kind, seen) {
162
- if ((kind === 1 && seen & 2) || (kind === 2 && seen & 1)) {
163
- return issueField(
164
- $,
165
- kind === 1 ? "conflicting_global_flag" : "conflicting_occurrence_flag",
166
- );
167
- }
168
- return kind === 1 ? alias("g", $.global_flag) : $.occurrence_flag;
169
- }
172
+ const exclusiveSubstitutionFlags = [
173
+ {
174
+ bit: 1,
175
+ flag: ($) => alias("g", $.global_flag),
176
+ conflict: "conflicting_global_flag",
177
+ },
178
+ {
179
+ bit: 2,
180
+ flag: ($) => $.occurrence_flag,
181
+ conflict: "conflicting_occurrence_flag",
182
+ },
183
+ ];
170
184
 
171
185
  function substitutionFlagRules() {
172
186
  const rules = {};
@@ -189,14 +203,14 @@ function substitutionFlagRules() {
189
203
  ]),
190
204
  ];
191
205
  const transitions = [];
192
- for (const kind of [1, 2]) {
193
- const flag = substitutionFlag($, kind, seen);
194
- if (seen & kind) {
195
- steady.push(flag);
206
+ for (const { bit, flag, conflict } of exclusiveSubstitutionFlags) {
207
+ const symbol = seen & ~bit ? issueField($, conflict) : flag($);
208
+ if (seen & bit) {
209
+ steady.push(symbol);
196
210
  } else {
197
- const tail = $[`_flags_${ending}_${seen | kind}`];
211
+ const tail = $[`_flags_${ending}_${seen | bit}`];
198
212
  transitions.push(
199
- seq(flag, ending === "write" ? tail : optional(tail)),
213
+ seq(symbol, ending === "write" ? tail : optional(tail)),
200
214
  );
201
215
  }
202
216
  }
@@ -245,7 +259,7 @@ function substitutionFlagRules() {
245
259
  }
246
260
 
247
261
  function delimiter($, name) {
248
- return namedExternal($, $[`_${name}`], "delimiter");
262
+ return alias($[`_${name}`], $.delimiter);
249
263
  }
250
264
 
251
265
  function missingOpeningDelimiter($) {
@@ -286,7 +300,9 @@ function writeCommandUnit($, block = false) {
286
300
  $.command_separator,
287
301
  ),
288
302
  issueField($, "undefined_write_command_separator"),
289
- issueField($, "missing_separator_before_unmatched_brace"),
303
+ ...(block
304
+ ? []
305
+ : [issueField($, "missing_separator_before_unmatched_brace")]),
290
306
  ),
291
307
  );
292
308
  }
@@ -323,11 +339,7 @@ function commandListRules() {
323
339
  seq(
324
340
  field(
325
341
  "suppression",
326
- namedExternal(
327
- $,
328
- $._default_output_suppression,
329
- "default_output_suppression",
330
- ),
342
+ alias($._default_output_suppression, $.default_output_suppression),
331
343
  ),
332
344
  repeat(sourcePiece($, $._comment_text, "comment_text")),
333
345
  ),
@@ -433,8 +445,13 @@ function omittedAddress($) {
433
445
  );
434
446
  }
435
447
 
448
+ const regularExpressionRules = {
449
+ bre: { expression: "basic_reg_exp", duplication: "bre_dupl_symbol" },
450
+ ere: { expression: "extended_reg_exp", duplication: "ere_dupl_symbol" },
451
+ };
452
+
436
453
  function addressRules(mode) {
437
- const expression = mode === "bre" ? "basic_reg_exp" : "extended_reg_exp";
454
+ const { expression } = regularExpressionRules[mode];
438
455
 
439
456
  function addressChoice($) {
440
457
  return choice(
@@ -588,7 +605,7 @@ function delimitedFunction($, spelling, name, first, middleReason, rest) {
588
605
  }
589
606
 
590
607
  function operandRules(mode) {
591
- const expression = mode === "bre" ? "basic_reg_exp" : "extended_reg_exp";
608
+ const { expression } = regularExpressionRules[mode];
592
609
 
593
610
  return {
594
611
  substitute_function: ($) =>
@@ -787,7 +804,7 @@ function functionRules() {
787
804
  seq(
788
805
  field(
789
806
  "separator",
790
- namedExternal($, $._argument_separator, "argument_separator"),
807
+ alias($._argument_separator, $.argument_separator),
791
808
  ),
792
809
  optional(field("label", $.label)),
793
810
  ),
@@ -980,6 +997,429 @@ function sedRules(mode) {
980
997
  };
981
998
  }
982
999
 
1000
+ const nonportableRangeClasses = ["character_class", "equivalence_class"];
1001
+
1002
+ function intervalExpression($, opening, closing) {
1003
+ const piece = (name) =>
1004
+ choice(
1005
+ field(name, $.duplication_count),
1006
+ field(name, alias($._regex_interval_escaped_count, $.escaped_delimiter)),
1007
+ issueField($, "invalid_interval_character"),
1008
+ ...(opening === "{"
1009
+ ? [issueField($, "incomplete_regular_expression_escape")]
1010
+ : []),
1011
+ issueField($, "invalid_regular_expression_character"),
1012
+ issueField($, "invalid_encoding"),
1013
+ seq(
1014
+ $._escape_prefix,
1015
+ choice(
1016
+ issueField($, "escaped_invalid_regular_expression_character"),
1017
+ issueField($, "invalid_encoding"),
1018
+ ),
1019
+ ),
1020
+ );
1021
+ return seq(
1022
+ alias($._regex_interval_open, opening),
1023
+ choice(
1024
+ repeat1(piece("minimum")),
1025
+ issueField($, "missing_interval_minimum"),
1026
+ issueField($, "incomplete_interval_minimum"),
1027
+ ),
1028
+ optional(
1029
+ seq(
1030
+ choice(
1031
+ alias($._regex_interval_separator, ","),
1032
+ alias($._regex_interval_escaped_separator, $.escaped_delimiter),
1033
+ ),
1034
+ repeat(
1035
+ choice(
1036
+ piece("maximum"),
1037
+ issueField($, "unexpected_interval_separator"),
1038
+ ),
1039
+ ),
1040
+ ),
1041
+ ),
1042
+ choice(
1043
+ alias($._regex_interval_close, closing),
1044
+ issueField($, "missing_interval_close"),
1045
+ issueField($, "incomplete_interval"),
1046
+ ...(opening === "\\{"
1047
+ ? [
1048
+ issueField($, "invalid_interval_close"),
1049
+ issueField($, "incomplete_interval_close"),
1050
+ ]
1051
+ : []),
1052
+ ),
1053
+ );
1054
+ }
1055
+
1056
+ function compoundBracketExpression(
1057
+ $,
1058
+ openingExternal,
1059
+ marker,
1060
+ contentField,
1061
+ content,
1062
+ closingExternal,
1063
+ ...payloadIssues
1064
+ ) {
1065
+ const closingIssues = [
1066
+ issueField($, "missing_bracket_term_close"),
1067
+ issueField($, "incomplete_bracket_term"),
1068
+ ];
1069
+ const closing = seq(
1070
+ alias(closingExternal, marker),
1071
+ choice("]", ...closingIssues),
1072
+ );
1073
+ const payload = repeat1(
1074
+ choice(
1075
+ field(contentField, content),
1076
+ issueField($, "invalid_regular_expression_character"),
1077
+ issueField($, "invalid_encoding"),
1078
+ ...payloadIssues.map((reason) => issueField($, reason)),
1079
+ ),
1080
+ );
1081
+ return seq(
1082
+ alias(openingExternal, "["),
1083
+ marker,
1084
+ choice(
1085
+ payload,
1086
+ issueField($, "missing_bracket_term_payload"),
1087
+ issueField($, "incomplete_bracket_term_payload"),
1088
+ ),
1089
+ choice(closing, ...closingIssues),
1090
+ );
1091
+ }
1092
+
1093
+ function bracketListBody($, list) {
1094
+ return choice(
1095
+ list,
1096
+ issueField($, "missing_bracket_list"),
1097
+ issueField($, "incomplete_missing_bracket_list"),
1098
+ );
1099
+ }
1100
+
1101
+ function subexpressionClose($, closing) {
1102
+ return choice(
1103
+ field("closing", alias($._regex_group_close, closing)),
1104
+ issueField($, "unclosed_subexpression"),
1105
+ issueField($, "incomplete_unclosed_subexpression"),
1106
+ );
1107
+ }
1108
+
1109
+ function bracketExpression($, ambiguous) {
1110
+ return seq(
1111
+ alias($._regex_bracket_open, "["),
1112
+ bracketListBody($, choice($.matching_list, $.nonmatching_list)),
1113
+ ...(ambiguous ? [$._ambiguous_bracket_expression_marker] : []),
1114
+ choice(
1115
+ alias($._regex_bracket_close, "]"),
1116
+ issueField($, "unclosed_bracket_expression"),
1117
+ issueField($, "incomplete_unclosed_bracket_expression"),
1118
+ ),
1119
+ );
1120
+ }
1121
+
1122
+ function rangeOperator($) {
1123
+ return alias($._regex_bracket_hyphen, "-");
1124
+ }
1125
+
1126
+ function nonportableRangeRules() {
1127
+ const rules = {};
1128
+ for (const kind of nonportableRangeClasses) {
1129
+ rules[`_${kind}_start_range`] = ($) =>
1130
+ seq(issueField($, `${kind}_range_start`), rangeOperator($));
1131
+ }
1132
+ for (const kind of nonportableRangeClasses) {
1133
+ rules[`_${kind}_end_range`] = ($) => issueField($, `${kind}_range_end`);
1134
+ }
1135
+ return rules;
1136
+ }
1137
+
1138
+ function bracketRules() {
1139
+ return {
1140
+ bracket_expression: ($) => bracketExpression($, false),
1141
+
1142
+ _ambiguous_bracket_expression: ($) => bracketExpression($, true),
1143
+
1144
+ _bracket_expression: ($) =>
1145
+ choice(
1146
+ $.bracket_expression,
1147
+ issueField($, "ambiguous_bracket_expression"),
1148
+ ),
1149
+
1150
+ matching_list: ($) => $.bracket_list,
1151
+
1152
+ nonmatching_list: ($) =>
1153
+ seq(
1154
+ alias($._regex_bracket_negation, "^"),
1155
+ bracketListBody($, $.bracket_list),
1156
+ ),
1157
+
1158
+ bracket_list: ($) =>
1159
+ seq(
1160
+ $.follow_list,
1161
+ optional(alias($._regex_bracket_trailing_hyphen, "-")),
1162
+ ),
1163
+
1164
+ follow_list: ($) => repeat1($.expression_term),
1165
+
1166
+ expression_term: ($) =>
1167
+ choice(
1168
+ $.single_expression,
1169
+ $.range_expression,
1170
+ issueField($, "shared_range_endpoint"),
1171
+ ),
1172
+
1173
+ single_expression: ($) =>
1174
+ choice($.end_range, $.character_class, $.equivalence_class),
1175
+
1176
+ range_expression: ($) =>
1177
+ seq(
1178
+ choice(
1179
+ $.start_range,
1180
+ ...nonportableRangeClasses.map((kind) =>
1181
+ alias($[`_${kind}_start_range`], $.start_range),
1182
+ ),
1183
+ ),
1184
+ choice(
1185
+ $.end_range,
1186
+ ...nonportableRangeClasses.map((kind) =>
1187
+ alias($[`_${kind}_end_range`], $.end_range),
1188
+ ),
1189
+ alias($._regex_bracket_range_end_hyphen, "-"),
1190
+ ),
1191
+ ),
1192
+
1193
+ ...nonportableRangeRules(),
1194
+
1195
+ start_range: ($) => seq($.end_range, rangeOperator($)),
1196
+
1197
+ end_range: ($) =>
1198
+ choice(
1199
+ alias($._regex_bracket_literal, $.collating_element_single),
1200
+ $.collating_symbol,
1201
+ issueField($, "invalid_regular_expression_character"),
1202
+ issueField($, "invalid_encoding"),
1203
+ ),
1204
+
1205
+ collating_symbol: ($) =>
1206
+ compoundBracketExpression(
1207
+ $,
1208
+ $._regex_open_dot,
1209
+ ".",
1210
+ "element",
1211
+ choice(
1212
+ alias($._regex_coll_elem_single, $.collating_element_single),
1213
+ alias($._regex_coll_elem_multi, $.collating_element_multi),
1214
+ alias($._regex_meta_char, $.meta_character),
1215
+ ),
1216
+ $._regex_dot_close,
1217
+ ),
1218
+
1219
+ equivalence_class: ($) =>
1220
+ compoundBracketExpression(
1221
+ $,
1222
+ $._regex_open_equal,
1223
+ "=",
1224
+ "element",
1225
+ choice(
1226
+ alias($._regex_coll_elem_single, $.collating_element_single),
1227
+ alias($._regex_coll_elem_multi, $.collating_element_multi),
1228
+ ),
1229
+ $._regex_equal_close,
1230
+ "equivalence_class_meta_character",
1231
+ "incomplete_equivalence_class_meta_character",
1232
+ ),
1233
+
1234
+ character_class: ($) =>
1235
+ compoundBracketExpression(
1236
+ $,
1237
+ $._regex_open_colon,
1238
+ ":",
1239
+ "name",
1240
+ alias($._regex_class_name, $.class_name),
1241
+ $._regex_colon_close,
1242
+ "invalid_character_class_name",
1243
+ ),
1244
+ };
1245
+ }
1246
+
1247
+ function regularExpressionEscape($) {
1248
+ return choice(
1249
+ $.quoted_character,
1250
+ seq(
1251
+ $._escape_prefix,
1252
+ choice(
1253
+ issueField($, "escaped_invalid_regular_expression_character"),
1254
+ issueField($, "invalid_encoding"),
1255
+ ),
1256
+ ),
1257
+ $.escaped_delimiter,
1258
+ issueField($, "ordinary_character_escape"),
1259
+ issueField($, "incomplete_regular_expression_escape"),
1260
+ issueField($, "forbidden_regular_expression_newline"),
1261
+ );
1262
+ }
1263
+
1264
+ function oneCharOrCollElem($, ...additional) {
1265
+ return choice(
1266
+ issueField($, "invalid_regular_expression_character"),
1267
+ issueField($, "invalid_encoding"),
1268
+ $.ordinary_character,
1269
+ regularExpressionEscape($),
1270
+ $.sed_newline_escape,
1271
+ alias($._regex_period, "."),
1272
+ $._bracket_expression,
1273
+ issueField($, "special_delimiter_escape"),
1274
+ ...additional,
1275
+ );
1276
+ }
1277
+
1278
+ function commonRegularExpressionRules() {
1279
+ return {
1280
+ duplication_count: ($) => $._regex_dup_count,
1281
+
1282
+ ordinary_character: ($) => $._regex_literal,
1283
+
1284
+ quoted_character: ($) => $._regex_quoted_escape,
1285
+
1286
+ escaped_delimiter: ($) => $._regex_escaped_delimiter,
1287
+
1288
+ sed_newline_escape: ($) => $._regex_newline_escape,
1289
+
1290
+ ...bracketRules(),
1291
+ };
1292
+ }
1293
+
1294
+ function breRules() {
1295
+ return {
1296
+ ...commonRegularExpressionRules(),
1297
+ basic_reg_exp: ($) => $.bre_branch,
1298
+
1299
+ bre_branch: ($) => repeat1($.bre_expression),
1300
+
1301
+ bre_expression: ($) =>
1302
+ prec.right(
1303
+ choice(
1304
+ seq(
1305
+ alias($._regex_beginning_anchor, "^"),
1306
+ optional($.simple_bre),
1307
+ optional(alias($._regex_end_anchor, "$")),
1308
+ ),
1309
+ seq($.simple_bre, optional(alias($._regex_end_anchor, "$"))),
1310
+ alias($._regex_end_anchor, "$"),
1311
+ ),
1312
+ ),
1313
+
1314
+ simple_bre: ($) =>
1315
+ seq(
1316
+ choice(
1317
+ seq($.nondupl_bre, optional($.bre_dupl_symbol)),
1318
+ issueField($, "leading_duplication_symbol"),
1319
+ ),
1320
+ repeat(issueField($, "adjacent_duplication_symbol")),
1321
+ ),
1322
+
1323
+ nondupl_bre: ($) =>
1324
+ choice(
1325
+ $.one_char_or_coll_elem_bre,
1326
+ seq(
1327
+ field("opening", alias($._regex_group_open, "\\(")),
1328
+ optional(field("expression", $.basic_reg_exp)),
1329
+ subexpressionClose($, "\\)"),
1330
+ ),
1331
+ $.backreference,
1332
+ issueField($, "unmatched_subexpression_close"),
1333
+ issueField($, "unmatched_interval_close"),
1334
+ ),
1335
+
1336
+ backreference: ($) => $._regex_backreference,
1337
+
1338
+ one_char_or_coll_elem_bre: ($) =>
1339
+ oneCharOrCollElem(
1340
+ $,
1341
+ issueField($, "bre_vertical_line_escape"),
1342
+ issueField($, "bre_question_mark_escape"),
1343
+ issueField($, "bre_plus_escape"),
1344
+ issueField($, "bre_subexpression_right_anchor"),
1345
+ issueField($, "bre_subexpression_left_anchor"),
1346
+ ),
1347
+
1348
+ bre_dupl_symbol: ($) =>
1349
+ choice(alias($._regex_zero_or_more, "*"), $._bre_interval),
1350
+
1351
+ _bre_interval: ($) => intervalExpression($, "\\{", "\\}"),
1352
+ };
1353
+ }
1354
+
1355
+ function ereRules() {
1356
+ return {
1357
+ ...commonRegularExpressionRules(),
1358
+ extended_reg_exp: ($) =>
1359
+ choice(
1360
+ $.ere_branch,
1361
+ seq(
1362
+ choice($.ere_branch, $._empty_ere_branch),
1363
+ repeat1(
1364
+ seq(
1365
+ alias($._regex_alternation_operator, "|"),
1366
+ choice($.ere_branch, $._empty_ere_branch),
1367
+ ),
1368
+ ),
1369
+ ),
1370
+ ),
1371
+
1372
+ _empty_ere_branch: ($) =>
1373
+ choice(
1374
+ issueField($, "empty_alternative"),
1375
+ issueField($, "incomplete_alternative"),
1376
+ ),
1377
+
1378
+ ere_branch: ($) => repeat1($.ere_expression),
1379
+
1380
+ ere_expression: ($) =>
1381
+ prec.left(
1382
+ 1,
1383
+ seq(
1384
+ choice(
1385
+ $.one_char_or_coll_elem_ere,
1386
+ alias($._regex_beginning_anchor, "^"),
1387
+ alias($._regex_end_anchor, "$"),
1388
+ seq(
1389
+ field("opening", alias($._regex_group_open, "(")),
1390
+ optional(field("expression", $.extended_reg_exp)),
1391
+ subexpressionClose($, ")"),
1392
+ ),
1393
+ issueField($, "leading_duplication_symbol"),
1394
+ ),
1395
+ repeat(
1396
+ choice(
1397
+ $.ere_dupl_symbol,
1398
+ issueField($, "adjacent_duplication_symbol"),
1399
+ ),
1400
+ ),
1401
+ ),
1402
+ ),
1403
+
1404
+ one_char_or_coll_elem_ere: ($) => oneCharOrCollElem($),
1405
+
1406
+ ere_dupl_symbol: ($) =>
1407
+ seq(
1408
+ choice(
1409
+ alias($._regex_zero_or_more, "*"),
1410
+ alias($._regex_one_or_more, "+"),
1411
+ alias($._regex_zero_or_one, "?"),
1412
+ $._ere_interval,
1413
+ ),
1414
+ optional(field("modifier", $.repetition_modifier)),
1415
+ ),
1416
+
1417
+ _ere_interval: ($) => intervalExpression($, "{", "}"),
1418
+
1419
+ repetition_modifier: ($) => $._regex_repetition_modifier,
1420
+ };
1421
+ }
1422
+
983
1423
  const missingCommandDefinitions = [
984
1424
  { reason: "missing_function", atBoundary: true },
985
1425
  { reason: "missing_label", atBoundary: true },
@@ -1058,14 +1498,13 @@ function issueDefinitions(mode) {
1058
1498
  id: "equivalence_class_meta_character",
1059
1499
  reason: "invalid_equivalence_class_element",
1060
1500
  outcome: "undefined_syntax",
1061
- rule: ($) => namedExternal($, $._regex_meta_char, "meta_character"),
1501
+ rule: ($) => alias($._regex_meta_char, $.meta_character),
1062
1502
  },
1063
1503
  {
1064
1504
  id: "incomplete_equivalence_class_meta_character",
1065
1505
  reason: "invalid_equivalence_class_element",
1066
1506
  outcome: "incomplete_syntax",
1067
- rule: ($) =>
1068
- namedExternal($, $._regex_incomplete_meta_char, "meta_character"),
1507
+ rule: ($) => alias($._regex_incomplete_meta_char, $.meta_character),
1069
1508
  },
1070
1509
  {
1071
1510
  reason: "missing_bracket_term_payload",
@@ -1088,19 +1527,18 @@ function issueDefinitions(mode) {
1088
1527
  outcome: "invalid_syntax",
1089
1528
  rule: ($) => $._nul_character,
1090
1529
  },
1091
- ...[
1092
- ["escaped_nul_character", "nul_character", "nonconforming_syntax"],
1093
- [
1094
- "escaped_invalid_regular_expression_character",
1095
- "invalid_regular_expression_character",
1096
- "invalid_syntax",
1097
- ],
1098
- ].map(([id, reason, outcome]) => ({
1099
- id,
1100
- reason,
1101
- outcome,
1102
- rule: ($) => $._escaped_nul_character,
1103
- })),
1530
+ {
1531
+ id: "escaped_nul_character",
1532
+ reason: "nul_character",
1533
+ outcome: "nonconforming_syntax",
1534
+ rule: ($) => $._single_nul_character,
1535
+ },
1536
+ {
1537
+ id: "escaped_invalid_regular_expression_character",
1538
+ reason: "invalid_regular_expression_character",
1539
+ outcome: "invalid_syntax",
1540
+ rule: ($) => $._single_nul_character,
1541
+ },
1104
1542
  {
1105
1543
  reason: "invalid_encoding",
1106
1544
  outcome: "invalid_syntax",
@@ -1179,51 +1617,47 @@ function issueDefinitions(mode) {
1179
1617
  rule: ($) =>
1180
1618
  choice(
1181
1619
  alias($._regex_interval_separator, ","),
1182
- namedExternal(
1183
- $,
1184
- $._regex_interval_escaped_separator,
1185
- "escaped_delimiter",
1186
- ),
1620
+ alias($._regex_interval_escaped_separator, $.escaped_delimiter),
1187
1621
  ),
1188
1622
  },
1189
- ...["minimum", "close"].flatMap((part) => [
1190
- {
1191
- reason: `missing_interval_${part}`,
1192
- outcome: "undefined_syntax",
1193
- rule: ($) => $[`_regex_missing_interval_${part}`],
1194
- },
1195
- ...(part === "minimum"
1196
- ? [
1197
- {
1198
- id: "incomplete_interval_minimum",
1199
- reason: "missing_interval_minimum",
1200
- outcome: "incomplete_syntax",
1201
- rule: ($) => $._regex_incomplete_interval_minimum,
1202
- },
1203
- ]
1204
- : []),
1205
- ]),
1206
1623
  {
1207
- reason: "invalid_interval_close",
1624
+ reason: "missing_interval_minimum",
1208
1625
  outcome: "undefined_syntax",
1209
- rule: ($) => $._regex_invalid_interval_close,
1626
+ rule: ($) => $._regex_missing_interval_minimum,
1210
1627
  },
1211
1628
  {
1212
- id: "incomplete_interval_close",
1213
- reason: "invalid_interval_close",
1629
+ id: "incomplete_interval_minimum",
1630
+ reason: "missing_interval_minimum",
1214
1631
  outcome: "incomplete_syntax",
1215
- rule: ($) => $._regex_incomplete_interval_close,
1632
+ rule: ($) => $._regex_incomplete_interval_minimum,
1633
+ },
1634
+ {
1635
+ reason: "missing_interval_close",
1636
+ outcome: "undefined_syntax",
1637
+ rule: ($) => $._regex_missing_interval_close,
1216
1638
  },
1639
+ ...(mode === "bre"
1640
+ ? [
1641
+ {
1642
+ reason: "invalid_interval_close",
1643
+ outcome: "undefined_syntax",
1644
+ rule: ($) => $._regex_invalid_interval_close,
1645
+ },
1646
+ {
1647
+ id: "incomplete_interval_close",
1648
+ reason: "invalid_interval_close",
1649
+ outcome: "incomplete_syntax",
1650
+ rule: ($) => $._regex_incomplete_interval_close,
1651
+ },
1652
+ ]
1653
+ : []),
1217
1654
  {
1218
1655
  reason: "leading_duplication_symbol",
1219
1656
  outcome: "undefined_syntax",
1220
1657
  rule: ($) =>
1221
1658
  seq(
1222
1659
  $._regex_leading_duplication_marker,
1223
- field(
1224
- "operator",
1225
- mode === "bre" ? $.bre_dupl_symbol : $.ere_dupl_symbol,
1226
- ),
1660
+ field("operator", $[regularExpressionRules[mode].duplication]),
1227
1661
  ),
1228
1662
  },
1229
1663
  {
@@ -1232,10 +1666,7 @@ function issueDefinitions(mode) {
1232
1666
  rule: ($) =>
1233
1667
  seq(
1234
1668
  $._regex_adjacent_duplication_marker,
1235
- field(
1236
- "operator",
1237
- mode === "bre" ? $.bre_dupl_symbol : $.ere_dupl_symbol,
1238
- ),
1669
+ field("operator", $[regularExpressionRules[mode].duplication]),
1239
1670
  ),
1240
1671
  },
1241
1672
  ...(mode === "ere"
@@ -1299,20 +1730,15 @@ function issueDefinitions(mode) {
1299
1730
  reason: "special_delimiter_escape",
1300
1731
  outcome: "unspecified_syntax",
1301
1732
  rule: ($) =>
1302
- namedExternal(
1303
- $,
1304
- $._regex_special_escaped_delimiter,
1305
- "escaped_delimiter",
1306
- ),
1733
+ alias($._regex_special_escaped_delimiter, $.escaped_delimiter),
1307
1734
  },
1308
1735
  {
1309
1736
  reason: "replacement_ampersand_delimiter_escape",
1310
1737
  outcome: "unspecified_syntax",
1311
1738
  rule: ($) =>
1312
- namedExternal(
1313
- $,
1739
+ alias(
1314
1740
  $._replacement_ampersand_escaped_delimiter,
1315
- "replacement_escaped_delimiter",
1741
+ $.replacement_escaped_delimiter,
1316
1742
  ),
1317
1743
  },
1318
1744
  {
@@ -1386,7 +1812,10 @@ function issueDefinitions(mode) {
1386
1812
  reason: "unknown_function",
1387
1813
  outcome: "nonconforming_syntax",
1388
1814
  rule: ($) =>
1389
- choice(token(prec(-2, unknownFunctionCharacter)), $._nul_character),
1815
+ choice(
1816
+ token(prec(-2, unknownFunctionCharacter)),
1817
+ $._single_nul_character,
1818
+ ),
1390
1819
  },
1391
1820
  {
1392
1821
  id: "reserved_unknown_function",
@@ -1487,12 +1916,12 @@ function issueDefinitions(mode) {
1487
1916
  {
1488
1917
  reason: "invalid_substitution_flag",
1489
1918
  outcome: "nonconforming_syntax",
1490
- rule: ($) => choice($._invalid_substitution_flag, $._nul_character),
1919
+ rule: ($) => $._invalid_substitution_flag,
1491
1920
  },
1492
1921
  {
1493
1922
  reason: "invalid_delimiter",
1494
1923
  outcome: "nonconforming_syntax",
1495
- rule: ($) => choice(token(/\\/), $._nul_character),
1924
+ rule: ($) => choice(token(/\\/), $._single_nul_character),
1496
1925
  },
1497
1926
  {
1498
1927
  reason: "unterminated_regular_expression",
@@ -1620,158 +2049,155 @@ function issueDefinitions(mode) {
1620
2049
  ];
1621
2050
  }
1622
2051
 
1623
- function externalTokens($, mode) {
2052
+ export function externalTokens(mode) {
1624
2053
  return [
1625
- $._regex_address_start,
1626
- $._escaped_regex_address_start,
1627
- $._regex_address_end,
1628
- $._substitute_start,
1629
- $._substitute_middle,
1630
- $._substitute_end,
1631
- $._translate_start,
1632
- $._translate_middle,
1633
- $._translate_end,
1634
- $._regex_literal,
1635
- $._invalid_character,
1636
- $._nul_character,
1637
- $._escaped_nul_character,
1638
- $._regex_beginning_anchor,
1639
- $._regex_end_anchor,
1640
- $._regex_period,
1641
- $._regex_quoted_escape,
1642
- $._escape_prefix,
1643
- $._regex_newline_escape,
1644
- $._regex_escaped_delimiter,
1645
- $._regex_special_escaped_delimiter,
1646
- $._regex_group_open,
1647
- $._regex_group_close,
1648
- $._regex_unclosed_group,
2054
+ "regex_address_start",
2055
+ "escaped_regex_address_start",
2056
+ "regex_address_end",
2057
+ "substitute_start",
2058
+ "substitute_middle",
2059
+ "substitute_end",
2060
+ "translate_start",
2061
+ "translate_middle",
2062
+ "translate_end",
2063
+ "regex_literal",
2064
+ "invalid_character",
2065
+ "nul_character",
2066
+ "single_nul_character",
2067
+ "regex_beginning_anchor",
2068
+ "regex_end_anchor",
2069
+ "regex_period",
2070
+ "regex_quoted_escape",
2071
+ "escape_prefix",
2072
+ "regex_newline_escape",
2073
+ "regex_escaped_delimiter",
2074
+ "regex_special_escaped_delimiter",
2075
+ "regex_group_open",
2076
+ "regex_group_close",
2077
+ "regex_unclosed_group",
1649
2078
  ...(mode === "bre"
1650
2079
  ? [
1651
- $._regex_unmatched_group_close,
1652
- $._regex_bre_vertical_line_escape,
1653
- $._regex_bre_question_mark_escape,
1654
- $._regex_bre_plus_escape,
1655
- $._regex_bre_subexpression_caret,
1656
- $._regex_bre_subexpression_dollar,
1657
- $._regex_unmatched_interval_close,
2080
+ "regex_unmatched_group_close",
2081
+ "regex_bre_vertical_line_escape",
2082
+ "regex_bre_question_mark_escape",
2083
+ "regex_bre_plus_escape",
2084
+ "regex_bre_subexpression_caret",
2085
+ "regex_bre_subexpression_dollar",
2086
+ "regex_unmatched_interval_close",
1658
2087
  ]
1659
2088
  : []),
1660
- ...(mode === "ere" ? [$._regex_alternation_operator] : []),
1661
- $._regex_leading_duplication_marker,
1662
- $._regex_adjacent_duplication_marker,
1663
- $._regex_zero_or_more,
2089
+ ...(mode === "ere" ? ["regex_alternation_operator"] : []),
2090
+ "regex_leading_duplication_marker",
2091
+ "regex_adjacent_duplication_marker",
2092
+ "regex_zero_or_more",
1664
2093
  ...(mode === "ere"
1665
- ? [
1666
- $._regex_one_or_more,
1667
- $._regex_zero_or_one,
1668
- $._regex_repetition_modifier,
1669
- ]
2094
+ ? ["regex_one_or_more", "regex_zero_or_one", "regex_repetition_modifier"]
2095
+ : []),
2096
+ "regex_interval_open",
2097
+ "regex_dup_count",
2098
+ "regex_interval_escaped_count",
2099
+ "regex_interval_escaped_separator",
2100
+ "regex_interval_separator",
2101
+ "regex_interval_close",
2102
+ ...(mode === "bre" ? ["regex_backreference"] : []),
2103
+ "regex_invalid_interval",
2104
+ "regex_missing_interval_minimum",
2105
+ "regex_incomplete_interval_minimum",
2106
+ "regex_missing_interval_close",
2107
+ ...(mode === "bre"
2108
+ ? ["regex_invalid_interval_close", "regex_incomplete_interval_close"]
1670
2109
  : []),
1671
- $._regex_interval_open,
1672
- $._regex_dup_count,
1673
- $._regex_interval_escaped_count,
1674
- $._regex_interval_escaped_separator,
1675
- $._regex_interval_separator,
1676
- $._regex_interval_close,
1677
- ...(mode === "bre" ? [$._regex_backreference] : []),
1678
- $._regex_invalid_interval,
1679
- $._regex_missing_interval_minimum,
1680
- $._regex_incomplete_interval_minimum,
1681
- $._regex_missing_interval_close,
1682
- $._regex_invalid_interval_close,
1683
- $._regex_incomplete_interval_close,
1684
- $._regex_nonportable_escape,
1685
- $._regex_incomplete_escape,
1686
- $._regex_bracket_open,
1687
- $._regex_bracket_close,
1688
- $._regex_bracket_literal,
1689
- $._regex_bracket_negation,
1690
- $._regex_bracket_hyphen,
1691
- $._regex_bracket_range_end_hyphen,
1692
- $._regex_bracket_trailing_hyphen,
1693
- $._regex_open_colon,
1694
- $._regex_class_name,
1695
- $._regex_invalid_class_name,
1696
- $._regex_colon_close,
1697
- $._regex_open_dot,
1698
- $._regex_coll_elem_single,
1699
- $._regex_coll_elem_multi,
1700
- $._regex_meta_char,
1701
- $._regex_incomplete_meta_char,
1702
- $._regex_dot_close,
1703
- $._regex_open_equal,
1704
- $._regex_equal_close,
1705
- $._regex_missing_bracket_term_close,
1706
- $._regex_missing_bracket_term_payload,
1707
- $._regex_incomplete_bracket_term_payload,
1708
- $._regex_shared_range_endpoint,
1709
- $._ambiguous_bracket_expression_marker,
1710
- $._missing_bracket_list_marker,
1711
- $._unclosed_bracket_expression_marker,
1712
- $._nonportable_range_start_marker,
1713
- $._nonportable_range_end_marker,
1714
- $._regex_unterminated_address,
1715
- $._regex_unterminated_substitute,
1716
- $._replacement_literal,
1717
- $._replacement_match_reference,
1718
- $._replacement_backreference,
1719
- $._replacement_escaped_delimiter,
1720
- $._replacement_ampersand_escaped_delimiter,
1721
- $._replacement_escape_sequence,
1722
- $._replacement_nonportable_escape,
1723
- $._replacement_escaped_newline,
1724
- $._replacement_incomplete_escape,
1725
- $._replacement_unterminated,
1726
- $._translate_literal,
1727
- $._translate_escaped_delimiter,
1728
- $._translate_escape,
1729
- $._translate_nonportable_escape,
1730
- $._translate_incomplete_escape,
1731
- $._translate_unterminated_source,
1732
- $._translate_unterminated_destination,
1733
- $._invalid_substitution_flag,
1734
- $._flag_after_write_marker,
1735
- $._write_terminal_separator,
1736
- $._write_block_terminal_separator,
1737
- $._write_following_separator,
1738
- $._text_command_start,
1739
- $._text_incomplete_introducer,
1740
- $._text_literal,
1741
- $._text_backslash_escape,
1742
- $._text_escaped_newline,
1743
- $._text_unspecified_escape,
1744
- $._text_line_end,
1745
- $._text_eof,
1746
- $._default_output_suppression,
1747
- $._comment_text,
1748
- $._file_argument,
1749
- $._substitution_wfile_argument,
1750
- $._substitution_wfile_continuation,
1751
- $._line_word,
1752
- $._label_start,
1753
- $._long_label_start,
1754
- $._label_literal,
1755
- $._nonportable_label_character,
1756
- $._argument_separator,
1757
- $._brace_leading_blanks,
1758
- $._block_trailing_blanks,
1759
- $._empty_command_marker,
1760
- $._reserved_unknown_function_token,
1761
- $._regex_incomplete_group,
1762
- $._regex_incomplete_bracket_term,
1763
- $._regex_incomplete_interval,
1764
- $._regex_forbidden_newline_escape,
1765
- $._regex_line_unterminated_address,
1766
- $._regex_line_unterminated_substitute,
1767
- $._replacement_line_unterminated,
1768
- $._translate_line_unterminated_source,
1769
- $._translate_line_unterminated_destination,
1770
- $._blanks_around_address_separator,
1771
- ...missingMarkerNames(mode).map((name) => $[`_${name}_marker`]),
1772
- $._unexpected_command_text,
1773
- $._incomplete_command_text,
1774
- $._error_sentinel,
2110
+ "regex_nonportable_escape",
2111
+ "regex_incomplete_escape",
2112
+ "regex_bracket_open",
2113
+ "regex_bracket_close",
2114
+ "regex_bracket_literal",
2115
+ "regex_bracket_negation",
2116
+ "regex_bracket_hyphen",
2117
+ "regex_bracket_range_end_hyphen",
2118
+ "regex_bracket_trailing_hyphen",
2119
+ "regex_open_colon",
2120
+ "regex_class_name",
2121
+ "regex_invalid_class_name",
2122
+ "regex_colon_close",
2123
+ "regex_open_dot",
2124
+ "regex_coll_elem_single",
2125
+ "regex_coll_elem_multi",
2126
+ "regex_meta_char",
2127
+ "regex_incomplete_meta_char",
2128
+ "regex_dot_close",
2129
+ "regex_open_equal",
2130
+ "regex_equal_close",
2131
+ "regex_missing_bracket_term_close",
2132
+ "regex_missing_bracket_term_payload",
2133
+ "regex_incomplete_bracket_term_payload",
2134
+ "regex_shared_range_endpoint",
2135
+ "ambiguous_bracket_expression_marker",
2136
+ "missing_bracket_list_marker",
2137
+ "unclosed_bracket_expression_marker",
2138
+ "nonportable_range_start_marker",
2139
+ "nonportable_range_end_marker",
2140
+ "regex_unterminated_address",
2141
+ "regex_unterminated_substitute",
2142
+ "replacement_literal",
2143
+ "replacement_match_reference",
2144
+ "replacement_backreference",
2145
+ "replacement_escaped_delimiter",
2146
+ "replacement_ampersand_escaped_delimiter",
2147
+ "replacement_escape_sequence",
2148
+ "replacement_nonportable_escape",
2149
+ "replacement_escaped_newline",
2150
+ "replacement_incomplete_escape",
2151
+ "replacement_unterminated",
2152
+ "translate_literal",
2153
+ "translate_escaped_delimiter",
2154
+ "translate_escape",
2155
+ "translate_nonportable_escape",
2156
+ "translate_incomplete_escape",
2157
+ "translate_unterminated_source",
2158
+ "translate_unterminated_destination",
2159
+ "invalid_substitution_flag",
2160
+ "flag_after_write_marker",
2161
+ "write_terminal_separator",
2162
+ "write_block_terminal_separator",
2163
+ "write_following_separator",
2164
+ "text_command_start",
2165
+ "text_incomplete_introducer",
2166
+ "text_literal",
2167
+ "text_backslash_escape",
2168
+ "text_escaped_newline",
2169
+ "text_unspecified_escape",
2170
+ "text_line_end",
2171
+ "text_eof",
2172
+ "default_output_suppression",
2173
+ "comment_text",
2174
+ "file_argument",
2175
+ "substitution_wfile_argument",
2176
+ "substitution_wfile_continuation",
2177
+ "line_word",
2178
+ "label_start",
2179
+ "long_label_start",
2180
+ "label_literal",
2181
+ "nonportable_label_character",
2182
+ "argument_separator",
2183
+ "brace_leading_blanks",
2184
+ "block_trailing_blanks",
2185
+ "empty_command_marker",
2186
+ "reserved_unknown_function_token",
2187
+ "regex_incomplete_group",
2188
+ "regex_incomplete_bracket_term",
2189
+ "regex_incomplete_interval",
2190
+ "regex_forbidden_newline_escape",
2191
+ "regex_line_unterminated_address",
2192
+ "regex_line_unterminated_substitute",
2193
+ "replacement_line_unterminated",
2194
+ "translate_line_unterminated_source",
2195
+ "translate_line_unterminated_destination",
2196
+ "blanks_around_address_separator",
2197
+ ...missingMarkerNames(mode).map((name) => `${name}_marker`),
2198
+ "unexpected_command_text",
2199
+ "incomplete_command_text",
2200
+ "error_sentinel",
1775
2201
  ];
1776
2202
  }
1777
2203
 
@@ -1783,7 +2209,7 @@ function defineGrammar(name, mode) {
1783
2209
  const options = {
1784
2210
  name,
1785
2211
 
1786
- externals: ($) => externalTokens($, mode),
2212
+ externals: ($) => externalTokens(mode).map((name) => $[`_${name}`]),
1787
2213
 
1788
2214
  extras: () => [],
1789
2215