parseman 0.47.1 → 0.48.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.
Files changed (124) hide show
  1. package/README.md +27 -21
  2. package/dist/analysis/diagnostics.js +2863 -353
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2854 -344
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/expect.d.ts +1 -0
  7. package/dist/combinators/expect.d.ts.map +1 -1
  8. package/dist/combinators/expected.d.ts +8 -0
  9. package/dist/combinators/expected.d.ts.map +1 -0
  10. package/dist/combinators/first-set.d.ts +8 -0
  11. package/dist/combinators/first-set.d.ts.map +1 -1
  12. package/dist/combinators/grammar.d.ts.map +1 -1
  13. package/dist/combinators/keywords.d.ts +4 -0
  14. package/dist/combinators/keywords.d.ts.map +1 -1
  15. package/dist/combinators/literal.d.ts.map +1 -1
  16. package/dist/combinators/not.d.ts.map +1 -1
  17. package/dist/combinators/peek.d.ts.map +1 -1
  18. package/dist/combinators/regex.d.ts.map +1 -1
  19. package/dist/combinators/repeat.d.ts.map +1 -1
  20. package/dist/combinators/sequence.d.ts.map +1 -1
  21. package/dist/combinators/trivia-skip.d.ts +16 -3
  22. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  23. package/dist/compiler/direct-projection.d.ts +12 -0
  24. package/dist/compiler/direct-projection.d.ts.map +1 -0
  25. package/dist/compiler/token-alphabet.d.ts +845 -5
  26. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  27. package/dist/compiler/token-capability.d.ts +3 -0
  28. package/dist/compiler/token-capability.d.ts.map +1 -0
  29. package/dist/compiler/token-capability.js +3192 -0
  30. package/dist/compiler/token-capability.js.map +6 -0
  31. package/dist/cst/trivia-charscan.d.ts +3 -0
  32. package/dist/cst/trivia-charscan.d.ts.map +1 -1
  33. package/dist/cst/trivia-css-scanner.d.ts +5 -0
  34. package/dist/cst/trivia-css-scanner.d.ts.map +1 -0
  35. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  36. package/dist/index.js +2862 -339
  37. package/dist/index.js.map +3 -3
  38. package/dist/language-service/index.js +5 -1
  39. package/dist/language-service/index.js.map +1 -1
  40. package/dist/plugin/index.js +2870 -347
  41. package/dist/plugin/index.js.map +3 -3
  42. package/dist/spec/index.js +315 -46
  43. package/dist/spec/index.js.map +2 -2
  44. package/dist/table/assemble.d.ts.map +1 -1
  45. package/dist/table/child-slots.d.ts.map +1 -1
  46. package/dist/table/compile-rule-map.d.ts +3 -1
  47. package/dist/table/compile-rule-map.d.ts.map +1 -1
  48. package/dist/table/emit-assembly.d.ts +12 -13
  49. package/dist/table/emit-assembly.d.ts.map +1 -1
  50. package/dist/table/emit.d.ts.map +1 -1
  51. package/dist/table/encode.d.ts.map +1 -1
  52. package/dist/table/exec-baseline.d.ts.map +1 -1
  53. package/dist/table/exec.d.ts.map +1 -1
  54. package/dist/table/index.js +2819 -300
  55. package/dist/table/index.js.map +3 -3
  56. package/dist/table/lex-body.d.ts +9 -0
  57. package/dist/table/lex-body.d.ts.map +1 -0
  58. package/dist/table/lex-program.d.ts +25 -0
  59. package/dist/table/lex-program.d.ts.map +1 -0
  60. package/dist/table/ops.d.ts +43 -7
  61. package/dist/table/ops.d.ts.map +1 -1
  62. package/dist/table/program.d.ts +50 -2
  63. package/dist/table/program.d.ts.map +1 -1
  64. package/dist/table/scalar-terminal.d.ts +13 -0
  65. package/dist/table/scalar-terminal.d.ts.map +1 -0
  66. package/dist/table/site-labels.d.ts.map +1 -1
  67. package/dist/types.d.ts +2 -0
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/version.d.ts +1 -1
  70. package/package.json +11 -11
  71. package/src/combinators/expect.ts +1 -0
  72. package/src/combinators/expected.ts +17 -0
  73. package/src/combinators/first-set.ts +58 -5
  74. package/src/combinators/grammar.ts +8 -3
  75. package/src/combinators/keywords.ts +22 -6
  76. package/src/combinators/literal.ts +2 -1
  77. package/src/combinators/not.ts +5 -1
  78. package/src/combinators/peek.ts +5 -1
  79. package/src/combinators/regex.ts +5 -3
  80. package/src/combinators/repeat.ts +4 -10
  81. package/src/combinators/sequence.ts +17 -14
  82. package/src/combinators/trivia-skip.ts +46 -13
  83. package/src/compiler/direct-projection.ts +43 -0
  84. package/src/compiler/token-alphabet.ts +4316 -12
  85. package/src/compiler/token-capability.ts +6 -0
  86. package/src/cst/trivia-charscan.ts +34 -0
  87. package/src/cst/trivia-css-scanner.ts +142 -0
  88. package/src/cst/trivia-kinds.ts +3 -1
  89. package/src/plugin/index.ts +4 -4
  90. package/src/table/assemble.ts +1211 -221
  91. package/src/table/child-slots.ts +2 -1
  92. package/src/table/compile-rule-map.ts +21 -3
  93. package/src/table/emit-assembly.ts +328 -85
  94. package/src/table/emit.ts +16 -2
  95. package/src/table/encode.ts +242 -50
  96. package/src/table/exec-baseline.ts +3 -7
  97. package/src/table/exec.ts +121 -7
  98. package/src/table/lex-body.ts +30 -0
  99. package/src/table/lex-program.ts +422 -0
  100. package/src/table/ops.ts +45 -7
  101. package/src/table/program.ts +46 -2
  102. package/src/table/scalar-terminal.ts +51 -0
  103. package/src/table/site-labels.ts +11 -1
  104. package/src/table/stamp.ts +1 -1
  105. package/src/types.ts +1 -1
  106. package/src/version.ts +1 -1
  107. package/dist/analysis/diagnostics.cjs +0 -13824
  108. package/dist/analysis/diagnostics.cjs.map +0 -6
  109. package/dist/cli/index.cjs +0 -14925
  110. package/dist/cli/index.cjs.map +0 -6
  111. package/dist/index.cjs +0 -16391
  112. package/dist/index.cjs.map +0 -6
  113. package/dist/language-service/index.cjs +0 -1304
  114. package/dist/language-service/index.cjs.map +0 -6
  115. package/dist/oracle/index.cjs +0 -254
  116. package/dist/oracle/index.cjs.map +0 -6
  117. package/dist/plugin/index.cjs +0 -16097
  118. package/dist/plugin/index.cjs.map +0 -6
  119. package/dist/run/index.cjs +0 -577
  120. package/dist/run/index.cjs.map +0 -6
  121. package/dist/spec/index.cjs +0 -6236
  122. package/dist/spec/index.cjs.map +0 -6
  123. package/dist/table/index.cjs +0 -11463
  124. package/dist/table/index.cjs.map +0 -6
package/dist/index.js CHANGED
@@ -1,4 +1,40 @@
1
1
  // src/combinators/first-set.ts
2
+ function classifyFinalChoice(arms, resolve) {
3
+ const firstSets = [];
4
+ const nullable2 = [];
5
+ let exclusive = true;
6
+ for (const arm of arms) {
7
+ const empty2 = matchesEmpty(arm, /* @__PURE__ */ new Set(), resolve);
8
+ nullable2.push(empty2);
9
+ firstSets.push(empty2 ? { kind: "any" } : firstSetOf(arm, /* @__PURE__ */ new Set(), resolve));
10
+ if (empty2) exclusive = false;
11
+ }
12
+ if (exclusive) {
13
+ const ascii = new Uint8Array(128);
14
+ let highOwners = 0;
15
+ for (let arm = 0; arm < firstSets.length && exclusive; arm++) {
16
+ const first = firstSets[arm];
17
+ if (first.kind !== "ranges" || first.ranges.length === 0) {
18
+ exclusive = false;
19
+ break;
20
+ }
21
+ let ownsHigh = false;
22
+ for (const range of first.ranges) {
23
+ if (range.hi >= 128) ownsHigh = true;
24
+ for (let code = Math.max(0, range.lo); code <= Math.min(127, range.hi); code++) {
25
+ if (ascii[code] !== 0) {
26
+ exclusive = false;
27
+ break;
28
+ }
29
+ ascii[code] = 1;
30
+ }
31
+ if (!exclusive) break;
32
+ }
33
+ if (ownsHigh && ++highOwners > 1) exclusive = false;
34
+ }
35
+ }
36
+ return { exclusive, firstSets, nullable: nullable2 };
37
+ }
2
38
  function resolveNamedRef(p, resolve) {
3
39
  if (resolve === void 0) return void 0;
4
40
  const name = p._ruleName;
@@ -503,6 +539,21 @@ function pushTriviaLogEntry(ctx, start, end, kindIndex) {
503
539
  }
504
540
  }
505
541
 
542
+ // src/combinators/expected.ts
543
+ function directTerminalFailureExpected(def) {
544
+ switch (def.tag) {
545
+ case "literal":
546
+ return [JSON.stringify(def.value)];
547
+ case "regex":
548
+ return [`/${def.source}/`];
549
+ case "keywords":
550
+ return ["keyword"];
551
+ }
552
+ }
553
+ function assertionFailureExpected(positive, childTag) {
554
+ return [`${positive ? "peek" : "not"}(${childTag})`];
555
+ }
556
+
506
557
  // src/combinators/literal.ts
507
558
  function asciiFoldEq(a, b) {
508
559
  if (a.length !== b.length) return false;
@@ -534,7 +585,7 @@ function literal(value, opts = {}) {
534
585
  { lo: firstUpper, hi: firstUpper }
535
586
  ] } : firstSet2;
536
587
  }
537
- const expected = [JSON.stringify(value)];
588
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
538
589
  const parse2 = !caseInsensitive && value.length === 1 ? (() => {
539
590
  const code = value.charCodeAt(0);
540
591
  return function parse3(input, pos, ctx) {
@@ -1012,14 +1063,15 @@ function regex(pattern, flags = "") {
1012
1063
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
1013
1064
  const canMatchNewline = raw.canMatchNewline;
1014
1065
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
1066
+ const def = { tag: "regex", source, flags: resolvedFlags };
1015
1067
  return {
1016
1068
  _tag: "regex",
1017
1069
  _meta: meta,
1018
- _def: { tag: "regex", source, flags: resolvedFlags },
1070
+ _def: def,
1019
1071
  parse(input, pos, ctx) {
1020
1072
  const scanEnd = scan?.(input, pos);
1021
1073
  if (scanEnd !== void 0) {
1022
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
1074
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
1023
1075
  const value = input.slice(pos, scanEnd);
1024
1076
  const span2 = { start: pos, end: scanEnd };
1025
1077
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -1029,7 +1081,7 @@ function regex(pattern, flags = "") {
1029
1081
  anchored.lastIndex = pos;
1030
1082
  const m = anchored.exec(input);
1031
1083
  if (m === null) {
1032
- return failAt(ctx, [`/${source}/`], pos);
1084
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
1033
1085
  }
1034
1086
  const span = { start: pos, end: pos + m[0].length };
1035
1087
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -1088,12 +1140,14 @@ function makeWord(boundaryOrOpts = "_0-9A-Za-z", opts) {
1088
1140
  function escapeRe(s) {
1089
1141
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1090
1142
  }
1143
+ function keywordsRegExp(words, boundary, caseInsensitive) {
1144
+ const alt = words.map(escapeRe).join("|");
1145
+ const boundarySource = boundary ? `(?![${boundary}])` : "";
1146
+ return new RegExp(`(?:${alt})${boundarySource}`, caseInsensitive ? "iy" : "uy");
1147
+ }
1091
1148
  function keywords(words, opts = {}) {
1092
1149
  const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
1093
- const alt = sorted.map(escapeRe).join("|");
1094
- const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
1095
- const flags = opts.caseInsensitive ? "iy" : "uy";
1096
- const re = new RegExp(`(?:${alt})${boundary}`, flags);
1150
+ const re = keywordsRegExp(sorted, opts.boundary, opts.caseInsensitive ?? false);
1097
1151
  let firstSet2 = empty();
1098
1152
  for (const w of sorted) {
1099
1153
  if (w.length === 0) continue;
@@ -1104,15 +1158,21 @@ function keywords(words, opts = {}) {
1104
1158
  }
1105
1159
  }
1106
1160
  const meta = { firstSet: firstSet2, canMatchNewline: false, isTrivia: false };
1161
+ const def = {
1162
+ tag: "keywords",
1163
+ words: sorted,
1164
+ caseInsensitive: opts.caseInsensitive ?? false,
1165
+ boundary: opts.boundary
1166
+ };
1107
1167
  return {
1108
1168
  _tag: "keywords",
1109
1169
  _meta: meta,
1110
- _def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
1170
+ _def: def,
1111
1171
  parse(input, pos, ctx) {
1112
1172
  re.lastIndex = pos;
1113
1173
  const m = re.exec(input);
1114
1174
  if (m === null || m.index !== pos) {
1115
- return failAt(ctx, ["keyword"], pos);
1175
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
1116
1176
  }
1117
1177
  const value = m[0];
1118
1178
  const span = { start: pos, end: pos + value.length };
@@ -1167,6 +1227,179 @@ function createDetachedParseContext(trackLines, state) {
1167
1227
  return ctx;
1168
1228
  }
1169
1229
 
1230
+ // src/cst/trivia-css-scanner.ts
1231
+ var CSS_WS_SOURCE = "[ \\t\\n\\r\\f]+";
1232
+ var CSS_LINE_COMMENT_SOURCE = "\\/\\/[^\\n\\r]*";
1233
+ var CSS_BLOCK_COMMENT_SOURCE = "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/";
1234
+ function scanWhitespace(input, cur) {
1235
+ let pos = cur;
1236
+ while (pos < input.length) {
1237
+ const c = input.charCodeAt(pos);
1238
+ if (c !== 32 && c !== 9 && c !== 10 && c !== 13 && c !== 12) break;
1239
+ pos++;
1240
+ }
1241
+ return pos;
1242
+ }
1243
+ function scanLineComment(input, cur) {
1244
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 47) return cur;
1245
+ let pos = cur + 2;
1246
+ while (pos < input.length) {
1247
+ const c = input.charCodeAt(pos);
1248
+ if (c === 10 || c === 13) break;
1249
+ pos++;
1250
+ }
1251
+ return pos;
1252
+ }
1253
+ function scanBlockComment(input, cur) {
1254
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
1255
+ const close = input.indexOf("*/", cur + 2);
1256
+ return close < 0 ? cur : close + 2;
1257
+ }
1258
+ function scanWsLineBlockTrivia(input, cur) {
1259
+ let pos = cur;
1260
+ for (; ; ) {
1261
+ const ws = scanWhitespace(input, pos);
1262
+ if (ws !== pos) {
1263
+ pos = ws;
1264
+ continue;
1265
+ }
1266
+ const line = scanLineComment(input, pos);
1267
+ if (line !== pos) {
1268
+ pos = line;
1269
+ continue;
1270
+ }
1271
+ const block = scanBlockComment(input, pos);
1272
+ if (block !== pos) {
1273
+ pos = block;
1274
+ continue;
1275
+ }
1276
+ return pos;
1277
+ }
1278
+ }
1279
+ function scanWsBlockTrivia(input, cur) {
1280
+ let pos = cur;
1281
+ for (; ; ) {
1282
+ const ws = scanWhitespace(input, pos);
1283
+ if (ws !== pos) {
1284
+ pos = ws;
1285
+ continue;
1286
+ }
1287
+ const block = scanBlockComment(input, pos);
1288
+ if (block !== pos) {
1289
+ pos = block;
1290
+ continue;
1291
+ }
1292
+ return pos;
1293
+ }
1294
+ }
1295
+ function scanLineBlockTrivia(input, cur) {
1296
+ let pos = cur;
1297
+ for (; ; ) {
1298
+ const line = scanLineComment(input, pos);
1299
+ if (line !== pos) {
1300
+ pos = line;
1301
+ continue;
1302
+ }
1303
+ const block = scanBlockComment(input, pos);
1304
+ if (block !== pos) {
1305
+ pos = block;
1306
+ continue;
1307
+ }
1308
+ return pos;
1309
+ }
1310
+ }
1311
+ function scanBlockTrivia(input, cur) {
1312
+ let pos = cur;
1313
+ for (; ; ) {
1314
+ const block = scanBlockComment(input, pos);
1315
+ if (block === pos) return pos;
1316
+ pos = block;
1317
+ }
1318
+ }
1319
+ function visitWsLineBlock(input, cur, visit) {
1320
+ let pos = cur;
1321
+ for (; ; ) {
1322
+ let end = scanWhitespace(input, pos);
1323
+ if (end !== pos) {
1324
+ visit(pos, end, 0);
1325
+ pos = end;
1326
+ continue;
1327
+ }
1328
+ end = scanLineComment(input, pos);
1329
+ if (end !== pos) {
1330
+ visit(pos, end, 1);
1331
+ pos = end;
1332
+ continue;
1333
+ }
1334
+ end = scanBlockComment(input, pos);
1335
+ if (end !== pos) {
1336
+ visit(pos, end, 2);
1337
+ pos = end;
1338
+ continue;
1339
+ }
1340
+ return pos;
1341
+ }
1342
+ }
1343
+ function visitWsBlock(input, cur, visit) {
1344
+ let pos = cur;
1345
+ for (; ; ) {
1346
+ let end = scanWhitespace(input, pos);
1347
+ if (end !== pos) {
1348
+ visit(pos, end, 0);
1349
+ pos = end;
1350
+ continue;
1351
+ }
1352
+ end = scanBlockComment(input, pos);
1353
+ if (end !== pos) {
1354
+ visit(pos, end, 1);
1355
+ pos = end;
1356
+ continue;
1357
+ }
1358
+ return pos;
1359
+ }
1360
+ }
1361
+ function visitLineBlock(input, cur, visit) {
1362
+ let pos = cur;
1363
+ for (; ; ) {
1364
+ let end = scanLineComment(input, pos);
1365
+ if (end !== pos) {
1366
+ visit(pos, end, 0);
1367
+ pos = end;
1368
+ continue;
1369
+ }
1370
+ end = scanBlockComment(input, pos);
1371
+ if (end !== pos) {
1372
+ visit(pos, end, 1);
1373
+ pos = end;
1374
+ continue;
1375
+ }
1376
+ return pos;
1377
+ }
1378
+ }
1379
+ function visitBlock(input, cur, visit) {
1380
+ let pos = cur;
1381
+ for (; ; ) {
1382
+ const end = scanBlockComment(input, pos);
1383
+ if (end === pos) return pos;
1384
+ visit(pos, end, 0);
1385
+ pos = end;
1386
+ }
1387
+ }
1388
+ function commonCssTriviaScanner(sources) {
1389
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return scanWsLineBlockTrivia;
1390
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanWsBlockTrivia;
1391
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return scanLineBlockTrivia;
1392
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return scanBlockTrivia;
1393
+ return null;
1394
+ }
1395
+ function commonCssTriviaVisitor(sources) {
1396
+ if (sources.length === 3 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_LINE_COMMENT_SOURCE && sources[2] === CSS_BLOCK_COMMENT_SOURCE) return visitWsLineBlock;
1397
+ if (sources.length === 2 && sources[0] === CSS_WS_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitWsBlock;
1398
+ if (sources.length === 2 && sources[0] === CSS_LINE_COMMENT_SOURCE && sources[1] === CSS_BLOCK_COMMENT_SOURCE) return visitLineBlock;
1399
+ if (sources.length === 1 && sources[0] === CSS_BLOCK_COMMENT_SOURCE) return visitBlock;
1400
+ return null;
1401
+ }
1402
+
1170
1403
  // src/cst/trivia-charscan.ts
1171
1404
  function inRanges2(cp, ranges) {
1172
1405
  for (let i = 0; i < ranges.length; i++) {
@@ -1320,6 +1553,35 @@ function classifyParser(p) {
1320
1553
  if (d.tag !== "regex" || d.flags) return null;
1321
1554
  return classifyArm(d.source);
1322
1555
  }
1556
+ function plainRegexSource(p) {
1557
+ const d = p._def;
1558
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
1559
+ }
1560
+ var visitSpec0;
1561
+ var visitSpec1;
1562
+ var visitSpec2;
1563
+ var visitSpec3;
1564
+ var visitValue0;
1565
+ var visitValue1;
1566
+ var visitValue2;
1567
+ var visitValue3;
1568
+ function commonLabeledTriviaVisitor(spec) {
1569
+ if (spec === visitSpec0) return visitValue0;
1570
+ if (spec === visitSpec1) return visitValue1;
1571
+ if (spec === visitSpec2) return visitValue2;
1572
+ if (spec === visitSpec3) return visitValue3;
1573
+ const sources = spec.minRepeats <= 1 ? spec.arms.map((arm) => plainRegexSource(arm.parser)) : [];
1574
+ const visitor = commonCssTriviaVisitor(sources);
1575
+ visitSpec3 = visitSpec2;
1576
+ visitValue3 = visitValue2;
1577
+ visitSpec2 = visitSpec1;
1578
+ visitValue2 = visitValue1;
1579
+ visitSpec1 = visitSpec0;
1580
+ visitValue1 = visitValue0;
1581
+ visitSpec0 = spec;
1582
+ visitValue0 = visitor;
1583
+ return visitor;
1584
+ }
1323
1585
  var armSpec0;
1324
1586
  var armSpec1;
1325
1587
  var armSpec2;
@@ -1518,6 +1780,8 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1518
1780
  }
1519
1781
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1520
1782
  if (spec.minRepeats > 1) return void 0;
1783
+ const common = commonLabeledTriviaVisitor(spec);
1784
+ if (common !== null) return common(input, cur, visit);
1521
1785
  const chars = charArmsFor(spec);
1522
1786
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1523
1787
  let pos = cur;
@@ -1617,6 +1881,14 @@ function triviaKindMask(labels, keep) {
1617
1881
  // src/combinators/trivia-skip.ts
1618
1882
  var NOOP_COMMIT = () => {
1619
1883
  };
1884
+ function triviaScanEnd(scan) {
1885
+ return typeof scan === "number" ? scan : scan.end;
1886
+ }
1887
+ function commitTriviaScan(scan) {
1888
+ if (typeof scan === "number") return scan;
1889
+ scan.commit();
1890
+ return scan.end;
1891
+ }
1620
1892
  var fastTrivia0;
1621
1893
  var fastTrivia1;
1622
1894
  var fastTrivia2;
@@ -1686,7 +1958,7 @@ function rollbackLookahead(ctx, mark) {
1686
1958
  function scanWithLabels(input, cur, ctx) {
1687
1959
  const triviaP = ctx.trivia;
1688
1960
  const spec = analyzeLabeledTrivia(triviaP);
1689
- if (!spec) return { end: cur, commit: NOOP_COMMIT };
1961
+ if (!spec) return cur;
1690
1962
  const log = ctx._triviaLog;
1691
1963
  const rootLog = ctx._rootTriviaLog;
1692
1964
  const rootKinds = ctx._rootTriviaKindIndex;
@@ -1704,7 +1976,8 @@ function scanWithLabels(input, cur, ctx) {
1704
1976
  }
1705
1977
  });
1706
1978
  if (visitedEnd !== void 0) {
1707
- if (visitedEnd === cur) return { end: cur, commit: NOOP_COMMIT };
1979
+ if (visitedEnd === cur) return cur;
1980
+ if (fullRows === void 0 && rootRows === void 0 && cstRows === void 0) return visitedEnd;
1708
1981
  return {
1709
1982
  end: visitedEnd,
1710
1983
  commit: () => {
@@ -1723,7 +1996,7 @@ function scanWithLabels(input, cur, ctx) {
1723
1996
  };
1724
1997
  }
1725
1998
  const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
1726
- if (end === cur) return { end: cur, commit: NOOP_COMMIT };
1999
+ if (end === cur) return cur;
1727
2000
  return {
1728
2001
  end,
1729
2002
  commit: () => recordTriviaChunks(ctx, chunks)
@@ -1764,7 +2037,7 @@ function advanceTrivia(input, cur, ctx) {
1764
2037
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1765
2038
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
1766
2039
  }
1767
- function scanTrivia(input, cur, ctx) {
2040
+ function scanTriviaCompact(input, cur, ctx) {
1768
2041
  const triviaP = ctx.trivia;
1769
2042
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
1770
2043
  const log = ctx._triviaLog;
@@ -1805,7 +2078,7 @@ function scanTrivia(input, cur, ctx) {
1805
2078
  }
1806
2079
  if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
1807
2080
  const scan = scanWithLabels(input, cur, ctx);
1808
- if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
2081
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, triviaScanEnd(scan));
1809
2082
  return scan;
1810
2083
  }
1811
2084
  if (ctx.triviaKindLabels) {
@@ -1835,6 +2108,10 @@ function scanTrivia(input, cur, ctx) {
1835
2108
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1836
2109
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
1837
2110
  }
2111
+ function scanTrivia(input, cur, ctx) {
2112
+ const scan = scanTriviaCompact(input, cur, ctx);
2113
+ return typeof scan === "number" ? { end: scan, commit: NOOP_COMMIT } : scan;
2114
+ }
1838
2115
  function skipTriviaScanned(s, input, cur, ctx) {
1839
2116
  const end = s(input, cur);
1840
2117
  if (end !== cur) {
@@ -1847,14 +2124,12 @@ function skipTriviaScanned(s, input, cur, ctx) {
1847
2124
  }
1848
2125
  function consumeTrivia(input, cur, ctx) {
1849
2126
  if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
1850
- const scan = scanTrivia(input, cur, ctx);
1851
- scan.commit();
1852
- return scan.end;
2127
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
1853
2128
  }
1854
2129
  function probeTriviaEnd(input, cur, ctx) {
1855
2130
  if (!ctx.trivia) return cur;
1856
2131
  const probeCtx = { ...ctx, trackLines: false };
1857
- if (needsDeferredTriviaCommit(probeCtx)) return scanTrivia(input, cur, probeCtx).end;
2132
+ if (needsDeferredTriviaCommit(probeCtx)) return triviaScanEnd(scanTriviaCompact(input, cur, probeCtx));
1858
2133
  return advanceTrivia(input, cur, probeCtx);
1859
2134
  }
1860
2135
  function fastTriviaScanner(trivia2) {
@@ -1882,10 +2157,16 @@ function buildFastTriviaScanner(trivia2) {
1882
2157
  const one = regexTriviaScanner(repeat);
1883
2158
  if (one) return loopScanner([one]);
1884
2159
  if (repeat._def.tag !== "choice") return null;
2160
+ const fused = commonCssTriviaScanner(repeat._def.parsers.map(triviaRegexSource));
2161
+ if (fused !== null) return fused;
1885
2162
  const arms = repeat._def.parsers.map(regexTriviaScanner);
1886
2163
  if (arms.some((s) => s === null)) return null;
1887
2164
  return loopScanner(arms);
1888
2165
  }
2166
+ function triviaRegexSource(parser2) {
2167
+ const d = parser2._def.tag === "label" ? parser2._def.parser._def : parser2._def;
2168
+ return d.tag === "regex" && d.flags === "" ? d.source : null;
2169
+ }
1889
2170
  function loopScanner(arms) {
1890
2171
  return (input, cur) => {
1891
2172
  let pos = cur;
@@ -2376,9 +2657,7 @@ function sequence(...parsers) {
2376
2657
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2377
2658
  let scanEnd;
2378
2659
  if (needsDeferredTriviaCommit(ctx)) {
2379
- const scan = scanTrivia(input, cur, ctx);
2380
- scan.commit();
2381
- scanEnd = scan.end;
2660
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2382
2661
  } else {
2383
2662
  scanEnd = advanceTrivia(input, cur, ctx);
2384
2663
  }
@@ -2388,7 +2667,15 @@ function sequence(...parsers) {
2388
2667
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2389
2668
  if (!result2.ok) return result2;
2390
2669
  if (result2.span.end > scanEnd) cur = result2.span.end;
2391
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2670
+ else rollbackScannedTriviaAt(
2671
+ ctx,
2672
+ mTlog,
2673
+ scanTlog,
2674
+ mLog,
2675
+ scanLog,
2676
+ mRootLog,
2677
+ scanRootLog
2678
+ );
2392
2679
  if (values !== void 0) values.push(result2.value);
2393
2680
  continue;
2394
2681
  }
@@ -2423,9 +2710,7 @@ function sequence(...parsers) {
2423
2710
  const mLog = ctx._triviaLog?.length ?? 0;
2424
2711
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2425
2712
  if (needsDeferredTriviaCommit(ctx)) {
2426
- const scan = scanTrivia(input, cur, ctx);
2427
- scan.commit();
2428
- scanEnd = scan.end;
2713
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2429
2714
  } else {
2430
2715
  scanEnd = advanceTrivia(input, cur, ctx);
2431
2716
  }
@@ -2435,7 +2720,15 @@ function sequence(...parsers) {
2435
2720
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2436
2721
  if (!result2.ok) return result2;
2437
2722
  if (result2.span.end > scanEnd) cur = result2.span.end;
2438
- else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2723
+ else rollbackScannedTriviaAt(
2724
+ ctx,
2725
+ mTlog,
2726
+ scanTlog,
2727
+ mLog,
2728
+ scanLog,
2729
+ mRootLog,
2730
+ scanRootLog
2731
+ );
2439
2732
  if (values !== void 0) values.push(result2.value);
2440
2733
  continue;
2441
2734
  }
@@ -2467,9 +2760,7 @@ function sequence(...parsers) {
2467
2760
  const mLog = ctx._triviaLog?.length ?? 0;
2468
2761
  const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2469
2762
  if (needsDeferredTriviaCommit(ctx)) {
2470
- const scan = scanTrivia(input, cur, ctx);
2471
- scan.commit();
2472
- scanEnd = scan.end;
2763
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2473
2764
  } else {
2474
2765
  scanEnd = advanceTrivia(input, cur, ctx);
2475
2766
  }
@@ -2481,7 +2772,15 @@ function sequence(...parsers) {
2481
2772
  if (result2.span.end > scanEnd) {
2482
2773
  cur = result2.span.end;
2483
2774
  } else {
2484
- rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2775
+ rollbackScannedTriviaAt(
2776
+ ctx,
2777
+ mTlog,
2778
+ scanTlog,
2779
+ mLog,
2780
+ scanLog,
2781
+ mRootLog,
2782
+ scanRootLog
2783
+ );
2485
2784
  }
2486
2785
  if (values !== void 0) values.push(result2.value);
2487
2786
  continue;
@@ -3179,9 +3478,7 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3179
3478
  let pos = cur;
3180
3479
  if (ctx.trivia) {
3181
3480
  if (needsDeferredTriviaCommit(ctx)) {
3182
- const scan = scanTrivia(input, cur, ctx);
3183
- scan.commit();
3184
- pos = scan.end;
3481
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3185
3482
  } else {
3186
3483
  pos = advanceTrivia(input, cur, ctx);
3187
3484
  }
@@ -3407,9 +3704,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3407
3704
  let sepPos = cur;
3408
3705
  if (ctx.trivia) {
3409
3706
  if (needsDeferredTriviaCommit(ctx)) {
3410
- const scan = scanTrivia(input, cur, ctx);
3411
- scan.commit();
3412
- sepPos = scan.end;
3707
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3413
3708
  } else {
3414
3709
  sepPos = advanceTrivia(input, cur, ctx);
3415
3710
  }
@@ -3425,9 +3720,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3425
3720
  let nextPos = sep.span.end;
3426
3721
  if (ctx.trivia) {
3427
3722
  if (needsDeferredTriviaCommit(ctx)) {
3428
- const scan = scanTrivia(input, sep.span.end, ctx);
3429
- scan.commit();
3430
- nextPos = scan.end;
3723
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
3431
3724
  } else {
3432
3725
  nextPos = advanceTrivia(input, sep.span.end, ctx);
3433
3726
  }
@@ -3687,11 +3980,12 @@ function parser(opts, root) {
3687
3980
  const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
3688
3981
  const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
3689
3982
  const forceCaptureTrivia = opts.captureTrivia === true;
3690
- const trackLinesOf = opts.trackLines === true ? TRACK_LINES_ON : opts.trackLines === false ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
3983
+ const trackLinesPolicy = opts.trackLines === true ? "on" : opts.trackLines === false ? "off" : "inherit";
3984
+ const trackLinesOf = trackLinesPolicy === "on" ? TRACK_LINES_ON : trackLinesPolicy === "off" ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
3691
3985
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
3692
3986
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
3693
3987
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
3694
- return {
3988
+ const grammar = {
3695
3989
  _tag: "grammar",
3696
3990
  _meta: {
3697
3991
  ...root._meta,
@@ -3710,7 +4004,9 @@ function parser(opts, root) {
3710
4004
  clearTrivia,
3711
4005
  ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
3712
4006
  ...opts.captureTrivia ? { captureTrivia: true } : {},
3713
- trackLines: opts.trackLines ?? false
4007
+ trackLines: opts.trackLines ?? false,
4008
+ constructionTrackLines: trackLinesPolicy,
4009
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
3714
4010
  },
3715
4011
  parse(input, pos, _ctx) {
3716
4012
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
@@ -3739,6 +4035,7 @@ function parser(opts, root) {
3739
4035
  return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
3740
4036
  }
3741
4037
  };
4038
+ return grammar;
3742
4039
  }
3743
4040
  function noTrivia(root) {
3744
4041
  return parser({ trivia: null }, root);
@@ -3998,7 +4295,11 @@ function not(combinator) {
3998
4295
  const result = combinator.parse(input, pos, ctx);
3999
4296
  rollbackLookahead(ctx, mark);
4000
4297
  if (result.ok) {
4001
- return { ok: false, expected: [`not(${combinator._tag})`], span: { start: pos, end: pos } };
4298
+ return {
4299
+ ok: false,
4300
+ expected: assertionFailureExpected(false, combinator._tag),
4301
+ span: { start: pos, end: pos }
4302
+ };
4002
4303
  }
4003
4304
  return { ok: true, value: null, span: { start: pos, end: pos } };
4004
4305
  }
@@ -4022,7 +4323,11 @@ function peek(combinator) {
4022
4323
  const result = combinator.parse(input, pos, ctx);
4023
4324
  rollbackLookahead(ctx, mark);
4024
4325
  if (result.ok) return { ok: true, value: null, span: { start: pos, end: pos } };
4025
- return { ok: false, expected: [`peek(${combinator._tag})`], span: { start: pos, end: pos } };
4326
+ return {
4327
+ ok: false,
4328
+ expected: assertionFailureExpected(true, combinator._tag),
4329
+ span: { start: pos, end: pos }
4330
+ };
4026
4331
  }
4027
4332
  };
4028
4333
  }
@@ -4272,6 +4577,12 @@ function confirmedArityForDef(def) {
4272
4577
  });
4273
4578
  return null;
4274
4579
  }
4580
+ function buildReadsRaw(def) {
4581
+ if (!def.build) return true;
4582
+ const arity = confirmedArityForDef(def);
4583
+ if (arity === null) return true;
4584
+ return arity >= 4;
4585
+ }
4275
4586
  function buildReadsTrivia(def) {
4276
4587
  if (!def.build) return true;
4277
4588
  const arity = confirmedArityForDef(def);
@@ -5104,6 +5415,8 @@ var OP_ATTEMPT = 38;
5104
5415
  var OP_LABEL = 39;
5105
5416
  var OP_COV = 40;
5106
5417
  var OP_SCOPE_PLAIN = 41;
5418
+ var OP_LEX_BODY = 42;
5419
+ var OP_LEX_PROGRAM = 43;
5107
5420
  var OP_DISPATCH = 25;
5108
5421
  var OP_ROUTED = 26;
5109
5422
  var OP_NAMES = {
@@ -5147,9 +5460,390 @@ var OP_NAMES = {
5147
5460
  [OP_ATTEMPT]: "ATTEMPT",
5148
5461
  [OP_LABEL]: "LABEL",
5149
5462
  [OP_COV]: "COV",
5150
- [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
5463
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
5464
+ [OP_LEX_BODY]: "LEX_BODY",
5465
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
5151
5466
  };
5152
5467
 
5468
+ // src/table/lex-program.ts
5469
+ var LEX_NODE_TERMINAL = 0;
5470
+ var LEX_NODE_SEQUENCE2 = 1;
5471
+ var LEX_NODE_SEQUENCE3 = 2;
5472
+ var LEX_NODE_SEQUENCE4 = 3;
5473
+ var LEX_NODE_SEQUENCE5 = 4;
5474
+ var LEX_NODE_CHOICE2 = 5;
5475
+ var LEX_NODE_CHOICE4 = 6;
5476
+ var LEX_NODE_CHOICE8 = 7;
5477
+ var LEX_NODE_NOT = 8;
5478
+ var LEX_NODE_OPTIONAL = 9;
5479
+ function lexProgramDigest(words) {
5480
+ let hash = 2166136261;
5481
+ for (const word2 of words) {
5482
+ hash ^= word2 | 0;
5483
+ hash = Math.imul(hash, 16777619);
5484
+ }
5485
+ return hash | 0;
5486
+ }
5487
+ function classHas(cls, code) {
5488
+ if (code < 0) return false;
5489
+ if (code < 128) return cls.ascii[code] === 1;
5490
+ for (let i = 0; i < cls.hi.length; i += 2) {
5491
+ if (code >= cls.hi[i] && code <= cls.hi[i + 1]) return true;
5492
+ }
5493
+ return false;
5494
+ }
5495
+ var committed = (ctx) => ctx._fc === true;
5496
+ function trackLexLines(ctx, input, end) {
5497
+ let at = ctx._lineScannedTo ?? 0;
5498
+ const starts = ctx._lineStarts;
5499
+ if (starts === void 0 || end <= at) return;
5500
+ while (at < end) {
5501
+ if (input.charCodeAt(at) === 10) starts.push(at + 1);
5502
+ at++;
5503
+ }
5504
+ ctx._lineScannedTo = end;
5505
+ }
5506
+ function terminalNode(matcher, failure, tracksLines) {
5507
+ const match = (input, pos) => {
5508
+ const result = matcher(input, pos);
5509
+ return result < 0 ? -1 : result / 2;
5510
+ };
5511
+ return {
5512
+ match,
5513
+ run: (input, pos, ctx) => {
5514
+ const end = match(input, pos);
5515
+ if (end < 0) {
5516
+ ctx._fe = pos;
5517
+ ctx._fx = failure;
5518
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
5519
+ return -1;
5520
+ }
5521
+ if (tracksLines) trackLexLines(ctx, input, end);
5522
+ return end;
5523
+ }
5524
+ };
5525
+ }
5526
+ function sequence2(a, b) {
5527
+ return {
5528
+ match: (input, pos) => {
5529
+ const e0 = a.match(input, pos);
5530
+ return e0 < 0 ? -1 : b.match(input, e0);
5531
+ },
5532
+ run: (input, pos, ctx) => {
5533
+ const e0 = a.run(input, pos, ctx);
5534
+ if (e0 < 0) return -1;
5535
+ ctx._fc = false;
5536
+ return b.run(input, e0, ctx);
5537
+ }
5538
+ };
5539
+ }
5540
+ function sequence3(a, b, c) {
5541
+ return {
5542
+ match: (input, pos) => {
5543
+ const e0 = a.match(input, pos);
5544
+ if (e0 < 0) return -1;
5545
+ const e1 = b.match(input, e0);
5546
+ return e1 < 0 ? -1 : c.match(input, e1);
5547
+ },
5548
+ run: (input, pos, ctx) => {
5549
+ const e0 = a.run(input, pos, ctx);
5550
+ if (e0 < 0) return -1;
5551
+ ctx._fc = false;
5552
+ const e1 = b.run(input, e0, ctx);
5553
+ if (e1 < 0) return -1;
5554
+ ctx._fc = false;
5555
+ return c.run(input, e1, ctx);
5556
+ }
5557
+ };
5558
+ }
5559
+ function sequence4(a, b, c, d) {
5560
+ const abc = sequence3(a, b, c);
5561
+ return {
5562
+ match: (input, pos) => {
5563
+ const end = abc.match(input, pos);
5564
+ return end < 0 ? -1 : d.match(input, end);
5565
+ },
5566
+ run: (input, pos, ctx) => {
5567
+ const end = abc.run(input, pos, ctx);
5568
+ if (end < 0) return -1;
5569
+ ctx._fc = false;
5570
+ return d.run(input, end, ctx);
5571
+ }
5572
+ };
5573
+ }
5574
+ function sequence5(a, b, c, d, e) {
5575
+ const abcd = sequence4(a, b, c, d);
5576
+ return {
5577
+ match: (input, pos) => {
5578
+ const end = abcd.match(input, pos);
5579
+ return end < 0 ? -1 : e.match(input, end);
5580
+ },
5581
+ run: (input, pos, ctx) => {
5582
+ const end = abcd.run(input, pos, ctx);
5583
+ if (end < 0) return -1;
5584
+ ctx._fc = false;
5585
+ return e.run(input, end, ctx);
5586
+ }
5587
+ };
5588
+ }
5589
+ function appendExpected(acc, values) {
5590
+ if (values === void 0 || values.length === 0) return acc;
5591
+ if (acc === void 0) return values.slice();
5592
+ acc.push(...values);
5593
+ return acc;
5594
+ }
5595
+ function choiceNode(arms, classes, armExpected, choiceExpected) {
5596
+ let matchTail = () => -1;
5597
+ for (let i = arms.length - 1; i >= 0; i--) {
5598
+ const arm = arms[i], next = matchTail;
5599
+ matchTail = (input, pos) => {
5600
+ const end = arm.match(input, pos);
5601
+ return end < 0 ? next(input, pos) : end;
5602
+ };
5603
+ }
5604
+ let tail = (_input, pos, ctx, _lead, acc) => {
5605
+ ctx._fe = pos;
5606
+ ctx._fx = acc ?? choiceExpected;
5607
+ return -1;
5608
+ };
5609
+ for (let i = arms.length - 1; i >= 0; i--) {
5610
+ const arm = arms[i], cls = classes[i], staticExpected = armExpected[i], next = tail;
5611
+ tail = (input, pos, ctx, lead2, acc) => {
5612
+ if (cls !== void 0 && !classHas(cls, lead2)) {
5613
+ return next(input, pos, ctx, lead2, appendExpected(acc, staticExpected));
5614
+ }
5615
+ ctx._fc = false;
5616
+ const end = arm.run(input, pos, ctx);
5617
+ if (end >= 0) return end;
5618
+ const nextAcc = appendExpected(acc, ctx._fx);
5619
+ if (committed(ctx)) {
5620
+ if (nextAcc !== void 0) ctx._fx = nextAcc;
5621
+ return -1;
5622
+ }
5623
+ return next(input, pos, ctx, lead2, nextAcc);
5624
+ };
5625
+ }
5626
+ return {
5627
+ match: matchTail,
5628
+ run: (input, pos, ctx) => tail(input, pos, ctx, pos < input.length ? input.codePointAt(pos) : -1, void 0)
5629
+ };
5630
+ }
5631
+ function notNode(body, failure) {
5632
+ return {
5633
+ match: (input, pos) => body.match(input, pos) < 0 ? pos : -1,
5634
+ run: (input, pos, ctx) => {
5635
+ if (body.match(input, pos) < 0) return pos;
5636
+ ctx._fe = pos;
5637
+ ctx._fx = failure;
5638
+ return -1;
5639
+ }
5640
+ };
5641
+ }
5642
+ function optionalNode(body) {
5643
+ return {
5644
+ match: (input, pos) => {
5645
+ const end = body.match(input, pos);
5646
+ return end < 0 ? pos : end;
5647
+ },
5648
+ run: (input, pos, ctx) => {
5649
+ ctx._fc = false;
5650
+ const end = body.run(input, pos, ctx);
5651
+ return end < 0 && !committed(ctx) ? pos : end;
5652
+ }
5653
+ };
5654
+ }
5655
+ function fixedTreeRunner(words, matchers, classes, expected) {
5656
+ const stack = [];
5657
+ const pop = () => {
5658
+ const value = stack.pop();
5659
+ if (value === void 0) throw new TypeError("table lexical tree has an incomplete fixed body");
5660
+ return value;
5661
+ };
5662
+ for (let at = 0; at < words.length; ) {
5663
+ const op = words[at++];
5664
+ if (op === LEX_NODE_TERMINAL) {
5665
+ const matcher = matchers[words[at++]], failure = expected[words[at++]];
5666
+ const tracks = words[at++];
5667
+ if (matcher === void 0 || failure === void 0 || tracks !== 0 && tracks !== 1) {
5668
+ throw new TypeError("table lexical tree terminal references an invalid pool entry");
5669
+ }
5670
+ stack.push(terminalNode(matcher, failure, tracks === 1));
5671
+ continue;
5672
+ }
5673
+ if (op >= LEX_NODE_SEQUENCE2 && op <= LEX_NODE_SEQUENCE5) {
5674
+ const count = op - LEX_NODE_SEQUENCE2 + 2;
5675
+ const nodes = Array.from({ length: count }, pop).reverse();
5676
+ if (count === 2) stack.push(sequence2(nodes[0], nodes[1]));
5677
+ else if (count === 3) stack.push(sequence3(nodes[0], nodes[1], nodes[2]));
5678
+ else if (count === 4) stack.push(sequence4(nodes[0], nodes[1], nodes[2], nodes[3]));
5679
+ else stack.push(sequence5(nodes[0], nodes[1], nodes[2], nodes[3], nodes[4]));
5680
+ continue;
5681
+ }
5682
+ if (op >= LEX_NODE_CHOICE2 && op <= LEX_NODE_CHOICE8) {
5683
+ const count = op === LEX_NODE_CHOICE2 ? 2 : op === LEX_NODE_CHOICE4 ? 4 : 8;
5684
+ const choiceFx = expected[words[at++]];
5685
+ if (choiceFx === void 0) throw new TypeError("table lexical tree choice has an invalid expected set");
5686
+ const armClasses = [];
5687
+ const armFx = [];
5688
+ for (let i = 0; i < count; i++) {
5689
+ const cls = words[at++], fx = expected[words[at++]];
5690
+ if (cls < -1 || cls >= 0 && classes[cls] === void 0 || fx === void 0) {
5691
+ throw new TypeError("table lexical tree choice references an invalid pool entry");
5692
+ }
5693
+ armClasses.push(cls < 0 ? void 0 : classes[cls]);
5694
+ armFx.push(fx);
5695
+ }
5696
+ const arms = Array.from({ length: count }, pop).reverse();
5697
+ stack.push(choiceNode(arms, armClasses, armFx, choiceFx));
5698
+ continue;
5699
+ }
5700
+ if (op === LEX_NODE_NOT) {
5701
+ const failure = expected[words[at++]];
5702
+ if (failure === void 0) throw new TypeError("table lexical tree assertion has an invalid expected set");
5703
+ stack.push(notNode(pop(), failure));
5704
+ continue;
5705
+ }
5706
+ if (op === LEX_NODE_OPTIONAL) {
5707
+ stack.push(optionalNode(pop()));
5708
+ continue;
5709
+ }
5710
+ throw new TypeError("table lexical tree has an unknown fixed body");
5711
+ }
5712
+ if (stack.length !== 1) throw new TypeError("table lexical tree does not resolve to one root body");
5713
+ return stack[0].run;
5714
+ }
5715
+ function buildLexProgramRunner(spec, matchers, classes, expected) {
5716
+ if (spec[0] !== 0 && spec[0] !== 1 && spec[0] !== 2 && spec[0] !== 3 || spec[0] === 0 && spec.length !== 13 || spec[0] === 1 && spec.length !== 12 || spec[0] === 2 && spec.length < 6 || spec[0] === 3 && spec.length !== 3) {
5717
+ throw new TypeError("table lexical program has an invalid fixed body width");
5718
+ }
5719
+ if (spec[1] !== lexProgramDigest(spec.slice(2))) {
5720
+ throw new TypeError("table lexical program semantic digest is inconsistent");
5721
+ }
5722
+ if (spec[0] === 3) {
5723
+ if (!Number.isInteger(spec[2]) || spec[2] < 0) {
5724
+ throw new TypeError("table balanced lexical program has an invalid scan reference");
5725
+ }
5726
+ const run3 = (_input, _pos, ctx, scan) => {
5727
+ if (scan === void 0) throw new TypeError("table balanced lexical program lost its scan body");
5728
+ const result = scan.parse(_input, _pos, ctx);
5729
+ if (!result.ok) {
5730
+ ctx._fe = result.span.start;
5731
+ ctx._fx = result.expected ?? [];
5732
+ return -1;
5733
+ }
5734
+ return result.span.end;
5735
+ };
5736
+ return Object.assign(run3, { scan: spec[2] });
5737
+ }
5738
+ if (spec[0] === 2) return fixedTreeRunner(spec.slice(2), matchers, classes, expected);
5739
+ if (spec[0] === 1) {
5740
+ const g00 = matchers[spec[2]], g01 = matchers[spec[3]];
5741
+ const g02 = matchers[spec[4]], g03 = matchers[spec[5]];
5742
+ const guard0Fx = expected[spec[6]];
5743
+ const g1 = matchers[spec[7]], guard1Fx = expected[spec[8]];
5744
+ const terminal = matchers[spec[9]], terminalFx = expected[spec[10]];
5745
+ const tracks2 = spec[11];
5746
+ if (g00 === void 0 || g01 === void 0 || g02 === void 0 || g03 === void 0 || guard0Fx === void 0 || g1 === void 0 || guard1Fx === void 0 || terminal === void 0 || terminalFx === void 0 || tracks2 !== 0 && tracks2 !== 1) {
5747
+ throw new TypeError("table lexical program references an invalid pool entry");
5748
+ }
5749
+ return (input, pos, ctx) => {
5750
+ ctx._fc = false;
5751
+ if (g00(input, pos) >= 0 || g01(input, pos) >= 0 || g02(input, pos) >= 0 || g03(input, pos) >= 0) {
5752
+ ctx._fe = pos;
5753
+ ctx._fx = guard0Fx;
5754
+ return -1;
5755
+ }
5756
+ ctx._fc = false;
5757
+ if (g1(input, pos) >= 0) {
5758
+ ctx._fe = pos;
5759
+ ctx._fx = guard1Fx;
5760
+ return -1;
5761
+ }
5762
+ ctx._fc = false;
5763
+ const result = terminal(input, pos);
5764
+ if (result < 0) {
5765
+ ctx._fe = pos;
5766
+ ctx._fx = terminalFx;
5767
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
5768
+ return -1;
5769
+ }
5770
+ const end = result / 2;
5771
+ if (tracks2 === 1) trackLexLines(ctx, input, end);
5772
+ return end;
5773
+ };
5774
+ }
5775
+ const cls = classes[spec[2]];
5776
+ const choiceFx = expected[spec[3]];
5777
+ const m0 = matchers[spec[4]], x0 = expected[spec[5]];
5778
+ const m1 = matchers[spec[6]], x1 = expected[spec[7]];
5779
+ const m2 = matchers[spec[8]], x2 = expected[spec[9]];
5780
+ const m3 = matchers[spec[10]], x3 = expected[spec[11]];
5781
+ const tracks = spec[12];
5782
+ if (cls === void 0 || choiceFx === void 0 || m0 === void 0 || x0 === void 0 || m1 === void 0 || x1 === void 0 || m2 === void 0 || x2 === void 0 || m3 === void 0 || x3 === void 0 || tracks !== 0 && tracks !== 1) {
5783
+ throw new TypeError("table lexical program references an invalid pool entry");
5784
+ }
5785
+ return (input, pos, ctx) => {
5786
+ const lead2 = pos < input.length ? input.codePointAt(pos) : -1;
5787
+ if (!classHas(cls, lead2)) {
5788
+ ctx._fe = pos;
5789
+ ctx._fx = choiceFx.slice();
5790
+ return -1;
5791
+ }
5792
+ let acc;
5793
+ const failed = (fx) => {
5794
+ ctx._fe = pos;
5795
+ ctx._fx = fx;
5796
+ if (ctx._probe !== void 0) failAt(ctx, ctx._fx, pos);
5797
+ if (acc === void 0) acc = fx.slice();
5798
+ else acc.push(...fx);
5799
+ };
5800
+ ctx._fc = false;
5801
+ const success = (result2) => {
5802
+ const end = result2 / 2;
5803
+ if (tracks === 1) trackLexLines(ctx, input, end);
5804
+ return end;
5805
+ };
5806
+ let result = m0(input, pos);
5807
+ if (result >= 0) return success(result);
5808
+ failed(x0);
5809
+ ctx._fc = false;
5810
+ result = m1(input, pos);
5811
+ if (result >= 0) return success(result);
5812
+ failed(x1);
5813
+ ctx._fc = false;
5814
+ result = m2(input, pos);
5815
+ if (result >= 0) return success(result);
5816
+ failed(x2);
5817
+ ctx._fc = false;
5818
+ result = m3(input, pos);
5819
+ if (result >= 0) return success(result);
5820
+ failed(x3);
5821
+ ctx._fe = pos;
5822
+ ctx._fx = acc ?? choiceFx;
5823
+ return -1;
5824
+ };
5825
+ }
5826
+
5827
+ // src/table/lex-body.ts
5828
+ function buildLexBodyRecognizer(spec, constants) {
5829
+ const raw = constants[spec[0]];
5830
+ if (!(raw instanceof RegExp)) {
5831
+ throw new TypeError("table lexical body does not reference a RegExp constant");
5832
+ }
5833
+ if (!Number.isInteger(spec[1]) || spec[1] < -1 || spec[1] > 65535) {
5834
+ throw new TypeError("table lexical body suffix is not absent or one UTF-16 code unit");
5835
+ }
5836
+ const re = raw.sticky ? new RegExp(raw.source, raw.flags) : new RegExp(raw.source, `${raw.flags.replace(/[gy]/g, "")}y`);
5837
+ const suffix = spec[1];
5838
+ return (input, pos) => {
5839
+ re.lastIndex = pos;
5840
+ if (!re.test(input)) return -1;
5841
+ const end = re.lastIndex;
5842
+ if (suffix < 0) return end * 2;
5843
+ return input.charCodeAt(end) === suffix ? (end + 1) * 2 + 1 : end * 2;
5844
+ };
5845
+ }
5846
+
5153
5847
  // src/table/program.ts
5154
5848
  function closureArtifact(prog) {
5155
5849
  return { ...prog, asm: [] };
@@ -5193,6 +5887,8 @@ function expandCompact(p) {
5193
5887
  fns: p.f,
5194
5888
  lines: p.l ?? 0,
5195
5889
  dsp: p.p ?? [],
5890
+ ...p.lx === void 0 ? {} : { lex: p.lx },
5891
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
5196
5892
  ...p.lb === void 0 ? {} : { labels: p.lb },
5197
5893
  ...p.rc === void 0 ? {} : { classified: p.rc },
5198
5894
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -5284,7 +5980,7 @@ function resolveClass(spec) {
5284
5980
  }
5285
5981
  return { ascii, hi };
5286
5982
  }
5287
- function classHas(cls, code) {
5983
+ function classHas2(cls, code) {
5288
5984
  if (code < 0) return false;
5289
5985
  if (code < 128) return cls.ascii[code] === 1;
5290
5986
  const hi = cls.hi;
@@ -5337,6 +6033,7 @@ function resolveTable(prog) {
5337
6033
  if (hit !== void 0) return hit;
5338
6034
  const cc = prog.cc.map(resolveClass);
5339
6035
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
6036
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
5340
6037
  const built = {
5341
6038
  prog,
5342
6039
  code: Int32Array.from(prog.code),
@@ -5355,33 +6052,387 @@ function resolveTable(prog) {
5355
6052
  routed: d.routed,
5356
6053
  expected: d.expected
5357
6054
  })),
6055
+ lex,
6056
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
5358
6057
  rules: prog.rules
5359
6058
  };
5360
6059
  if (owner !== void 0) owner.resolved = built;
5361
6060
  return built;
5362
6061
  }
5363
6062
 
5364
- // src/table/encode.ts
5365
- function emittableConst(v) {
5366
- const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
5367
- if (scalar(v) || v instanceof RegExp) return true;
5368
- if (Array.isArray(v)) return v.every(scalar);
5369
- if (typeof v === "object" && v !== null) {
5370
- const proto = Object.getPrototypeOf(v);
5371
- if (proto !== Object.prototype && proto !== null) return false;
5372
- return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
5373
- }
5374
- return false;
6063
+ // src/compiler/direct-projection.ts
6064
+ function directArrayProjection(fn, fnSrc, arity) {
6065
+ let source = fnSrc;
6066
+ if (source === void 0) {
6067
+ source = Function.prototype.toString.call(fn);
6068
+ if (source.includes("[native code]")) return null;
6069
+ }
6070
+ const match = /^\s*\(\s*\[([^\]]*)\]\s*\)\s*=>\s*([A-Za-z_$][\w$]*)\s*$/.exec(source);
6071
+ if (match === null) return null;
6072
+ const slots = match[1].split(",").map((slot) => slot.trim());
6073
+ if (slots.length > arity) return null;
6074
+ const result = match[2];
6075
+ let selected = -1;
6076
+ for (let i = 0; i < slots.length; i++) {
6077
+ const slot = slots[i];
6078
+ if (slot === "") continue;
6079
+ if (!/^[A-Za-z_$][\w$]*$/.test(slot)) return null;
6080
+ if (slot === result) {
6081
+ if (selected >= 0) return null;
6082
+ selected = i;
6083
+ }
6084
+ }
6085
+ return selected >= 0 ? selected : null;
5375
6086
  }
5376
- function wrapsRef(winner, p) {
5377
- let cur = winner;
5378
- for (let n = 0; n < 16; n++) {
5379
- if (cur === p) return true;
5380
- const d = cur._def;
5381
- if (d.tag !== "grammar" && d.tag !== "trivia") return false;
5382
- cur = d.parser;
5383
- }
5384
- return false;
6087
+
6088
+ // src/table/encode.ts
6089
+ import {
6090
+ assertLexicalCapabilityClosure,
6091
+ collectLexicalCapabilities,
6092
+ winnerWrapsReference as winnerWrapsReference2
6093
+ } from "./compiler/token-capability.js";
6094
+
6095
+ // src/compiler/token-alphabet.ts
6096
+ function optionalSuffixLexBody(ir) {
6097
+ if (ir.kind !== "sequence" || ir.parts.length !== 2) return void 0;
6098
+ const [base, suffix] = ir.parts;
6099
+ if (base?.kind !== "regex" || suffix?.kind !== "repeat" || suffix.min !== 0 || suffix.max !== 1 || !suffix.greedy || suffix.mode !== "possessive" || suffix.body.kind !== "literal" || suffix.body.caseInsensitive || suffix.body.value.length !== 1) return void 0;
6100
+ return {
6101
+ kind: "regex-optional-code-unit",
6102
+ source: base.source,
6103
+ flags: base.flags,
6104
+ suffix: suffix.body.value
6105
+ };
6106
+ }
6107
+ function selectOptionalSuffixLexBody(ir) {
6108
+ const body = optionalSuffixLexBody(ir);
6109
+ const character = { strategy: "character", estimatedOps: 5 };
6110
+ if (body === void 0) return character;
6111
+ const token2 = { strategy: "token", estimatedOps: 2, body };
6112
+ return token2.estimatedOps < character.estimatedOps ? token2 : character;
6113
+ }
6114
+ function directTokenBodyParser(parser2, resolve) {
6115
+ const outer = parser2._def;
6116
+ if (outer.tag !== "token") return void 0;
6117
+ let body = outer.parser;
6118
+ const seen = /* @__PURE__ */ new Set();
6119
+ while (!seen.has(body)) {
6120
+ seen.add(body);
6121
+ const wrapper = body._def;
6122
+ if (wrapper.tag === "grammar") {
6123
+ if (wrapper.clearTrivia !== true || wrapper.triviaParser !== void 0 || wrapper.captureTrivia === true || wrapper.rootCapture === "opaque" || wrapper.constructionTrackLines !== "inherit" || wrapper.constructionCaptureTriviaKinds !== void 0) return void 0;
6124
+ body = wrapper.parser;
6125
+ continue;
6126
+ }
6127
+ if (wrapper.tag === "lazy") {
6128
+ const target = resolvedLazyTarget(body, resolve);
6129
+ if (target === void 0) return void 0;
6130
+ body = target;
6131
+ continue;
6132
+ }
6133
+ return body;
6134
+ }
6135
+ return void 0;
6136
+ }
6137
+ function directOptionalSuffixTokenBody(parser2, resolve) {
6138
+ const inner = directTokenBodyParser(parser2, resolve);
6139
+ if (inner === void 0) return void 0;
6140
+ const sequence6 = inner._def;
6141
+ if (sequence6.tag !== "sequence" || sequence6.parsers.length !== 2) return void 0;
6142
+ let baseParser = sequence6.parsers[0];
6143
+ const seenBase = /* @__PURE__ */ new Set();
6144
+ while (baseParser !== void 0 && baseParser._def.tag === "lazy" && !seenBase.has(baseParser)) {
6145
+ seenBase.add(baseParser);
6146
+ baseParser = resolvedLazyTarget(baseParser, resolve);
6147
+ }
6148
+ const base = baseParser?._def;
6149
+ const optional2 = sequence6.parsers[1]?._def;
6150
+ if (base?.tag !== "regex" || optional2?.tag !== "optional") return void 0;
6151
+ const suffix = optional2.parser._def;
6152
+ if (suffix.tag !== "literal" || suffix.caseInsensitive || suffix.value.length !== 1) return void 0;
6153
+ const selected = selectOptionalSuffixLexBody({
6154
+ kind: "sequence",
6155
+ parts: [
6156
+ { kind: "regex", source: base.source, flags: base.flags },
6157
+ {
6158
+ kind: "repeat",
6159
+ body: { kind: "literal", value: suffix.value, caseInsensitive: false },
6160
+ min: 0,
6161
+ max: 1,
6162
+ greedy: true,
6163
+ mode: "possessive"
6164
+ }
6165
+ ]
6166
+ });
6167
+ return selected.strategy === "token" ? {
6168
+ ...selected.body,
6169
+ baseCanMatchNewline: baseParser._meta.canMatchNewline,
6170
+ suffixCanMatchNewline: optional2.parser._meta.canMatchNewline,
6171
+ expected: directTerminalFailureExpected(base)
6172
+ } : void 0;
6173
+ }
6174
+ function directTerminalTokenBody(parser2, resolve) {
6175
+ const outer = parser2._def;
6176
+ if (outer.tag !== "token") return void 0;
6177
+ const body = directTokenBodyParser(parser2, resolve);
6178
+ if (body === void 0) return void 0;
6179
+ const def = body._def;
6180
+ if (def.tag === "regex") return {
6181
+ kind: "regex-terminal",
6182
+ source: def.source,
6183
+ flags: def.flags,
6184
+ canMatchNewline: body._meta.canMatchNewline,
6185
+ expected: directTerminalFailureExpected(def)
6186
+ };
6187
+ if (def.tag !== "keywords") return void 0;
6188
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
6189
+ return {
6190
+ kind: "regex-terminal",
6191
+ source: re.source,
6192
+ flags: re.flags,
6193
+ canMatchNewline: body._meta.canMatchNewline,
6194
+ expected: directTerminalFailureExpected(def)
6195
+ };
6196
+ }
6197
+ function directTerminalParser(parser2, resolve) {
6198
+ const seen = /* @__PURE__ */ new Set();
6199
+ while (!seen.has(parser2)) {
6200
+ seen.add(parser2);
6201
+ const def = parser2._def;
6202
+ if (def.tag === "lazy") {
6203
+ const target = resolvedLazyTarget(parser2, resolve);
6204
+ if (target === void 0) return void 0;
6205
+ parser2 = target;
6206
+ continue;
6207
+ }
6208
+ if (def.tag === "token") {
6209
+ parser2 = def.parser;
6210
+ continue;
6211
+ }
6212
+ if (def.tag === "grammar") return void 0;
6213
+ return parser2;
6214
+ }
6215
+ return void 0;
6216
+ }
6217
+ function directTerminalLexBody(parser2, resolve) {
6218
+ const terminal = directTerminalParser(parser2, resolve);
6219
+ if (terminal === void 0) return void 0;
6220
+ const def = terminal._def;
6221
+ if (def.tag === "literal") {
6222
+ if (def.caseInsensitive) return void 0;
6223
+ const source = def.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6224
+ return {
6225
+ kind: "regex-terminal",
6226
+ source,
6227
+ flags: "",
6228
+ canMatchNewline: terminal._meta.canMatchNewline,
6229
+ expected: directTerminalFailureExpected(def)
6230
+ };
6231
+ }
6232
+ if (def.tag === "regex") return {
6233
+ kind: "regex-terminal",
6234
+ source: def.source,
6235
+ flags: def.flags,
6236
+ canMatchNewline: terminal._meta.canMatchNewline,
6237
+ expected: directTerminalFailureExpected(def)
6238
+ };
6239
+ if (def.tag !== "keywords") return void 0;
6240
+ const re = keywordsRegExp(def.words, def.boundary, def.caseInsensitive);
6241
+ return {
6242
+ kind: "regex-terminal",
6243
+ source: re.source,
6244
+ flags: re.flags,
6245
+ canMatchNewline: terminal._meta.canMatchNewline,
6246
+ expected: directTerminalFailureExpected(def)
6247
+ };
6248
+ }
6249
+ function directOrdered4TokenBody(parser2, resolve) {
6250
+ const body = directTokenBodyParser(parser2, resolve);
6251
+ return body === void 0 ? void 0 : directOrdered4Body(body, resolve);
6252
+ }
6253
+ function directOrdered4Body(body, resolve) {
6254
+ if (body === void 0) return void 0;
6255
+ const choice2 = body._def;
6256
+ if (choice2.tag !== "choice" || choice2.parsers.length !== 4 || choice2.strategy.tag !== "firstMatch" || choice2.gates.some((gate2) => gate2 !== null) || choice2.autoNot.some((check) => check !== null)) return void 0;
6257
+ const arms = [];
6258
+ let common;
6259
+ for (const arm of choice2.parsers) {
6260
+ const selected = directTerminalLexBody(arm, resolve);
6261
+ if (selected === void 0) return void 0;
6262
+ if (selected.canMatchNewline) return void 0;
6263
+ const terminal = directTerminalParser(arm, resolve);
6264
+ const first = firstSetOf(terminal, /* @__PURE__ */ new Set(), resolve);
6265
+ if (first.kind !== "ranges" || first.ranges.length === 0) return void 0;
6266
+ if (common === void 0) common = first;
6267
+ else if (JSON.stringify(common) !== JSON.stringify(first)) return void 0;
6268
+ arms.push(selected);
6269
+ }
6270
+ return {
6271
+ kind: "ordered4-terminals",
6272
+ commonFirstSet: common,
6273
+ commonMissExpected: deriveExpected(body),
6274
+ expected: arms.flatMap((arm) => arm.expected),
6275
+ arms
6276
+ };
6277
+ }
6278
+ function directNot2TokenBody(parser2, resolve) {
6279
+ const body = directTokenBodyParser(parser2, resolve);
6280
+ const sequence6 = body?._def;
6281
+ if (sequence6?.tag !== "sequence" || sequence6.parsers.length !== 3) return void 0;
6282
+ const [guard0Parser, guard1Parser, terminalParser] = sequence6.parsers;
6283
+ const guard0Def = guard0Parser?._def;
6284
+ const guard1Def = guard1Parser?._def;
6285
+ if (guard0Def?.tag !== "not" || guard1Def?.tag !== "not") return void 0;
6286
+ const ordered = directTokenBodyParser(guard0Def.parser, resolve) ?? directTerminalParser(guard0Def.parser, resolve);
6287
+ const guard0Body = ordered === void 0 ? void 0 : directOrdered4Body(ordered, resolve);
6288
+ const guard1 = directTerminalLexBody(guard1Def.parser, resolve);
6289
+ const terminal = terminalParser === void 0 ? void 0 : directTerminalLexBody(terminalParser, resolve);
6290
+ if (guard0Body === void 0 || guard1 === void 0 || terminal === void 0 || guard1.canMatchNewline || terminal.canMatchNewline) return void 0;
6291
+ return {
6292
+ kind: "not2-ordered4-terminal",
6293
+ guard0Expected: assertionFailureExpected(false, guard0Def.parser._tag),
6294
+ guard1Expected: assertionFailureExpected(false, guard1Def.parser._tag),
6295
+ terminalExpected: terminal.expected,
6296
+ guard0: guard0Body.arms,
6297
+ guard1,
6298
+ terminal
6299
+ };
6300
+ }
6301
+ function directFixedLexNode(parser2, resolve, active, pureOnly = false) {
6302
+ let current = parser2;
6303
+ const wrappers = /* @__PURE__ */ new Set();
6304
+ while (!wrappers.has(current)) {
6305
+ wrappers.add(current);
6306
+ const def = current._def;
6307
+ if (def.tag === "lazy") {
6308
+ const target = resolvedLazyTarget(current, resolve);
6309
+ if (target === void 0) return void 0;
6310
+ current = target;
6311
+ continue;
6312
+ }
6313
+ if (def.tag === "token") {
6314
+ current = def.parser;
6315
+ continue;
6316
+ }
6317
+ break;
6318
+ }
6319
+ if (wrappers.has(current) && current !== parser2 && current._def.tag === "lazy") return void 0;
6320
+ if (active.has(current)) return void 0;
6321
+ active.add(current);
6322
+ try {
6323
+ const terminal = directTerminalLexBody(current, resolve);
6324
+ if (terminal !== void 0) return { kind: "terminal", terminal };
6325
+ const def = current._def;
6326
+ if (def.tag === "grammar") {
6327
+ if (!pureOnly || def.parser._def.tag !== "token" && (def.clearTrivia !== true || def.triviaParser !== void 0 || def.captureTrivia === true || def.rootCapture === "opaque")) return void 0;
6328
+ return directFixedLexNode(def.parser, resolve, active, true);
6329
+ }
6330
+ if (def.tag === "sequence") {
6331
+ if (def.parsers.length < 2 || def.parsers.length > 5) return void 0;
6332
+ const parts = def.parsers.map((part) => directFixedLexNode(part, resolve, active, pureOnly));
6333
+ if (parts.some((part) => part === void 0)) return void 0;
6334
+ return { kind: "sequence", parts };
6335
+ }
6336
+ if (def.tag === "choice") {
6337
+ if (def.parsers.length !== 2 && def.parsers.length !== 4 && def.parsers.length !== 8 || def.strategy.tag !== "firstMatch" || def.gates.some((gate2) => gate2 !== null) || def.autoNot.some((check) => check !== null)) return void 0;
6338
+ const arms = def.parsers.map((arm) => directFixedLexNode(arm, resolve, active, pureOnly));
6339
+ if (arms.some((arm) => arm === void 0)) return void 0;
6340
+ const final = classifyFinalChoice(def.parsers, resolve);
6341
+ return {
6342
+ kind: "choice",
6343
+ arms,
6344
+ firstSets: final.firstSets,
6345
+ armExpected: def.parsers.map(deriveExpected),
6346
+ expected: def.parsers.flatMap(deriveExpected)
6347
+ };
6348
+ }
6349
+ if (def.tag === "not") {
6350
+ const body = directFixedLexNode(def.parser, resolve, active, true);
6351
+ return body === void 0 ? void 0 : {
6352
+ kind: "not",
6353
+ body,
6354
+ expected: assertionFailureExpected(false, def.parser._tag)
6355
+ };
6356
+ }
6357
+ if (def.tag === "optional") {
6358
+ const body = directFixedLexNode(def.parser, resolve, active, pureOnly);
6359
+ return body === void 0 ? void 0 : { kind: "optional", body };
6360
+ }
6361
+ return void 0;
6362
+ } finally {
6363
+ active.delete(current);
6364
+ }
6365
+ }
6366
+ function directFixedTokenBody(parser2, resolve) {
6367
+ const body = directTokenBodyParser(parser2, resolve);
6368
+ if (body === void 0) return void 0;
6369
+ const root = directFixedLexNode(body, resolve, /* @__PURE__ */ new Set());
6370
+ return root === void 0 ? void 0 : { kind: "fixed-tree", root };
6371
+ }
6372
+ function directBalancedTokenBody(parser2, resolve) {
6373
+ if (directTokenBodyParser(parser2, resolve) === void 0) return void 0;
6374
+ const spec = balancedSpecOf(parser2);
6375
+ return spec === void 0 ? void 0 : {
6376
+ kind: "balanced-scan",
6377
+ open: spec.open,
6378
+ close: spec.close,
6379
+ raw: spec.raw,
6380
+ strict: spec.strict,
6381
+ ownSkip: spec.ownSkip
6382
+ };
6383
+ }
6384
+ function directExecutableTokenBody(parser2, resolve) {
6385
+ return directOptionalSuffixTokenBody(parser2, resolve) ?? directTerminalTokenBody(parser2, resolve) ?? directOrdered4TokenBody(parser2, resolve) ?? directNot2TokenBody(parser2, resolve) ?? directBalancedTokenBody(parser2, resolve) ?? directFixedTokenBody(parser2, resolve);
6386
+ }
6387
+ function winnerWrapsReference(winner, reference) {
6388
+ let current = winner;
6389
+ const seen = /* @__PURE__ */ new Set();
6390
+ while (!seen.has(current)) {
6391
+ if (current === reference) return true;
6392
+ seen.add(current);
6393
+ const def = current._def;
6394
+ if (def.tag !== "grammar" && def.tag !== "trivia") return false;
6395
+ current = def.parser;
6396
+ }
6397
+ return false;
6398
+ }
6399
+ function resolvedLazyTarget(parser2, resolve) {
6400
+ const def = parser2._def;
6401
+ if (def.tag !== "lazy") return void 0;
6402
+ const name = parser2._ruleName;
6403
+ if (name !== void 0 && resolve !== void 0) {
6404
+ const winner = resolve(name);
6405
+ if (winner !== void 0 && !winnerWrapsReference(winner, parser2)) return winner;
6406
+ }
6407
+ try {
6408
+ return def.thunk();
6409
+ } catch {
6410
+ return void 0;
6411
+ }
6412
+ }
6413
+ function balancedSpecOf(parser2) {
6414
+ let current = parser2;
6415
+ let spec = current._balancedSpec;
6416
+ const seen = /* @__PURE__ */ new Set();
6417
+ while (spec === void 0 && current._def.tag === "token" && !seen.has(current)) {
6418
+ seen.add(current);
6419
+ current = current._def.parser;
6420
+ spec = current._balancedSpec;
6421
+ }
6422
+ return spec;
6423
+ }
6424
+
6425
+ // src/table/encode.ts
6426
+ function emittableConst(v) {
6427
+ const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
6428
+ if (scalar(v) || v instanceof RegExp) return true;
6429
+ if (Array.isArray(v)) return v.every(scalar);
6430
+ if (typeof v === "object" && v !== null) {
6431
+ const proto = Object.getPrototypeOf(v);
6432
+ if (proto !== Object.prototype && proto !== null) return false;
6433
+ return Object.values(v).every((x) => scalar(x) || Array.isArray(x) && x.every(scalar));
6434
+ }
6435
+ return false;
5385
6436
  }
5386
6437
  var UnsupportedConstruct = class extends Error {
5387
6438
  tag;
@@ -5414,6 +6465,10 @@ var Encoder = class {
5414
6465
  fx = [];
5415
6466
  disp = [];
5416
6467
  dsp = [];
6468
+ lex = [];
6469
+ lexIndex = /* @__PURE__ */ new Map();
6470
+ lexPrograms = [];
6471
+ lexProgramIndex = /* @__PURE__ */ new Map();
5417
6472
  labels = void 0;
5418
6473
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
5419
6474
  activeTrivia = void 0;
@@ -5484,6 +6539,146 @@ var Encoder = class {
5484
6539
  this.triviaSpecs.push(this.triviaSpecOf(t));
5485
6540
  return idx;
5486
6541
  }
6542
+ lexicalBodySlot(p) {
6543
+ if (!this.selectLexicalBodies) return void 0;
6544
+ const body = directExecutableTokenBody(p, (name) => this.winners?.[name]);
6545
+ if (body === void 0) return void 0;
6546
+ const tokenDef = p._def;
6547
+ if (tokenDef.tag !== "token") throw new Error("parseman: selected lexical body lost token boundary");
6548
+ const matcher = (arm) => {
6549
+ const flags2 = arm.flags.includes("y") ? arm.flags : `${arm.flags.replace(/g/g, "")}y`;
6550
+ const regex3 = this.constant(new RegExp(arm.source, flags2));
6551
+ const key2 = `${regex3}:-1`;
6552
+ const prior2 = this.lexIndex.get(key2);
6553
+ if (prior2 !== void 0) return prior2;
6554
+ const id2 = this.lex.length;
6555
+ this.lexIndex.set(key2, id2);
6556
+ this.lex.push([regex3, -1]);
6557
+ return id2;
6558
+ };
6559
+ if (body.kind === "balanced-scan") {
6560
+ const scan = this.scanSlot({
6561
+ kind: 1,
6562
+ flags: (body.raw ? 1 : 0) | (body.strict ? 4 : 0),
6563
+ skip: body.ownSkip.map((combinator) => this.subtree(combinator)),
6564
+ open: body.open,
6565
+ close: body.close
6566
+ });
6567
+ const words = [scan];
6568
+ const spec = [3, lexProgramDigest(words), scan];
6569
+ const key2 = spec.join(",");
6570
+ const prior2 = this.lexProgramIndex.get(key2);
6571
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6572
+ const id2 = this.lexPrograms.length;
6573
+ this.lexProgramIndex.set(key2, id2);
6574
+ this.lexPrograms.push(spec);
6575
+ return { kind: "program", program: id2 };
6576
+ }
6577
+ if (body.kind === "fixed-tree") {
6578
+ const words = [];
6579
+ const emitNode = (node2) => {
6580
+ switch (node2.kind) {
6581
+ case "terminal":
6582
+ words.push(
6583
+ LEX_NODE_TERMINAL,
6584
+ matcher(node2.terminal),
6585
+ this.expected(node2.terminal.expected),
6586
+ this.track ? 1 : 0
6587
+ );
6588
+ return true;
6589
+ case "sequence": {
6590
+ for (const part of node2.parts) if (!emitNode(part)) return false;
6591
+ const op = node2.parts.length === 2 ? LEX_NODE_SEQUENCE2 : node2.parts.length === 3 ? LEX_NODE_SEQUENCE3 : node2.parts.length === 4 ? LEX_NODE_SEQUENCE4 : node2.parts.length === 5 ? LEX_NODE_SEQUENCE5 : -1;
6592
+ if (op < 0) return false;
6593
+ words.push(op);
6594
+ return true;
6595
+ }
6596
+ case "choice": {
6597
+ for (const arm of node2.arms) if (!emitNode(arm)) return false;
6598
+ const op = node2.arms.length === 2 ? LEX_NODE_CHOICE2 : node2.arms.length === 4 ? LEX_NODE_CHOICE4 : node2.arms.length === 8 ? LEX_NODE_CHOICE8 : -1;
6599
+ if (op < 0) return false;
6600
+ words.push(op, this.expected(node2.expected));
6601
+ for (let i = 0; i < node2.arms.length; i++) {
6602
+ const first = node2.firstSets[i];
6603
+ words.push(first.kind === "ranges" ? this.charClass(first) : -1);
6604
+ words.push(this.expected(node2.armExpected[i]));
6605
+ }
6606
+ return true;
6607
+ }
6608
+ case "not":
6609
+ if (!emitNode(node2.body)) return false;
6610
+ words.push(LEX_NODE_NOT, this.expected(node2.expected));
6611
+ return true;
6612
+ case "optional":
6613
+ if (!emitNode(node2.body)) return false;
6614
+ words.push(LEX_NODE_OPTIONAL);
6615
+ return true;
6616
+ }
6617
+ };
6618
+ if (!emitNode(body.root)) return void 0;
6619
+ const spec = [2, lexProgramDigest(words), ...words];
6620
+ const key2 = spec.join(",");
6621
+ const prior2 = this.lexProgramIndex.get(key2);
6622
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6623
+ const id2 = this.lexPrograms.length;
6624
+ this.lexProgramIndex.set(key2, id2);
6625
+ this.lexPrograms.push(spec);
6626
+ return { kind: "program", program: id2 };
6627
+ }
6628
+ if (body.kind === "not2-ordered4-terminal") {
6629
+ const words = [
6630
+ ...body.guard0.map(matcher),
6631
+ this.expected(body.guard0Expected),
6632
+ matcher(body.guard1),
6633
+ this.expected(body.guard1Expected),
6634
+ matcher(body.terminal),
6635
+ this.expected(body.terminalExpected),
6636
+ this.track ? 1 : 0
6637
+ ];
6638
+ const spec = [1, lexProgramDigest(words), ...words];
6639
+ const key2 = spec.join(",");
6640
+ const prior2 = this.lexProgramIndex.get(key2);
6641
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6642
+ const id2 = this.lexPrograms.length;
6643
+ this.lexProgramIndex.set(key2, id2);
6644
+ this.lexPrograms.push(spec);
6645
+ return { kind: "program", program: id2 };
6646
+ }
6647
+ if (body.kind === "ordered4-terminals") {
6648
+ const commonClass = this.charClass(body.commonFirstSet);
6649
+ if (commonClass < 0) return void 0;
6650
+ const words = [commonClass, this.expected(body.commonMissExpected)];
6651
+ for (const arm of body.arms) {
6652
+ words.push(matcher(arm), this.expected(arm.expected));
6653
+ }
6654
+ words.push(this.track ? 1 : 0);
6655
+ const spec = [0, lexProgramDigest(words), ...words];
6656
+ const key2 = spec.join(",");
6657
+ const prior2 = this.lexProgramIndex.get(key2);
6658
+ if (prior2 !== void 0) return { kind: "program", program: prior2 };
6659
+ const id2 = this.lexPrograms.length;
6660
+ this.lexProgramIndex.set(key2, id2);
6661
+ this.lexPrograms.push(spec);
6662
+ return { kind: "program", program: id2 };
6663
+ }
6664
+ const expectedFx = this.expected(body.expected);
6665
+ const flags = body.flags.includes("y") ? body.flags : `${body.flags.replace(/g/g, "")}y`;
6666
+ const regex2 = this.constant(new RegExp(body.source, flags));
6667
+ const suffix = body.kind === "regex-terminal" ? -1 : body.suffix.charCodeAt(0);
6668
+ const key = `${regex2}:${suffix}`;
6669
+ const prior = this.lexIndex.get(key);
6670
+ const suffixFx = this.expected(body.kind === "regex-terminal" ? [] : directTerminalFailureExpected({
6671
+ tag: "literal",
6672
+ value: body.suffix,
6673
+ caseInsensitive: false
6674
+ }));
6675
+ const lineFlags = this.track ? body.kind === "regex-terminal" ? 1 : 1 | 2 | 4 : body.kind === "regex-terminal" ? 0 : 4;
6676
+ if (prior !== void 0) return { kind: "body", body: prior, expectedFx, suffixFx, lineFlags };
6677
+ const id = this.lex.length;
6678
+ this.lexIndex.set(key, id);
6679
+ this.lex.push([regex2, suffix]);
6680
+ return { kind: "body", body: id, expectedFx, suffixFx, lineFlags };
6681
+ }
5487
6682
  triviaSpecOf(t) {
5488
6683
  const unlowered = (why) => {
5489
6684
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -5567,6 +6762,9 @@ var Encoder = class {
5567
6762
  settings;
5568
6763
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
5569
6764
  track;
6765
+ /** TOKEN bodies are an all-program decision. A complete occurrence inside an
6766
+ * otherwise incomplete final graph stays on CHARACTER with every sibling. */
6767
+ selectLexicalBodies;
5570
6768
  /**
5571
6769
  * Decides the extra operands laid down below. ALWAYS TRUE — see
5572
6770
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -5574,9 +6772,10 @@ var Encoder = class {
5574
6772
  * row is stated.
5575
6773
  */
5576
6774
  rec;
5577
- constructor(settings) {
6775
+ constructor(settings, selectLexicalBodies) {
5578
6776
  this.settings = settings;
5579
6777
  this.track = settings.trackLines === true;
6778
+ this.selectLexicalBodies = selectLexicalBodies;
5580
6779
  this.rec = true;
5581
6780
  this.plan = settings.coverage;
5582
6781
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -5691,6 +6890,13 @@ var Encoder = class {
5691
6890
  this.ccIndex.set(spec, i);
5692
6891
  return i;
5693
6892
  }
6893
+ /** Bind a guard only when its class is already part of the program. Repeat
6894
+ * gating must not grow the compact artifact merely to avoid a failed call. */
6895
+ existingCharClass(fs) {
6896
+ if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
6897
+ const hit = this.ccIndex.get(encodeClassSpec(fs.ranges));
6898
+ return hit !== void 0 && hit < 100 ? hit : -1;
6899
+ }
5694
6900
  /**
5695
6901
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
5696
6902
  *
@@ -5779,7 +6985,7 @@ var Encoder = class {
5779
6985
  * in the target rule's own ambient trivia when that differs from the trivia
5780
6986
  * lexically active at the reference.
5781
6987
  *
5782
- * `encodeRule` wraps a rule ENTRY in `OP_SCOPE`, but only the entry: a `g.X`
6988
+ * `encodeRule` wraps a rule ENTRY in `OP_SCOPE_PLAIN`, but only the entry: a `g.X`
5783
6989
  * reference resolves straight to the body's offset and jumps past it (the note
5784
6990
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
5785
6991
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -5856,6 +7062,19 @@ var Encoder = class {
5856
7062
  }
5857
7063
  encodeDef(p) {
5858
7064
  const d = p._def;
7065
+ if (d.tag === "token") {
7066
+ const selected = this.lexicalBodySlot(p);
7067
+ if (selected !== void 0) {
7068
+ if (selected.kind === "program") return this.emit(OP_LEX_PROGRAM, selected.program);
7069
+ return this.emit(
7070
+ OP_LEX_BODY,
7071
+ selected.body,
7072
+ selected.expectedFx,
7073
+ selected.suffixFx,
7074
+ selected.lineFlags
7075
+ );
7076
+ }
7077
+ }
5859
7078
  const bal = p._balancedSpec;
5860
7079
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
5861
7080
  kind: 1,
@@ -5877,13 +7096,13 @@ var Encoder = class {
5877
7096
  switch (d.tag) {
5878
7097
  case "literal": {
5879
7098
  if (d.caseInsensitive) {
5880
- return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(deriveExpected(p)));
7099
+ return this.emit(this.track ? OP_LIT_CI_TRACK : OP_LIT_CI, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
5881
7100
  }
5882
- return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(deriveExpected(p)));
7101
+ return this.emit(this.track ? OP_LIT_TRACK : OP_LIT, this.constant(d.value), this.expected(directTerminalFailureExpected(d)));
5883
7102
  }
5884
7103
  case "regex": {
5885
7104
  const flags = d.flags.includes("y") ? d.flags : `${d.flags}y`;
5886
- return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(deriveExpected(p)));
7105
+ return this.emit(this.track ? OP_RX_TRACK : OP_RX, this.constant(new RegExp(d.source, flags)), this.expected(directTerminalFailureExpected(d)));
5887
7106
  }
5888
7107
  case "keywords": {
5889
7108
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -5897,7 +7116,7 @@ var Encoder = class {
5897
7116
  // failing keyword arm names the CATEGORY rather than reciting every
5898
7117
  // literal in the family. `deriveExpected` reports the literals, so the
5899
7118
  // table said `'"media"'` where both other engines say `'keyword'`.
5900
- this.expected(["keyword"])
7119
+ this.expected(directTerminalFailureExpected(d))
5901
7120
  );
5902
7121
  }
5903
7122
  case "expect": {
@@ -5944,7 +7163,8 @@ var Encoder = class {
5944
7163
  return this.covWrap(gated, armCovIds?.[src], 1);
5945
7164
  });
5946
7165
  const rr = this.refResolver();
5947
- const classes = arms.map((a) => matchesEmpty(a, /* @__PURE__ */ new Set(), rr) ? -1 : this.charClass(firstSetOf(a, /* @__PURE__ */ new Set(), rr)));
7166
+ const finalChoice = classifyFinalChoice(arms, rr);
7167
+ const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
5948
7168
  const dispIdx = this.disp.length;
5949
7169
  this.disp.push(classes);
5950
7170
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -5960,9 +7180,11 @@ var Encoder = class {
5960
7180
  case "many":
5961
7181
  case "oneOrMore": {
5962
7182
  const child = this.node(d.parser).ip;
7183
+ const rr = this.refResolver();
7184
+ const itemClass = matchesEmpty(d.parser, /* @__PURE__ */ new Set(), rr) ? -1 : this.existingCharClass(firstSetOf(d.parser, /* @__PURE__ */ new Set(), rr));
5963
7185
  const op = d.valueUnused ? OP_REPV : OP_REP;
5964
7186
  const min = d.tag === "many" ? 0 : d.min;
5965
- return this.rec ? this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), -1) : this.emit(op, child, min, d.max ?? -1, -1, 0);
7187
+ return this.rec ? this.emit(op, child, min, d.max ?? -1, -1, 0, this.expected(deriveExpected(d.parser)), itemClass) : this.emit(op, child, min, d.max ?? -1, -1, 0);
5966
7188
  }
5967
7189
  case "sepBy": {
5968
7190
  const child = this.node(d.parser).ip;
@@ -5989,7 +7211,8 @@ var Encoder = class {
5989
7211
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
5990
7212
  const kids = inner.parsers.map((c) => this.node(c).ip);
5991
7213
  const head = this.emitHead(OP_SEQX, 2 + kids.length + (this.rec ? kids.length : 0));
5992
- this.code[head + 1] = this.fn(d.fn, d.fnSrc ?? null);
7214
+ const projection = directArrayProjection(d.fn, d.fnSrc, kids.length);
7215
+ this.code[head + 1] = projection === null ? this.fn(d.fn, d.fnSrc ?? null) : ~projection;
5993
7216
  this.code[head + 2] = kids.length;
5994
7217
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
5995
7218
  if (this.rec) {
@@ -6010,10 +7233,11 @@ var Encoder = class {
6010
7233
  const cstOut = this.settings.hostMode === "cst";
6011
7234
  const noBuildCaptures = d.project === void 0;
6012
7235
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
7236
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
6013
7237
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
6014
7238
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
6015
7239
  const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
6016
- const flags = (cstOut || d.captureTrivia === true || d.trailingTrivia === true || derivedTrivia ? 4 : 0) | (cstOut || derivedState ? 8 : 0) | (wantsFields ? 16 : 0) | (d.collapse === true ? 32 : 0) | (d.unwrap === true ? 64 : 0) | (d.trailingTrivia === true ? 128 : 0) | (d.captureTrivia === true ? 1 : 0);
7240
+ const flags = (cstOut || d.captureTrivia === true || d.trailingTrivia === true || derivedTrivia ? 4 : 0) | (!cstOut && omitsRaw ? 2 : 0) | (cstOut || derivedState ? 8 : 0) | (wantsFields ? 16 : 0) | (d.collapse === true ? 32 : 0) | (d.unwrap === true ? 64 : 0) | (d.trailingTrivia === true ? 128 : 0) | (d.captureTrivia === true ? 1 : 0);
6017
7241
  const body = this.emit(
6018
7242
  this.track ? OP_NODE_TRACK : OP_NODE,
6019
7243
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -6034,8 +7258,9 @@ var Encoder = class {
6034
7258
  const e = deriveExpected(d.parser);
6035
7259
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
6036
7260
  }
6037
- case "token":
7261
+ case "token": {
6038
7262
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
7263
+ }
6039
7264
  case "routed":
6040
7265
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
6041
7266
  case "dispatch": {
@@ -6100,7 +7325,7 @@ var Encoder = class {
6100
7325
  case "lazy": {
6101
7326
  const refName = p._ruleName;
6102
7327
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
6103
- if (winner !== void 0 && !wrapsRef(winner, p)) return this.scopedRef(p, winner);
7328
+ if (winner !== void 0 && !winnerWrapsReference2(winner, p)) return this.scopedRef(p, winner);
6104
7329
  let resolved;
6105
7330
  try {
6106
7331
  resolved = d.thunk();
@@ -6116,7 +7341,7 @@ var Encoder = class {
6116
7341
  // other engine reported `['not(literal)']`. It hid because `expected` is a
6117
7342
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
6118
7343
  case "not":
6119
- return this.emit(OP_NOT, this.node(d.parser).ip, this.expected([`not(${d.parser._tag})`]));
7344
+ return this.emit(OP_NOT, this.node(d.parser).ip, this.expected(assertionFailureExpected(false, d.parser._tag)));
6120
7345
  case "guard":
6121
7346
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
6122
7347
  case "adjacency":
@@ -6134,7 +7359,7 @@ var Encoder = class {
6134
7359
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
6135
7360
  }
6136
7361
  case "peek":
6137
- return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected([`peek(${d.parser._tag})`]));
7362
+ return this.emit(OP_PEEK, this.node(d.parser).ip, this.expected(assertionFailureExpected(true, d.parser._tag)));
6138
7363
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
6139
7364
  // lowering was correct only for a choice arm.
6140
7365
  case "attempt": {
@@ -6295,6 +7520,8 @@ var Encoder = class {
6295
7520
  disp: this.disp,
6296
7521
  dsp: this.dsp,
6297
7522
  rules: this.rules,
7523
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
7524
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
6298
7525
  ...this.labels === void 0 ? {} : { labels: this.labels },
6299
7526
  ...this.classified ? { classified: 1 } : {},
6300
7527
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -6349,7 +7576,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
6349
7576
  ...hostMode === void 0 ? {} : { hostMode },
6350
7577
  ...track ? { trackLines: true } : {}
6351
7578
  };
6352
- const enc = new Encoder(resolvedSettings);
7579
+ const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
7580
+ const resolveLexical = (name) => ruleMap[name];
7581
+ const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
7582
+ assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
7583
+ const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
6353
7584
  enc.winners = ruleMap;
6354
7585
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
6355
7586
  const prog = enc.finish();
@@ -7394,6 +8625,8 @@ function childSlots(code, ip, out) {
7394
8625
  case OP_GUARD:
7395
8626
  case OP_ADJ:
7396
8627
  case OP_LIVE:
8628
+ case OP_LEX_BODY:
8629
+ case OP_LEX_PROGRAM:
7397
8630
  return true;
7398
8631
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
7399
8632
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -7511,7 +8744,12 @@ function transfer(code, ip, at, hostCst) {
7511
8744
  return { tri, buf: at.buf, cap };
7512
8745
  }
7513
8746
  if (op === OP_NODE || op === OP_NODE_TRACK) {
7514
- const cap = (code[ip + 3] & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
8747
+ const flags = code[ip + 3];
8748
+ const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
8749
+ if (directChildren) {
8750
+ return { tri: at.tri, buf: false, cap: CAP_OFF };
8751
+ }
8752
+ const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
7515
8753
  if (at.buf && cap === at.cap) return at;
7516
8754
  return { tri: at.tri, buf: true, cap };
7517
8755
  }
@@ -7552,6 +8790,43 @@ function computeSiteLabels(code, roots, hostCst) {
7552
8790
  return { at: (ip) => labels.get(ip) ?? TOP };
7553
8791
  }
7554
8792
 
8793
+ // src/table/scalar-terminal.ts
8794
+ function makeScalarRecognizer(op, spec) {
8795
+ if (op === OP_RX && spec instanceof RegExp) {
8796
+ return (input, pos) => {
8797
+ spec.lastIndex = pos;
8798
+ return spec.test(input) ? spec.lastIndex : -1;
8799
+ };
8800
+ }
8801
+ if (op !== OP_LIT || typeof spec !== "string") return void 0;
8802
+ const len = spec.length;
8803
+ if (len === 1) {
8804
+ const c0 = spec.charCodeAt(0);
8805
+ return (input, pos) => input.charCodeAt(pos) === c0 ? pos + 1 : -1;
8806
+ }
8807
+ if (len === 2) {
8808
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1);
8809
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 ? pos + 2 : -1;
8810
+ }
8811
+ if (len === 3) {
8812
+ const c0 = spec.charCodeAt(0), c1 = spec.charCodeAt(1), c2 = spec.charCodeAt(2);
8813
+ return (input, pos) => input.charCodeAt(pos) === c0 && input.charCodeAt(pos + 1) === c1 && input.charCodeAt(pos + 2) === c2 ? pos + 3 : -1;
8814
+ }
8815
+ return (input, pos) => input.startsWith(spec, pos) ? pos + len : -1;
8816
+ }
8817
+ function scalarTerminalNodeChild(code, ip) {
8818
+ if (code[ip + 1] < 0 || code[ip + 3] !== 0 || code[ip + 4] !== -1) return -1;
8819
+ const child = code[ip + 2];
8820
+ const op = code[child];
8821
+ return op === OP_RX || op === OP_LIT ? child : -1;
8822
+ }
8823
+ function scalarTerminalNotChild(code, ip) {
8824
+ if (code[ip] !== OP_NOT) return -1;
8825
+ const child = code[ip + 1];
8826
+ const op = code[child];
8827
+ return op === OP_RX || op === OP_LIT ? child : -1;
8828
+ }
8829
+
7555
8830
  // src/table/emit-assembly.ts
7556
8831
  var Unemittable = class extends Error {
7557
8832
  construct;
@@ -7613,7 +8888,19 @@ var EMITTED_PARAMS = [
7613
8888
  "matchesAt",
7614
8889
  "recoverScan",
7615
8890
  "orSentinel",
7616
- "captureError"
8891
+ "captureError",
8892
+ // Pure scalar terminal recognizers, indexed by the terminal's existing const
8893
+ // operand. Appended for compatibility with older precompiled factories.
8894
+ "RECOG",
8895
+ // Appended so precompiled factories produced by earlier runtimes keep every
8896
+ // positional helper binding. Older factories ignore this trailing argument.
8897
+ "commitTriviaScan",
8898
+ "scanTriviaCompact",
8899
+ "LEX",
8900
+ // Appended for old precompiled-factory ABI: old factories ignore it.
8901
+ "adjacencyHolds",
8902
+ // Appended for selected composite lexical programs; old factories ignore it.
8903
+ "LEXPROG"
7617
8904
  ];
7618
8905
  var RUNTIME_PRELUDE = `
7619
8906
  let _pfScan=null
@@ -7624,7 +8911,7 @@ function _skipTrivia(input,cur,ctx){
7624
8911
  const s=_pfScan
7625
8912
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
7626
8913
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
7627
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
8914
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
7628
8915
  return advanceTrivia(input,cur,ctx)
7629
8916
  }
7630
8917
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -7638,6 +8925,13 @@ if(b.raw!==undefined)b.raw.push(l)
7638
8925
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
7639
8926
  else b.rawSingle=l
7640
8927
  }
8928
+ function _capturedFlatChildren(children){
8929
+ if(children.length===0)return EMPTY_CH
8930
+ if(children[0]!==undefined)return children
8931
+ let first=1
8932
+ while(first<children.length&&children[first]===undefined)first++
8933
+ return first===children.length?EMPTY_CH:children.slice(first)
8934
+ }
7641
8935
  function _accSet(ax,acc){
7642
8936
  if(ax===undefined||ax.length===0)return acc
7643
8937
  if(acc===undefined)return ax.slice()
@@ -7772,12 +9066,16 @@ function maskForClassRow(gates) {
7772
9066
  }
7773
9067
  return m;
7774
9068
  }
7775
- function rebuildPools(cc, fx, plan) {
9069
+ function rebuildPools(cc, fx, disp, plan) {
7776
9070
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
7777
9071
  return {
7778
9072
  classes,
7779
9073
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
7780
- masks: plan.masks.map((ci) => maskForClassRow(classes[ci]))
9074
+ masks: plan.masks.map((source) => {
9075
+ const row = source >= 0 ? classes[source] : disp[~source]?.armCls;
9076
+ if (row === void 0) throw new TypeError(`table emitter: invalid MASK plan source ${source}`);
9077
+ return maskForClassRow(row);
9078
+ })
7781
9079
  };
7782
9080
  }
7783
9081
  function emitAssemblySource(t, prog, cfg, extraIps = []) {
@@ -7788,6 +9086,14 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7788
9086
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
7789
9087
  const roots = [...Object.values(prog.rules), ...extraIps];
7790
9088
  const labels = computeSiteLabels(code, roots, hostCst);
9089
+ const scalarSpecs = /* @__PURE__ */ new Set();
9090
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
9091
+ for (const ip of reachableSites(code, roots)) {
9092
+ if (code[ip] !== OP_NODE) continue;
9093
+ const child = scalarTerminalNodeChild(code, ip);
9094
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
9095
+ }
9096
+ }
7791
9097
  const sinks = (() => {
7792
9098
  let fd = false;
7793
9099
  let er = REC2;
@@ -7808,6 +9114,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7808
9114
  const reached = /* @__PURE__ */ new Set();
7809
9115
  const prelude = [];
7810
9116
  const skipDefs = [];
9117
+ const choiceDefs = [];
7811
9118
  const skipPool = /* @__PURE__ */ new Map();
7812
9119
  const pool = /* @__PURE__ */ new Map();
7813
9120
  const masks = [];
@@ -7827,6 +9134,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7827
9134
  const kRef = (i) => hoist("k", `K[${i}]`);
7828
9135
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
7829
9136
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
9137
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
7830
9138
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
7831
9139
  let uid = 0;
7832
9140
  const tmp = () => `_t${uid++}_`;
@@ -7840,8 +9148,8 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7840
9148
  const nm = `_sk${skipPool.size}`;
7841
9149
  skipPool.set(key, nm);
7842
9150
  if (!hasScan) {
7843
- skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){const s=scanTrivia(input,cur,ctx);s.commit();return s.end}` : `function ${nm}(input,cur,ctx){
7844
- if(needsDeferredTriviaCommit(ctx)){const s=scanTrivia(input,cur,ctx);s.commit();return s.end}
9151
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return commitTriviaScan(scanTriviaCompact(input,cur,ctx))}` : `function ${nm}(input,cur,ctx){
9152
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
7845
9153
  return advanceTrivia(input,cur,ctx)}`);
7846
9154
  return nm;
7847
9155
  }
@@ -7928,6 +9236,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7928
9236
  const s = k[code[ip + 1]];
7929
9237
  const xf = fxRef(code[ip + 2]);
7930
9238
  const track = op === OP_LIT_TRACK;
9239
+ if (!track && scalarSpecs.has(code[ip + 1])) {
9240
+ const recognize = recognizerRef(code[ip + 1]);
9241
+ return `${head}
9242
+ const e=${recognize}(input,pos)
9243
+ if(e>=0){
9244
+ ${captureLeaf(q(s))}
9245
+ EC.e=e
9246
+ return ${q(s)}
9247
+ }
9248
+ ctx._fe=pos;ctx._fx=${xf}
9249
+ return FAIL
9250
+ }`;
9251
+ }
7931
9252
  const test = s.length === 1 ? `input.charCodeAt(pos)===${s.charCodeAt(0)}` : s.length === 2 ? `input.charCodeAt(pos)===${s.charCodeAt(0)}&&input.charCodeAt(pos+1)===${s.charCodeAt(1)}` : `input.startsWith(${q(s)},pos)`;
7932
9253
  return `${head}
7933
9254
  if(${test}){
@@ -7977,6 +9298,20 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7977
9298
  case OP_RX_TRACK: {
7978
9299
  const xf = fxRef(code[ip + 2]);
7979
9300
  const track = op === OP_RX_TRACK;
9301
+ if (!track && scalarSpecs.has(code[ip + 1])) {
9302
+ const recognize = recognizerRef(code[ip + 1]);
9303
+ return `${head}
9304
+ const e=${recognize}(input,pos)
9305
+ if(e>=0){
9306
+ const v=input.slice(pos,e)
9307
+ ${captureLeaf("v")}
9308
+ EC.e=e
9309
+ return v
9310
+ }
9311
+ ctx._fe=pos;ctx._fx=${xf}
9312
+ return FAIL
9313
+ }`;
9314
+ }
7980
9315
  const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
7981
9316
  if (scanned !== void 0) return `${head}${scanned}}`;
7982
9317
  const rxk = k[code[ip + 1]];
@@ -8138,6 +9473,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
8138
9473
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
8139
9474
  EC.e=e
8140
9475
  return out
9476
+ }`;
9477
+ }
9478
+ case OP_LEX_BODY: {
9479
+ const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
9480
+ const expected = fxRef(code[ip + 2]);
9481
+ const suffixExpected = fxRef(code[ip + 3]);
9482
+ const lineFlags = code[ip + 4];
9483
+ const hasSuffix = (lineFlags & 4) !== 0;
9484
+ return `${head}
9485
+ const r=${recognize}(input,pos)
9486
+ if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
9487
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
9488
+ ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
9489
+ ${hasSuffix ? "ctx._fc=false" : ""}
9490
+ ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
9491
+ ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
9492
+ const v=input.slice(pos,e)
9493
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9494
+ EC.e=e
9495
+ return v
9496
+ }`;
9497
+ }
9498
+ case OP_LEX_PROGRAM: {
9499
+ const programId = code[ip + 1];
9500
+ const run3 = hoist("lexProgram", `LEXPROG[${programId}]`);
9501
+ const scanId = t.lexPrograms[programId].scan;
9502
+ if (scanId !== void 0) return `${head}
9503
+ const sTri=ctx.trivia,sKinds=ctx.triviaKindLabels,sScan=_pfScan
9504
+ const sBuf=ctx._cstBuf,sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
9505
+ const sOtl=ctx._triviaLog,sRtl=ctx._rootTriviaLog
9506
+ const wasCap=ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined
9507
+ _pfScan=null
9508
+ ctx.trivia=undefined
9509
+ ctx.triviaKindLabels=undefined
9510
+ ctx._cstBuf=undefined
9511
+ ctx._cstChildren=undefined
9512
+ ctx._cstLeaves=undefined
9513
+ ctx._cstRawChildren=undefined
9514
+ ctx._cstTriviaLog=undefined
9515
+ ctx._triviaLog=undefined
9516
+ ctx._rootTriviaLog=undefined
9517
+ let e
9518
+ try{e=${run3}(input,pos,ctx,SCANS[${scanId}])}finally{
9519
+ _pfScan=sScan
9520
+ ctx.trivia=sTri
9521
+ ctx.triviaKindLabels=sKinds
9522
+ ctx._cstBuf=sBuf
9523
+ ctx._cstChildren=sCh
9524
+ ctx._cstLeaves=sLv
9525
+ ctx._cstRawChildren=sRaw
9526
+ ctx._cstTriviaLog=sTl
9527
+ ctx._triviaLog=sOtl
9528
+ ctx._rootTriviaLog=sRtl
9529
+ }
9530
+ if(e<0)return FAIL
9531
+ const v=input.slice(pos,e)
9532
+ if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9533
+ EC.e=e
9534
+ return v
9535
+ }`;
9536
+ return `${head}
9537
+ const e=${run3}(input,pos,ctx)
9538
+ if(e<0)return FAIL
9539
+ const v=input.slice(pos,e)
9540
+ if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9541
+ EC.e=e
9542
+ return v
8141
9543
  }`;
8142
9544
  }
8143
9545
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -8155,6 +9557,18 @@ return FAIL
8155
9557
  }`;
8156
9558
  }
8157
9559
  case OP_NOT: {
9560
+ const scalarChild = scalarTerminalNotChild(code, ip);
9561
+ if (scalarChild >= 0) {
9562
+ const recognize = recognizerRef(code[scalarChild + 1]);
9563
+ const xf2 = fxRef(code[ip + 2]);
9564
+ return `${head}
9565
+ if(${recognize}(input,pos)<0){EC.e=pos;return null}
9566
+ ctx._fe=pos
9567
+ ctx._fx=${xf2}
9568
+ EC.e=pos
9569
+ return FAIL
9570
+ }`;
9571
+ }
8158
9572
  const child = link(code[ip + 1]);
8159
9573
  const xf = fxRef(code[ip + 2]);
8160
9574
  const p = tmp();
@@ -8204,14 +9618,14 @@ return v
8204
9618
  const base = fused ? ip + 3 : ip + 2;
8205
9619
  const n = code[fused ? ip + 2 : ip + 1];
8206
9620
  const wantValues = op !== OP_SEQV;
8207
- for (let i = 1; i < n; i++) {
8208
- if (code[code[base + i]] === OP_ADJ) {
8209
- throw new Unemittable("a sequence carrying an adjacency assertion (OP_ADJ)");
8210
- }
8211
- }
8212
- const fn = fused ? fnRef(code[ip + 1]) : void 0;
9621
+ const reducer = fused ? code[ip + 1] : -1;
9622
+ const projection = reducer < 0 ? ~reducer : -1;
9623
+ const fn = fused && projection < 0 ? fnRef(reducer) : void 0;
8213
9624
  const kids = [];
8214
- for (let i = 0; i < n; i++) kids.push(link(code[base + i]));
9625
+ for (let i = 0; i < n; i++) {
9626
+ const childIp = code[base + i];
9627
+ kids.push(code[childIp] === OP_ADJ ? "" : link(childIp));
9628
+ }
8215
9629
  const sy = REC2 ? `${tmp()}sy` : "";
8216
9630
  const pub = (i) => {
8217
9631
  const s = sentRef(code[base + n + i]);
@@ -8225,7 +9639,7 @@ return v
8225
9639
  }` : `${parts.join("\n")}
8226
9640
  }`;
8227
9641
  if (n === 1) {
8228
- parts.push(fused ? `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
9642
+ parts.push(fused ? projection === 0 ? "return v0" : `return ${fn}([v0],{start:pos,end:EC.e})` : wantValues ? "return [v0]" : "return undefined");
8229
9643
  return close();
8230
9644
  }
8231
9645
  parts.push("let cur=EC.e");
@@ -8234,11 +9648,21 @@ return v
8234
9648
  const vn = `v${i}`;
8235
9649
  parts.push(`let ${vn}`);
8236
9650
  if (REC2) parts.push(pub(i));
8237
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
9651
+ const childIp = code[base + i];
9652
+ if (code[childIp] === OP_ADJ) {
9653
+ const negated = code[childIp + 1] === 1;
9654
+ const ki = code[childIp + 2];
9655
+ const kinds = ki < 0 ? "undefined" : `K[${ki}]`;
9656
+ const expected = fxRef(code[childIp + 3]);
9657
+ parts.push(
9658
+ `if(!adjacencyHolds(input,cur,ctx,${negated ? "true" : "false"},${kinds})){ctx._fe=cur;ctx._fx=${expected};return FAIL}`,
9659
+ `${vn}=null`
9660
+ );
9661
+ } else parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
8238
9662
  names.push(vn);
8239
9663
  }
8240
9664
  parts.push("EC.e=cur");
8241
- parts.push(fused ? `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
9665
+ parts.push(fused ? projection >= 0 ? `return ${names[projection]}` : `return ${fn}([${names.join(",")}],{start:pos,end:cur})` : wantValues ? `return [${names.join(",")}]` : "return undefined");
8242
9666
  return close();
8243
9667
  }
8244
9668
  case OP_CHOICE: {
@@ -8248,11 +9672,6 @@ return v
8248
9672
  const base = ip + 4;
8249
9673
  const arms = [];
8250
9674
  for (let i = 0; i < n; i++) arms.push(link(code[base + i]));
8251
- const axi = armExpected.push(
8252
- Array.from({ length: n }, (_, i) => t.fx[code[base + n + i]])
8253
- ) - 1;
8254
- armExpectedPlan.push(Array.from({ length: n }, (_, i) => code[base + n + i]));
8255
- const afx = hoist("afx", `AFX[${axi}]`);
8256
9675
  if (table.exclusive) {
8257
9676
  const di = code[ip + 1];
8258
9677
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -8279,38 +9698,43 @@ ctx._fe=pos;ctx._fx=${choiceFx}
8279
9698
  return FAIL
8280
9699
  }`;
8281
9700
  }
8282
- const ci = classes.push(Array.from({ length: n }, (_, i) => table.armCls[i] ?? null)) - 1;
8283
- classPlan.push(Array.from({ length: n }, (_, i) => prog.disp[code[ip + 1]][i] ?? -1));
8284
- const gates = classes[ci];
8285
- const gRef = hoist("g", `CLS[${ci}]`);
8286
- const maskable = n <= 32;
8287
- let maskName = "";
8288
- if (maskable) {
8289
- maskName = hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`);
8290
- maskPlan.push(ci);
8291
- }
8292
- const p = tmp();
8293
- const maskArms = arms.map((a, i) => `
8294
- if((bits&${1 << i})!==0){
9701
+ {
9702
+ const di = code[ip + 1];
9703
+ const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
9704
+ const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
9705
+ const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
9706
+ const maskable = n <= 32;
9707
+ const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
9708
+ if (maskable) maskPlan.push(~di);
9709
+ const p = tmp();
9710
+ const catchName = maskable ? `_cx${uid++}_` : "";
9711
+ if (maskable) {
9712
+ const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
9713
+ choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
9714
+ ${catchCases}
9715
+ }return acc}`);
9716
+ }
9717
+ const maskArms = maskable ? arms.map((arm, i) => {
9718
+ return `if((bits&${1 << i})!==0){
8295
9719
  ctx._fc=false
8296
- {const v=${a}(input,pos,ctx)
9720
+ {const v=${arm}(input,pos,ctx)
8297
9721
  if(v!==FAIL)return v}
8298
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9722
+ acc=${catchName}(${i},prev,acc)
8299
9723
  prev=${i + 1}
8300
9724
  acc=_accSet(ctx._fx,acc)
8301
9725
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8302
9726
  ${emitRollback(p, L.buf, sinks)}
8303
- }`).join("");
8304
- const generalArms = arms.map((a, i) => `
8305
- if(${gRef}[${i}]===null||classHas(${gRef}[${i}],c)){
9727
+ }`;
9728
+ }).join("\n") : "";
9729
+ const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
8306
9730
  ctx._fc=false
8307
- {const v=${a}(input,pos,ctx)
9731
+ {const v=${arm}(input,pos,ctx)
8308
9732
  if(v!==FAIL)return v}
8309
9733
  acc=_accSet(ctx._fx,acc)
8310
9734
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8311
9735
  ${emitRollback(p, L.buf, sinks)}
8312
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
8313
- return `${head}
9736
+ }else acc=_accSet(${expected[i]},acc)`).join("\n");
9737
+ return `${head}
8314
9738
  const c=lead(input,pos)
8315
9739
  ${emitMark(p, L.buf, sinks)}
8316
9740
  let acc
@@ -8318,14 +9742,16 @@ ${maskable ? `if(c<128){
8318
9742
  const bits=${maskName}[c<0?128:c]
8319
9743
  let prev=0
8320
9744
  ${maskArms}
8321
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9745
+ acc=${catchName}(${n},prev,acc)
8322
9746
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
8323
9747
  return FAIL
8324
9748
  }
8325
- ` : ""}${generalArms}
9749
+ ` : ""}
9750
+ ${generalArms}
8326
9751
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
8327
9752
  return FAIL
8328
9753
  }`;
9754
+ }
8329
9755
  }
8330
9756
  case OP_DISPATCH: {
8331
9757
  const di = code[ip + 2];
@@ -8351,8 +9777,16 @@ return FAIL
8351
9777
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
8352
9778
  case 4:
8353
9779
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
8354
- default:
9780
+ default: {
9781
+ if (!m[2].includes("g") && !m[2].includes("y")) {
9782
+ try {
9783
+ new RegExp(m[1], m[2]);
9784
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
9785
+ } catch {
9786
+ }
9787
+ }
8355
9788
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
9789
+ }
8356
9790
  }
8357
9791
  };
8358
9792
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -8410,6 +9844,15 @@ return [key,v]
8410
9844
  const reportItem = (flags & 4) !== 0;
8411
9845
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
8412
9846
  const collect = op === OP_REP;
9847
+ let itemCls;
9848
+ if (!REC2) {
9849
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
9850
+ if (itemClassIndex >= 0) {
9851
+ const ci = classes.push([t.cc[itemClassIndex]]) - 1;
9852
+ classPlan.push([itemClassIndex]);
9853
+ itemCls = hoist("ri", `CLS[${ci}][0]`);
9854
+ }
9855
+ }
8413
9856
  const skipBeforeFirst = sepIp < 0 && min === 0;
8414
9857
  const p = tmp();
8415
9858
  const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -8417,7 +9860,6 @@ return [key,v]
8417
9860
  const skip = skipFor(L);
8418
9861
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
8419
9862
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
8420
- const needMark = L.buf ? "true" : "needMark";
8421
9863
  const pfd = sinks.fd ? `${p}fd` : "0";
8422
9864
  const per = sinks.er ? `${p}er` : "undefined";
8423
9865
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -8462,11 +9904,13 @@ continue
8462
9904
  return `${head}
8463
9905
  const out=${collect ? "[]" : "undefined"}
8464
9906
  ${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC2 ? `const ${my}=ctx._sync
8465
- ` : ""}let cur=pos
9907
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
9908
+ `}let cur=pos
8466
9909
  let count=0
8467
9910
  for(;;){
8468
9911
  ${max >= 0 ? `if(count>=${max})break
8469
9912
  ` : ""}${sep !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
9913
+ ` : ""}${itemCls !== void 0 && sep === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}&&!classHas(${itemCls},lead(input,cur)))break
8470
9914
  ` : ""}let ${p}raw=0,${p}tl=0,${p}lv=0,${p}lg=0,${p}rt=0${sinks.fd ? `,${p}fd=0` : ""}${sinks.er ? `,${p}er=0` : ""}
8471
9915
  ${markBody}
8472
9916
  let itemStart=cur
@@ -8491,7 +9935,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
8491
9935
  ${rb}
8492
9936
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
8493
9937
  }
8494
- ctx._fc=false
9938
+ ${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&!classHas(${itemCls},lead(input,itemStart))){
9939
+ ${rb}
9940
+ ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
9941
+ }
9942
+ `}ctx._fc=false
8495
9943
  const v=${child}(input,itemStart,ctx)
8496
9944
  if(v===FAIL){
8497
9945
  ${REC2 ? `if(ctx._fc===true){
@@ -8520,6 +9968,26 @@ return out
8520
9968
  case OP_NODE:
8521
9969
  case OP_NODE_TRACK: {
8522
9970
  const flags = code[ip + 3];
9971
+ const scalarChild = scalarTerminalNodeChild(code, ip);
9972
+ if (scalarChild >= 0 && scalarSpecs.has(code[scalarChild + 1])) {
9973
+ const recognize = recognizerRef(code[scalarChild + 1]);
9974
+ const spec = code[scalarChild] === OP_RX ? null : k[code[scalarChild + 1]];
9975
+ const value2 = spec === null ? "input.slice(pos,end)" : q(spec);
9976
+ const xf = fxRef(code[scalarChild + 2]);
9977
+ const build2 = fnRef(code[ip + 1]);
9978
+ return `${head}
9979
+ const end=${recognize}(input,pos)
9980
+ if(end<0){ctx._fe=pos;ctx._fx=${xf};return FAIL}
9981
+ const value=${value2}
9982
+ const leaf={_tag:'leaf',value,span:{start:pos,end}}
9983
+ const kids=[leaf],rawKids=[leaf],span={start:pos,end}
9984
+ EC.e=end
9985
+ const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
9986
+ ${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
9987
+ EC.e=end
9988
+ return nd
9989
+ }`;
9990
+ }
8523
9991
  const child = link(code[ip + 2]);
8524
9992
  const proj = code[ip + 4];
8525
9993
  const buildIdx = code[ip + 1];
@@ -8534,6 +10002,51 @@ return out
8534
10002
  const unwrap = (flags & 64) !== 0;
8535
10003
  const trailingTrivia = (flags & 128) !== 0;
8536
10004
  const build = buildIdx >= 0 ? fnRef(buildIdx) : void 0;
10005
+ if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
10006
+ const fields = flags === 18;
10007
+ const collapseChildren = flags === 34;
10008
+ const publish = `if(sBuf!==undefined){
10009
+ if(sBuf.rawOnly!==true){
10010
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
10011
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
10012
+ else sBuf.single=nd
10013
+ }
10014
+ const rawNd=rawEntry(nd,input,pos,end)
10015
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
10016
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
10017
+ else sBuf.rawSingle=rawNd
10018
+ }else if(sCh!==undefined){
10019
+ sCh.push(nd)
10020
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
10021
+ }`;
10022
+ return `${head}
10023
+ const sCh=ctx._cstChildren,sLv=ctx._cstLeaves,sRaw=ctx._cstRawChildren,sTl=ctx._cstTriviaLog
10024
+ const sCap=ctx.captureTrivia,sBuf=ctx._cstBuf,sFields=ctx._fields
10025
+ const flat=[]
10026
+ ctx._cstBuf=undefined
10027
+ ctx._cstChildren=flat
10028
+ ctx._cstLeaves=flat
10029
+ ctx._cstRawChildren=undefined
10030
+ ctx._cstTriviaLog=undefined
10031
+ ctx.captureTrivia=false
10032
+ ctx._fields=${fields ? "[]" : "undefined"}
10033
+ const v=${child}(input,pos,ctx)
10034
+ const captured=_capturedFlatChildren(flat)
10035
+ ${fields ? "const fieldMap=buildFieldMap(ctx._fields)\n" : ""}ctx._fields=sFields
10036
+ ctx._cstBuf=sBuf
10037
+ ctx._cstChildren=sCh
10038
+ ctx._cstLeaves=sLv
10039
+ ctx._cstRawChildren=sRaw
10040
+ ctx._cstTriviaLog=sTl
10041
+ ctx.captureTrivia=sCap
10042
+ if(v===FAIL)return FAIL
10043
+ const end=EC.e
10044
+ ${collapseChildren ? `const nd=captured.length===1?captured[0]:${build}(captured,undefined,{start:pos,end},EMPTY_CH,EMPTY_TL,undefined)` : `const nd=${build}(captured,${fields ? "fieldMap" : "undefined"},{start:pos,end},EMPTY_CH,EMPTY_TL,undefined)`}
10045
+ ${publish}
10046
+ EC.e=end
10047
+ return nd
10048
+ }`;
10049
+ }
8537
10050
  const structural = build === void 0 && proj < 0;
8538
10051
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
8539
10052
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -8619,6 +10132,7 @@ return nd
8619
10132
  const source = `${RUNTIME_PRELUDE}
8620
10133
  ${prelude.join("\n")}
8621
10134
  ${skipDefs.join("\n")}
10135
+ ${choiceDefs.join("\n")}
8622
10136
  ${bodies.join("\n")}
8623
10137
  function _begin(ctx){
8624
10138
  const host=ctx.build
@@ -8859,7 +10373,7 @@ function reachableIps(prog) {
8859
10373
 
8860
10374
  // src/table/stamp.ts
8861
10375
  var EMPTY_FX = [];
8862
- function committed(c) {
10376
+ function committed2(c) {
8863
10377
  return c._fc === true;
8864
10378
  }
8865
10379
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
@@ -8909,7 +10423,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
8909
10423
  const fe = ctx._fe;
8910
10424
  const at = fe === void 0 || fe < 0 ? pos : fe;
8911
10425
  const fspan = lines ? spanLines(ctx, at, at) : { start: at, end: at };
8912
- return committed(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
10426
+ return committed2(ctx) ? { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan, committed: true } : { ok: false, expected: ctx._fx ?? EMPTY_FX, span: fspan };
8913
10427
  }
8914
10428
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
8915
10429
  };
@@ -8955,11 +10469,15 @@ function linkMatcher(m) {
8955
10469
  return (key) => asciiFoldKey(key).startsWith(value);
8956
10470
  case 4:
8957
10471
  return (key) => asciiFoldKey(key).endsWith(value);
8958
- // A fresh RegExp per test, as `matchesDispatchMatcher` builds — a cached one
8959
- // would carry `lastIndex` across parses whenever the author's pattern was
8960
- // sticky or global.
8961
10472
  default: {
8962
10473
  const flags = m[2];
10474
+ if (!flags.includes("g") && !flags.includes("y")) {
10475
+ try {
10476
+ const pattern = new RegExp(value, flags);
10477
+ return (key) => pattern.test(key);
10478
+ } catch {
10479
+ }
10480
+ }
8963
10481
  return (key) => new RegExp(value, flags).test(key);
8964
10482
  }
8965
10483
  }
@@ -8990,6 +10508,17 @@ function assemble(t, prog, cfg) {
8990
10508
  return made;
8991
10509
  }
8992
10510
  const EC = newEndCell();
10511
+ const scalarRecognizers = [];
10512
+ const rawScalarSpecs = /* @__PURE__ */ new Set();
10513
+ function scalarFor(child) {
10514
+ const spec = code[child + 1];
10515
+ let recognize = scalarRecognizers[spec];
10516
+ if (recognize === void 0) {
10517
+ recognize = makeScalarRecognizer(code[child], k[spec]);
10518
+ scalarRecognizers[spec] = recognize;
10519
+ }
10520
+ return recognize;
10521
+ }
8993
10522
  let SCAN = null;
8994
10523
  const memo = /* @__PURE__ */ new Map();
8995
10524
  const reached = /* @__PURE__ */ new Set();
@@ -8997,19 +10526,247 @@ function assemble(t, prog, cfg) {
8997
10526
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
8998
10527
  pushCstLeaf(ctx, lf);
8999
10528
  }
9000
- function rollbackNeeded(ctx) {
9001
- return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0 || ctx._cstRawChildren !== void 0 || ctx._cstTriviaLog !== void 0 || ctx._fields !== void 0 || ctx._errors !== void 0 || ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0;
10529
+ function plainBuildNode(child, build) {
10530
+ return (input, pos, ctx) => {
10531
+ const sCh = ctx._cstChildren;
10532
+ const sLv = ctx._cstLeaves;
10533
+ const sRaw = ctx._cstRawChildren;
10534
+ const sTl = ctx._cstTriviaLog;
10535
+ const sCap = ctx.captureTrivia;
10536
+ const sBuf = ctx._cstBuf;
10537
+ const savedFields = ctx._fields;
10538
+ const buf = {};
10539
+ ctx._cstBuf = buf;
10540
+ ctx._cstChildren = void 0;
10541
+ ctx._cstLeaves = void 0;
10542
+ ctx._cstRawChildren = void 0;
10543
+ ctx._cstTriviaLog = void 0;
10544
+ ctx.captureTrivia = false;
10545
+ ctx._fields = void 0;
10546
+ const value = child(input, pos, ctx);
10547
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10548
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10549
+ ctx._fields = savedFields;
10550
+ ctx._cstBuf = sBuf;
10551
+ ctx._cstChildren = sCh;
10552
+ ctx._cstLeaves = sLv;
10553
+ ctx._cstRawChildren = sRaw;
10554
+ ctx._cstTriviaLog = sTl;
10555
+ ctx.captureTrivia = sCap;
10556
+ if (value === FAIL) return FAIL;
10557
+ const end = EC.e;
10558
+ const span = { start: pos, end };
10559
+ const node2 = build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
10560
+ if (sBuf !== void 0 || sCh !== void 0) {
10561
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10562
+ }
10563
+ EC.e = end;
10564
+ return node2;
10565
+ };
9002
10566
  }
9003
- let MRAW = 0;
9004
- let MTL = 0;
9005
- let MLV = 0;
9006
- function markCst(ctx) {
9007
- const b = ctx._cstBuf;
9008
- if (b !== void 0) {
9009
- const raw = b.raw;
9010
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
9011
- const ch2 = b.ch;
9012
- MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
10567
+ function capturedFlatChildren(children2) {
10568
+ if (children2.length === 0) return EMPTY_CH;
10569
+ if (children2[0] !== void 0) return children2;
10570
+ let first = 1;
10571
+ while (first < children2.length && children2[first] === void 0) first++;
10572
+ return first === children2.length ? EMPTY_CH : children2.slice(first);
10573
+ }
10574
+ function childrenOnlyBuildNode(child, build) {
10575
+ return (input, pos, ctx) => {
10576
+ const sCh = ctx._cstChildren;
10577
+ const sLv = ctx._cstLeaves;
10578
+ const sRaw = ctx._cstRawChildren;
10579
+ const sTl = ctx._cstTriviaLog;
10580
+ const sCap = ctx.captureTrivia;
10581
+ const sBuf = ctx._cstBuf;
10582
+ const savedFields = ctx._fields;
10583
+ const kids = [];
10584
+ ctx._cstBuf = void 0;
10585
+ ctx._cstChildren = kids;
10586
+ ctx._cstLeaves = kids;
10587
+ ctx._cstRawChildren = void 0;
10588
+ ctx._cstTriviaLog = void 0;
10589
+ ctx.captureTrivia = false;
10590
+ ctx._fields = void 0;
10591
+ const value = child(input, pos, ctx);
10592
+ const captured = capturedFlatChildren(kids);
10593
+ ctx._fields = savedFields;
10594
+ ctx._cstBuf = sBuf;
10595
+ ctx._cstChildren = sCh;
10596
+ ctx._cstLeaves = sLv;
10597
+ ctx._cstRawChildren = sRaw;
10598
+ ctx._cstTriviaLog = sTl;
10599
+ ctx.captureTrivia = sCap;
10600
+ if (value === FAIL) return FAIL;
10601
+ const end = EC.e;
10602
+ const node2 = build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10603
+ if (sBuf !== void 0 || sCh !== void 0) {
10604
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10605
+ }
10606
+ EC.e = end;
10607
+ return node2;
10608
+ };
10609
+ }
10610
+ function childrenOnlyFieldsBuildNode(child, build) {
10611
+ return (input, pos, ctx) => {
10612
+ const sCh = ctx._cstChildren;
10613
+ const sLv = ctx._cstLeaves;
10614
+ const sRaw = ctx._cstRawChildren;
10615
+ const sTl = ctx._cstTriviaLog;
10616
+ const sCap = ctx.captureTrivia;
10617
+ const sBuf = ctx._cstBuf;
10618
+ const savedFields = ctx._fields;
10619
+ const kids = [];
10620
+ ctx._cstBuf = void 0;
10621
+ ctx._cstChildren = kids;
10622
+ ctx._cstLeaves = kids;
10623
+ ctx._cstRawChildren = void 0;
10624
+ ctx._cstTriviaLog = void 0;
10625
+ ctx.captureTrivia = false;
10626
+ ctx._fields = [];
10627
+ const value = child(input, pos, ctx);
10628
+ const captured = capturedFlatChildren(kids);
10629
+ const fieldMap = buildFieldMap(ctx._fields);
10630
+ ctx._fields = savedFields;
10631
+ ctx._cstBuf = sBuf;
10632
+ ctx._cstChildren = sCh;
10633
+ ctx._cstLeaves = sLv;
10634
+ ctx._cstRawChildren = sRaw;
10635
+ ctx._cstTriviaLog = sTl;
10636
+ ctx.captureTrivia = sCap;
10637
+ if (value === FAIL) return FAIL;
10638
+ const end = EC.e;
10639
+ const node2 = build(captured, fieldMap, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10640
+ if (sBuf !== void 0 || sCh !== void 0) {
10641
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10642
+ }
10643
+ EC.e = end;
10644
+ return node2;
10645
+ };
10646
+ }
10647
+ function collapseBuildNode(child, build) {
10648
+ return (input, pos, ctx) => {
10649
+ const sCh = ctx._cstChildren;
10650
+ const sLv = ctx._cstLeaves;
10651
+ const sRaw = ctx._cstRawChildren;
10652
+ const sTl = ctx._cstTriviaLog;
10653
+ const sCap = ctx.captureTrivia;
10654
+ const sBuf = ctx._cstBuf;
10655
+ const savedFields = ctx._fields;
10656
+ const buf = {};
10657
+ ctx._cstBuf = buf;
10658
+ ctx._cstChildren = void 0;
10659
+ ctx._cstLeaves = void 0;
10660
+ ctx._cstRawChildren = void 0;
10661
+ ctx._cstTriviaLog = void 0;
10662
+ ctx.captureTrivia = false;
10663
+ ctx._fields = void 0;
10664
+ const value = child(input, pos, ctx);
10665
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10666
+ const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
10667
+ ctx._fields = savedFields;
10668
+ ctx._cstBuf = sBuf;
10669
+ ctx._cstChildren = sCh;
10670
+ ctx._cstLeaves = sLv;
10671
+ ctx._cstRawChildren = sRaw;
10672
+ ctx._cstTriviaLog = sTl;
10673
+ ctx.captureTrivia = sCap;
10674
+ if (value === FAIL) return FAIL;
10675
+ const end = EC.e;
10676
+ const span = { start: pos, end };
10677
+ const node2 = kids.length === 1 ? kids[0] : build(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
10678
+ if (sBuf !== void 0 || sCh !== void 0) {
10679
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10680
+ }
10681
+ EC.e = end;
10682
+ return node2;
10683
+ };
10684
+ }
10685
+ function childrenOnlyCollapseBuildNode(child, build) {
10686
+ return (input, pos, ctx) => {
10687
+ const sCh = ctx._cstChildren;
10688
+ const sLv = ctx._cstLeaves;
10689
+ const sRaw = ctx._cstRawChildren;
10690
+ const sTl = ctx._cstTriviaLog;
10691
+ const sCap = ctx.captureTrivia;
10692
+ const sBuf = ctx._cstBuf;
10693
+ const savedFields = ctx._fields;
10694
+ const kids = [];
10695
+ ctx._cstBuf = void 0;
10696
+ ctx._cstChildren = kids;
10697
+ ctx._cstLeaves = kids;
10698
+ ctx._cstRawChildren = void 0;
10699
+ ctx._cstTriviaLog = void 0;
10700
+ ctx.captureTrivia = false;
10701
+ ctx._fields = void 0;
10702
+ const value = child(input, pos, ctx);
10703
+ const captured = capturedFlatChildren(kids);
10704
+ ctx._fields = savedFields;
10705
+ ctx._cstBuf = sBuf;
10706
+ ctx._cstChildren = sCh;
10707
+ ctx._cstLeaves = sLv;
10708
+ ctx._cstRawChildren = sRaw;
10709
+ ctx._cstTriviaLog = sTl;
10710
+ ctx.captureTrivia = sCap;
10711
+ if (value === FAIL) return FAIL;
10712
+ const end = EC.e;
10713
+ const node2 = captured.length === 1 ? captured[0] : build(captured, void 0, { start: pos, end }, EMPTY_CH, EMPTY_TL2, void 0);
10714
+ if (sBuf !== void 0 || sCh !== void 0) {
10715
+ pushCstChild(ctx, node2, sBuf !== void 0 || sRaw !== void 0 ? rawEntry(node2, input, pos, end) : void 0);
10716
+ }
10717
+ EC.e = end;
10718
+ return node2;
10719
+ };
10720
+ }
10721
+ function plainProjectNode(child, projection, type) {
10722
+ return (input, pos, ctx) => {
10723
+ const sCh = ctx._cstChildren;
10724
+ const sLv = ctx._cstLeaves;
10725
+ const sRaw = ctx._cstRawChildren;
10726
+ const sTl = ctx._cstTriviaLog;
10727
+ const sCap = ctx.captureTrivia;
10728
+ const sBuf = ctx._cstBuf;
10729
+ const savedFields = ctx._fields;
10730
+ const buf = {};
10731
+ ctx._cstBuf = buf;
10732
+ ctx._cstChildren = void 0;
10733
+ ctx._cstLeaves = void 0;
10734
+ ctx._cstRawChildren = void 0;
10735
+ ctx._cstTriviaLog = void 0;
10736
+ ctx.captureTrivia = false;
10737
+ ctx._fields = void 0;
10738
+ const value = child(input, pos, ctx);
10739
+ const kids = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
10740
+ ctx._fields = savedFields;
10741
+ ctx._cstBuf = sBuf;
10742
+ ctx._cstChildren = sCh;
10743
+ ctx._cstLeaves = sLv;
10744
+ ctx._cstRawChildren = sRaw;
10745
+ ctx._cstTriviaLog = sTl;
10746
+ ctx.captureTrivia = sCap;
10747
+ if (value === FAIL) return FAIL;
10748
+ const end = EC.e;
10749
+ const node2 = projectChild(kids, projection, type);
10750
+ if (sBuf !== void 0 || sCh !== void 0) {
10751
+ pushCstChild(ctx, node2, rawEntry(node2, input, pos, end));
10752
+ }
10753
+ EC.e = end;
10754
+ return node2;
10755
+ };
10756
+ }
10757
+ function rollbackNeeded(ctx) {
10758
+ return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0 || ctx._cstRawChildren !== void 0 || ctx._cstTriviaLog !== void 0 || ctx._fields !== void 0 || ctx._errors !== void 0 || ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0;
10759
+ }
10760
+ let MRAW = 0;
10761
+ let MTL = 0;
10762
+ let MLV = 0;
10763
+ function markCst(ctx) {
10764
+ const b = ctx._cstBuf;
10765
+ if (b !== void 0) {
10766
+ const raw = b.raw;
10767
+ MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
10768
+ const ch2 = b.ch;
10769
+ MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
9013
10770
  const tl = b.tl;
9014
10771
  MTL = tl !== void 0 ? tl.length : 0;
9015
10772
  return true;
@@ -9053,9 +10810,7 @@ function assemble(t, prog, cfg) {
9053
10810
  }
9054
10811
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
9055
10812
  if (needsDeferredTriviaCommit(ctx)) {
9056
- const scan = scanTrivia(input, cur, ctx);
9057
- scan.commit();
9058
- return scan.end;
10813
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
9059
10814
  }
9060
10815
  return advanceTrivia(input, cur, ctx);
9061
10816
  }
@@ -9093,7 +10848,7 @@ function assemble(t, prog, cfg) {
9093
10848
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
9094
10849
  return cur;
9095
10850
  }
9096
- function committed2(c) {
10851
+ function committed3(c) {
9097
10852
  return c._fc === true;
9098
10853
  }
9099
10854
  function accSet(ax, acc) {
@@ -9102,6 +10857,207 @@ function assemble(t, prog, cfg) {
9102
10857
  for (const s of ax) acc.push(s);
9103
10858
  return acc;
9104
10859
  }
10860
+ const NEVER_PIECE = () => FAIL;
10861
+ const NEVER_CLASS = { ascii: new Uint8Array(128), hi: [] };
10862
+ const EMPTY_EXPECTED_PREFIX = (_target, _prev, acc) => acc;
10863
+ function expectedBlock(start, e0, e1, e2, e3, prior) {
10864
+ return (target, prev, acc) => {
10865
+ if (prev < start) {
10866
+ acc = prior(start, prev, acc);
10867
+ prev = start;
10868
+ }
10869
+ if (target > start && prev < start + 1) acc = accSet(e0, acc);
10870
+ if (target > start + 1 && prev < start + 2) acc = accSet(e1, acc);
10871
+ if (target > start + 2 && prev < start + 3) acc = accSet(e2, acc);
10872
+ if (target > start + 3 && prev < start + 4) acc = accSet(e3, acc);
10873
+ return acc;
10874
+ };
10875
+ }
10876
+ function maskedChoiceBlock(start, a0, a1, a2, a3, through, next, total, choiceFx) {
10877
+ return (input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev) => {
10878
+ if ((bits & 1 << start) !== 0) {
10879
+ ctx._fc = false;
10880
+ const v = a0(input, pos, ctx);
10881
+ if (v !== FAIL) return v;
10882
+ acc = through(start, prev, acc);
10883
+ prev = start + 1;
10884
+ acc = accSet(ctx._fx, acc);
10885
+ if (committed3(ctx)) {
10886
+ if (acc !== void 0) ctx._fx = acc;
10887
+ return FAIL;
10888
+ }
10889
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10890
+ }
10891
+ if ((bits & 1 << start + 1) !== 0) {
10892
+ ctx._fc = false;
10893
+ const v = a1(input, pos, ctx);
10894
+ if (v !== FAIL) return v;
10895
+ acc = through(start + 1, prev, acc);
10896
+ prev = start + 2;
10897
+ acc = accSet(ctx._fx, acc);
10898
+ if (committed3(ctx)) {
10899
+ if (acc !== void 0) ctx._fx = acc;
10900
+ return FAIL;
10901
+ }
10902
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10903
+ }
10904
+ if ((bits & 1 << start + 2) !== 0) {
10905
+ ctx._fc = false;
10906
+ const v = a2(input, pos, ctx);
10907
+ if (v !== FAIL) return v;
10908
+ acc = through(start + 2, prev, acc);
10909
+ prev = start + 3;
10910
+ acc = accSet(ctx._fx, acc);
10911
+ if (committed3(ctx)) {
10912
+ if (acc !== void 0) ctx._fx = acc;
10913
+ return FAIL;
10914
+ }
10915
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10916
+ }
10917
+ if ((bits & 1 << start + 3) !== 0) {
10918
+ ctx._fc = false;
10919
+ const v = a3(input, pos, ctx);
10920
+ if (v !== FAIL) return v;
10921
+ acc = through(start + 3, prev, acc);
10922
+ prev = start + 4;
10923
+ acc = accSet(ctx._fx, acc);
10924
+ if (committed3(ctx)) {
10925
+ if (acc !== void 0) ctx._fx = acc;
10926
+ return FAIL;
10927
+ }
10928
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10929
+ }
10930
+ if (next !== void 0) {
10931
+ return next(input, pos, ctx, bits, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev);
10932
+ }
10933
+ acc = through(total, prev, acc);
10934
+ ctx._fe = pos;
10935
+ ctx._fx = acc ?? choiceFx;
10936
+ return FAIL;
10937
+ };
10938
+ }
10939
+ function generalChoiceBlock(start, a0, a1, a2, a3, g0, g1, g2, g3, through, next, total, choiceFx) {
10940
+ return (input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev) => {
10941
+ if (g0 === null || classHas2(g0, c)) {
10942
+ ctx._fc = false;
10943
+ const v = a0(input, pos, ctx);
10944
+ if (v !== FAIL) return v;
10945
+ acc = through(start, prev, acc);
10946
+ prev = start + 1;
10947
+ acc = accSet(ctx._fx, acc);
10948
+ if (committed3(ctx)) {
10949
+ if (acc !== void 0) ctx._fx = acc;
10950
+ return FAIL;
10951
+ }
10952
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10953
+ }
10954
+ if (g1 === null || classHas2(g1, c)) {
10955
+ ctx._fc = false;
10956
+ const v = a1(input, pos, ctx);
10957
+ if (v !== FAIL) return v;
10958
+ acc = through(start + 1, prev, acc);
10959
+ prev = start + 2;
10960
+ acc = accSet(ctx._fx, acc);
10961
+ if (committed3(ctx)) {
10962
+ if (acc !== void 0) ctx._fx = acc;
10963
+ return FAIL;
10964
+ }
10965
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10966
+ }
10967
+ if (g2 === null || classHas2(g2, c)) {
10968
+ ctx._fc = false;
10969
+ const v = a2(input, pos, ctx);
10970
+ if (v !== FAIL) return v;
10971
+ acc = through(start + 2, prev, acc);
10972
+ prev = start + 3;
10973
+ acc = accSet(ctx._fx, acc);
10974
+ if (committed3(ctx)) {
10975
+ if (acc !== void 0) ctx._fx = acc;
10976
+ return FAIL;
10977
+ }
10978
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10979
+ }
10980
+ if (g3 === null || classHas2(g3, c)) {
10981
+ ctx._fc = false;
10982
+ const v = a3(input, pos, ctx);
10983
+ if (v !== FAIL) return v;
10984
+ acc = through(start + 3, prev, acc);
10985
+ prev = start + 4;
10986
+ acc = accSet(ctx._fx, acc);
10987
+ if (committed3(ctx)) {
10988
+ if (acc !== void 0) ctx._fx = acc;
10989
+ return FAIL;
10990
+ }
10991
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10992
+ }
10993
+ if (next !== void 0) {
10994
+ return next(input, pos, ctx, c, need, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot, acc, prev);
10995
+ }
10996
+ acc = through(total, prev, acc);
10997
+ ctx._fe = pos;
10998
+ ctx._fx = acc ?? choiceFx;
10999
+ return FAIL;
11000
+ };
11001
+ }
11002
+ function exclusiveChoiceBlock(start, a0, a1, a2, a3, next) {
11003
+ return (arm, input, pos, ctx) => {
11004
+ if (arm === start) return a0(input, pos, ctx);
11005
+ if (arm === start + 1) return a1(input, pos, ctx);
11006
+ if (arm === start + 2) return a2(input, pos, ctx);
11007
+ if (arm === start + 3) return a3(input, pos, ctx);
11008
+ return next === void 0 ? FAIL : next(arm, input, pos, ctx);
11009
+ };
11010
+ }
11011
+ function dispatchMatcherBlock(m0, a0, m1, a1, m2, a2, m3, a3, next) {
11012
+ return (key) => {
11013
+ if (m0(key)) return a0;
11014
+ if (m1(key)) return a1;
11015
+ if (m2(key)) return a2;
11016
+ if (m3(key)) return a3;
11017
+ return next?.(key);
11018
+ };
11019
+ }
11020
+ function dispatchBranch(child, usesRouted) {
11021
+ if (!usesRouted) {
11022
+ return (input, _pos, selEnd, key, _selectorMark, ctx) => {
11023
+ const mark = saveTriviaMark(ctx);
11024
+ const v = child(input, selEnd, ctx);
11025
+ if (v === FAIL) {
11026
+ rollbackTrivia(ctx, mark);
11027
+ ctx._fc = true;
11028
+ return FAIL;
11029
+ }
11030
+ return [key, v];
11031
+ };
11032
+ }
11033
+ return (input, pos, selEnd, key, selectorMark, ctx) => {
11034
+ const savedRouted = ctx._routed;
11035
+ rollbackTrivia(ctx, selectorMark);
11036
+ const mark = saveTriviaMark(ctx);
11037
+ ctx._routed = { value: key, span: { start: pos, end: selEnd } };
11038
+ let v;
11039
+ try {
11040
+ v = child(input, pos, ctx);
11041
+ } finally {
11042
+ ctx._routed = savedRouted;
11043
+ }
11044
+ if (v === FAIL) {
11045
+ rollbackTrivia(ctx, mark);
11046
+ ctx._fc = true;
11047
+ return FAIL;
11048
+ }
11049
+ return [key, v];
11050
+ };
11051
+ }
11052
+ function dispatchArmBlock(start, a0, a1, a2, a3, next) {
11053
+ return (arm, input, pos, selEnd, key, selectorMark, ctx) => {
11054
+ if (arm === start) return a0(input, pos, selEnd, key, selectorMark, ctx);
11055
+ if (arm === start + 1) return a1(input, pos, selEnd, key, selectorMark, ctx);
11056
+ if (arm === start + 2) return a2(input, pos, selEnd, key, selectorMark, ctx);
11057
+ if (arm === start + 3) return a3(input, pos, selEnd, key, selectorMark, ctx);
11058
+ return next === void 0 ? FAIL : next(arm, input, pos, selEnd, key, selectorMark, ctx);
11059
+ };
11060
+ }
9105
11061
  function trackLinesInto(ctx, input, end) {
9106
11062
  const from = ctx._lineScannedTo ?? 0;
9107
11063
  if (end <= from) return;
@@ -9137,6 +11093,21 @@ function assemble(t, prog, cfg) {
9137
11093
  const s = k[code[ip + 1]];
9138
11094
  const len = s.length;
9139
11095
  const xf = fx[code[ip + 2]];
11096
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
11097
+ if (shared !== void 0) {
11098
+ return (input, pos, ctx) => {
11099
+ const e = shared(input, pos);
11100
+ if (e >= 0) {
11101
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, s, pos, e);
11102
+ EC.e = e;
11103
+ return s;
11104
+ }
11105
+ ctx._fe = pos;
11106
+ ctx._fx = xf;
11107
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
11108
+ return FAIL;
11109
+ };
11110
+ }
9140
11111
  if (len === 1) {
9141
11112
  const c0 = s.charCodeAt(0);
9142
11113
  return (input, pos, ctx) => {
@@ -9264,6 +11235,22 @@ function assemble(t, prog, cfg) {
9264
11235
  case OP_RX: {
9265
11236
  const re = k[code[ip + 1]];
9266
11237
  const xf = fx[code[ip + 2]];
11238
+ const shared = rawScalarSpecs.has(code[ip + 1]) ? scalarFor(ip) : void 0;
11239
+ if (shared !== void 0) {
11240
+ return (input, pos, ctx) => {
11241
+ const e = shared(input, pos);
11242
+ if (e >= 0) {
11243
+ const v = input.slice(pos, e);
11244
+ if (cstCaptureActive(ctx)) pushLeaf(ctx, v, pos, e);
11245
+ EC.e = e;
11246
+ return v;
11247
+ }
11248
+ ctx._fe = pos;
11249
+ ctx._fx = xf;
11250
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
11251
+ return FAIL;
11252
+ };
11253
+ }
9267
11254
  return (input, pos, ctx) => {
9268
11255
  re.lastIndex = pos;
9269
11256
  if (re.test(input)) {
@@ -9373,7 +11360,7 @@ function assemble(t, prog, cfg) {
9373
11360
  const child = link(code[ip + 2]);
9374
11361
  if (cfg.tolerant || cfg.probe) return child;
9375
11362
  return (input, pos, ctx) => {
9376
- if (!classHas(cls, lead(input, pos))) {
11363
+ if (!classHas2(cls, lead(input, pos))) {
9377
11364
  ctx._fe = pos;
9378
11365
  ctx._fx = xf;
9379
11366
  return FAIL;
@@ -9572,13 +11559,28 @@ function assemble(t, prog, cfg) {
9572
11559
  const v = child(input, pos, ctx);
9573
11560
  if (v !== FAIL) return v;
9574
11561
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9575
- if (committed2(ctx)) return FAIL;
11562
+ if (committed3(ctx)) return FAIL;
9576
11563
  ctx._fe = pos;
9577
11564
  return FAIL;
9578
11565
  };
9579
11566
  }
9580
11567
  /* ── zero-width ──────────────────────────────────────────────────────── */
9581
11568
  case OP_NOT: {
11569
+ const scalarChild = scalarTerminalNotChild(code, ip);
11570
+ if (scalarChild >= 0) {
11571
+ const recognize = scalarFor(scalarChild);
11572
+ const xf2 = fx[code[ip + 2]];
11573
+ return (input, pos, ctx) => {
11574
+ if (recognize(input, pos) < 0) {
11575
+ EC.e = pos;
11576
+ return null;
11577
+ }
11578
+ ctx._fe = pos;
11579
+ ctx._fx = xf2;
11580
+ EC.e = pos;
11581
+ return FAIL;
11582
+ };
11583
+ }
9582
11584
  const child = link(code[ip + 1]);
9583
11585
  const xf = fx[code[ip + 2]];
9584
11586
  return (input, pos, ctx) => {
@@ -9638,7 +11640,7 @@ function assemble(t, prog, cfg) {
9638
11640
  ctx._fc = false;
9639
11641
  const v = child(input, pos, ctx);
9640
11642
  if (v === FAIL) {
9641
- if (committed2(ctx)) return FAIL;
11643
+ if (committed3(ctx)) return FAIL;
9642
11644
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9643
11645
  EC.e = pos;
9644
11646
  return null;
@@ -9689,6 +11691,92 @@ function assemble(t, prog, cfg) {
9689
11691
  return value;
9690
11692
  };
9691
11693
  }
11694
+ case OP_LEX_BODY: {
11695
+ const recognize = t.lex[code[ip + 1]];
11696
+ const expected = fx[code[ip + 2]];
11697
+ return (input, pos, ctx) => {
11698
+ const recognized = recognize(input, pos);
11699
+ if (recognized < 0) {
11700
+ ctx._fe = pos;
11701
+ ctx._fx = expected;
11702
+ if (ctx._probe !== void 0) failAt(ctx, expected, pos);
11703
+ return FAIL;
11704
+ }
11705
+ const lineFlags = code[ip + 4];
11706
+ const hasSuffix = (lineFlags & 4) !== 0;
11707
+ const suffixMatched = hasSuffix && recognized % 2 === 1;
11708
+ const end = (recognized - (suffixMatched ? 1 : 0)) / 2;
11709
+ if ((lineFlags & 1) !== 0) {
11710
+ trackLinesInto(ctx, input, suffixMatched ? end - 1 : end);
11711
+ }
11712
+ if (hasSuffix) ctx._fc = false;
11713
+ if (hasSuffix && suffixMatched && (lineFlags & 2) !== 0) {
11714
+ trackLinesInto(ctx, input, end);
11715
+ }
11716
+ if (hasSuffix && !suffixMatched) {
11717
+ const suffixExpected = fx[code[ip + 3]];
11718
+ ctx._fe = end;
11719
+ ctx._fx = suffixExpected;
11720
+ if (ctx._probe !== void 0) failAt(ctx, suffixExpected, end);
11721
+ }
11722
+ const value = input.slice(pos, end);
11723
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11724
+ EC.e = end;
11725
+ return value;
11726
+ };
11727
+ }
11728
+ case OP_LEX_PROGRAM: {
11729
+ const run3 = t.lexPrograms[code[ip + 1]];
11730
+ const scanId = run3.scan;
11731
+ if (scanId !== void 0) {
11732
+ return (input, pos, ctx) => {
11733
+ const sTrivia = ctx.trivia, sKinds = ctx.triviaKindLabels;
11734
+ const sBuf = ctx._cstBuf, sChildren = ctx._cstChildren, sLeaves = ctx._cstLeaves;
11735
+ const sRaw = ctx._cstRawChildren, sTl = ctx._cstTriviaLog;
11736
+ const sOuterTl = ctx._triviaLog, sRootTl = ctx._rootTriviaLog;
11737
+ const wasCapturing = cstCaptureActive(ctx);
11738
+ const sScan = SCAN;
11739
+ SCAN = null;
11740
+ ctx.trivia = void 0;
11741
+ ctx.triviaKindLabels = void 0;
11742
+ ctx._cstBuf = void 0;
11743
+ ctx._cstChildren = void 0;
11744
+ ctx._cstLeaves = void 0;
11745
+ ctx._cstRawChildren = void 0;
11746
+ ctx._cstTriviaLog = void 0;
11747
+ ctx._triviaLog = void 0;
11748
+ ctx._rootTriviaLog = void 0;
11749
+ let end;
11750
+ try {
11751
+ end = run3(input, pos, ctx, scans[scanId]);
11752
+ } finally {
11753
+ SCAN = sScan;
11754
+ ctx.trivia = sTrivia;
11755
+ ctx.triviaKindLabels = sKinds;
11756
+ ctx._cstBuf = sBuf;
11757
+ ctx._cstChildren = sChildren;
11758
+ ctx._cstLeaves = sLeaves;
11759
+ ctx._cstRawChildren = sRaw;
11760
+ ctx._cstTriviaLog = sTl;
11761
+ ctx._triviaLog = sOuterTl;
11762
+ ctx._rootTriviaLog = sRootTl;
11763
+ }
11764
+ if (end < 0) return FAIL;
11765
+ const value = input.slice(pos, end);
11766
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11767
+ EC.e = end;
11768
+ return value;
11769
+ };
11770
+ }
11771
+ return (input, pos, ctx) => {
11772
+ const end = run3(input, pos, ctx);
11773
+ if (end < 0) return FAIL;
11774
+ const value = input.slice(pos, end);
11775
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: { start: pos, end } });
11776
+ EC.e = end;
11777
+ return value;
11778
+ };
11779
+ }
9692
11780
  case OP_LEAF: {
9693
11781
  const fn = fns[code[ip + 1]];
9694
11782
  const child = link(code[ip + 2]);
@@ -9729,38 +11817,73 @@ function assemble(t, prog, cfg) {
9729
11817
  const fused = op === OP_SEQX;
9730
11818
  const base = fused ? ip + 3 : ip + 2;
9731
11819
  const n = code[fused ? ip + 2 : ip + 1];
9732
- const kids = new Array(n);
9733
- for (let i = 0; i < n; i++) kids[i] = link(code[base + i]);
9734
11820
  const wantValues = op !== OP_SEQV;
9735
- const fn = fused ? fns[code[ip + 1]] : void 0;
9736
- const runTerms = (input, pos, ctx, values) => {
9737
- const v0 = kids[0](input, pos, ctx);
9738
- if (v0 === FAIL) return -1;
9739
- if (values !== void 0) values.push(v0);
9740
- let cur = EC.e;
9741
- for (let i = 1; i < n; i++) {
9742
- cur = nextTerm(kids[i], input, cur, ctx);
11821
+ const reducer = fused ? code[ip + 1] : -1;
11822
+ const projection = reducer < 0 ? ~reducer : -1;
11823
+ const fn = fused && projection < 0 ? fns[reducer] : void 0;
11824
+ const runnerBlock = (count, r0, r1, r2, r3, next) => {
11825
+ if (count === 1) return (input, cur, ctx, values, inherited) => {
11826
+ cur = r0(input, cur, ctx, inherited);
9743
11827
  if (cur < 0) return -1;
9744
11828
  if (values !== void 0) values.push(TERMV);
9745
- }
9746
- return cur;
11829
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11830
+ };
11831
+ if (count === 2) return (input, cur, ctx, values, inherited) => {
11832
+ cur = r0(input, cur, ctx, inherited);
11833
+ if (cur < 0) return -1;
11834
+ if (values !== void 0) values.push(TERMV);
11835
+ cur = r1(input, cur, ctx, inherited);
11836
+ if (cur < 0) return -1;
11837
+ if (values !== void 0) values.push(TERMV);
11838
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11839
+ };
11840
+ if (count === 3) return (input, cur, ctx, values, inherited) => {
11841
+ cur = r0(input, cur, ctx, inherited);
11842
+ if (cur < 0) return -1;
11843
+ if (values !== void 0) values.push(TERMV);
11844
+ cur = r1(input, cur, ctx, inherited);
11845
+ if (cur < 0) return -1;
11846
+ if (values !== void 0) values.push(TERMV);
11847
+ cur = r2(input, cur, ctx, inherited);
11848
+ if (cur < 0) return -1;
11849
+ if (values !== void 0) values.push(TERMV);
11850
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11851
+ };
11852
+ return (input, cur, ctx, values, inherited) => {
11853
+ cur = r0(input, cur, ctx, inherited);
11854
+ if (cur < 0) return -1;
11855
+ if (values !== void 0) values.push(TERMV);
11856
+ cur = r1(input, cur, ctx, inherited);
11857
+ if (cur < 0) return -1;
11858
+ if (values !== void 0) values.push(TERMV);
11859
+ cur = r2(input, cur, ctx, inherited);
11860
+ if (cur < 0) return -1;
11861
+ if (values !== void 0) values.push(TERMV);
11862
+ cur = r3(input, cur, ctx, inherited);
11863
+ if (cur < 0) return -1;
11864
+ if (values !== void 0) values.push(TERMV);
11865
+ return next === void 0 ? cur : next(input, cur, ctx, values, inherited);
11866
+ };
9747
11867
  };
9748
11868
  if (REC2) {
9749
- const syncs = new Array(n);
9750
- for (let i = 0; i < n; i++) syncs[i] = sentinelFor(code[base + n + i]);
9751
- const runners = new Array(n);
9752
- for (let i = 1; i < n; i++) {
11869
+ const first2 = link(code[base]);
11870
+ const firstSync = sentinelFor(code[base + n]);
11871
+ const runnerAt = (i) => {
11872
+ const sync = sentinelFor(code[base + n + i]);
9753
11873
  const kidIp = code[base + i];
9754
11874
  if (code[kidIp] !== OP_ADJ) {
9755
- const kid = kids[i];
9756
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9757
- continue;
11875
+ const kid = link(kidIp);
11876
+ return (input, cur, ctx, inherited) => {
11877
+ ctx._sync = sync ?? inherited;
11878
+ return nextTerm(kid, input, cur, ctx);
11879
+ };
9758
11880
  }
9759
11881
  const negated = code[kidIp + 1] === 1;
9760
11882
  const ki = code[kidIp + 2];
9761
11883
  const kinds = ki < 0 ? void 0 : k[ki];
9762
11884
  const xf = fx[code[kidIp + 3]];
9763
- runners[i] = (input, cur, ctx) => {
11885
+ return (input, cur, ctx, inherited) => {
11886
+ ctx._sync = sync ?? inherited;
9764
11887
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9765
11888
  ctx._fe = cur;
9766
11889
  ctx._fx = xf;
@@ -9769,25 +11892,34 @@ function assemble(t, prog, cfg) {
9769
11892
  TERMV = null;
9770
11893
  return cur;
9771
11894
  };
9772
- }
11895
+ };
11896
+ const bindRunners = (start) => {
11897
+ const count = Math.min(4, n - start);
11898
+ const at = (offset) => runnerAt(start + offset);
11899
+ const never = () => -1;
11900
+ return runnerBlock(
11901
+ count,
11902
+ at(0),
11903
+ count > 1 ? at(1) : never,
11904
+ count > 2 ? at(2) : never,
11905
+ count > 3 ? at(3) : never,
11906
+ start + count < n ? bindRunners(start + count) : void 0
11907
+ );
11908
+ };
11909
+ const tail2 = n > 1 ? bindRunners(1) : void 0;
9773
11910
  const runSyncTerms = (input, pos, ctx, values) => {
9774
11911
  const inherited = ctx._sync;
9775
- ctx._sync = syncs[0] ?? inherited;
9776
- const v0 = kids[0](input, pos, ctx);
11912
+ ctx._sync = firstSync ?? inherited;
11913
+ const v0 = first2(input, pos, ctx);
9777
11914
  if (v0 === FAIL) {
9778
11915
  ctx._sync = inherited;
9779
11916
  return -1;
9780
11917
  }
9781
11918
  if (values !== void 0) values.push(v0);
9782
- let cur = EC.e;
9783
- for (let i = 1; i < n; i++) {
9784
- ctx._sync = syncs[i] ?? inherited;
9785
- cur = runners[i](input, cur, ctx);
9786
- if (cur < 0) {
9787
- ctx._sync = inherited;
9788
- return -1;
9789
- }
9790
- if (values !== void 0) values.push(TERMV);
11919
+ const cur = tail2 === void 0 ? EC.e : tail2(input, EC.e, ctx, values, inherited);
11920
+ if (cur < 0) {
11921
+ ctx._sync = inherited;
11922
+ return -1;
9791
11923
  }
9792
11924
  ctx._sync = inherited;
9793
11925
  return cur;
@@ -9798,7 +11930,7 @@ function assemble(t, prog, cfg) {
9798
11930
  const cur = runSyncTerms(input, pos, ctx, values);
9799
11931
  if (cur < 0) return FAIL;
9800
11932
  EC.e = cur;
9801
- return fn(values, { start: pos, end: cur });
11933
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9802
11934
  };
9803
11935
  }
9804
11936
  if (wantValues) {
@@ -9823,19 +11955,18 @@ function assemble(t, prog, cfg) {
9823
11955
  break;
9824
11956
  }
9825
11957
  if (hasAdj) {
9826
- const runners = new Array(n);
9827
- for (let i = 1; i < n; i++) {
11958
+ const first2 = link(code[base]);
11959
+ const runnerAt = (i) => {
9828
11960
  const kidIp = code[base + i];
9829
11961
  if (code[kidIp] !== OP_ADJ) {
9830
- const kid = kids[i];
9831
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9832
- continue;
11962
+ const kid = link(kidIp);
11963
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9833
11964
  }
9834
11965
  const negated = code[kidIp + 1] === 1;
9835
11966
  const ki = code[kidIp + 2];
9836
11967
  const kinds = ki < 0 ? void 0 : k[ki];
9837
11968
  const xf = fx[code[kidIp + 3]];
9838
- runners[i] = (input, cur, ctx) => {
11969
+ return (input, cur, ctx) => {
9839
11970
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9840
11971
  ctx._fe = cur;
9841
11972
  ctx._fx = xf;
@@ -9844,18 +11975,26 @@ function assemble(t, prog, cfg) {
9844
11975
  TERMV = null;
9845
11976
  return cur;
9846
11977
  };
9847
- }
11978
+ };
11979
+ const bindRunners = (start) => {
11980
+ const count = Math.min(4, n - start);
11981
+ const at = (offset) => runnerAt(start + offset);
11982
+ const never = () => -1;
11983
+ return runnerBlock(
11984
+ count,
11985
+ at(0),
11986
+ count > 1 ? at(1) : never,
11987
+ count > 2 ? at(2) : never,
11988
+ count > 3 ? at(3) : never,
11989
+ start + count < n ? bindRunners(start + count) : void 0
11990
+ );
11991
+ };
11992
+ const tail2 = bindRunners(1);
9848
11993
  const runAdjTerms = (input, pos, ctx, values) => {
9849
- const v0 = kids[0](input, pos, ctx);
11994
+ const v0 = first2(input, pos, ctx);
9850
11995
  if (v0 === FAIL) return -1;
9851
11996
  if (values !== void 0) values.push(v0);
9852
- let cur = EC.e;
9853
- for (let i = 1; i < n; i++) {
9854
- cur = runners[i](input, cur, ctx);
9855
- if (cur < 0) return -1;
9856
- if (values !== void 0) values.push(TERMV);
9857
- }
9858
- return cur;
11997
+ return tail2(input, EC.e, ctx, values);
9859
11998
  };
9860
11999
  if (fused) {
9861
12000
  return (input, pos, ctx) => {
@@ -9863,7 +12002,7 @@ function assemble(t, prog, cfg) {
9863
12002
  const cur = runAdjTerms(input, pos, ctx, values);
9864
12003
  if (cur < 0) return FAIL;
9865
12004
  EC.e = cur;
9866
- return fn(values, { start: pos, end: cur });
12005
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9867
12006
  };
9868
12007
  }
9869
12008
  if (wantValues) {
@@ -9883,12 +12022,12 @@ function assemble(t, prog, cfg) {
9883
12022
  };
9884
12023
  }
9885
12024
  if (n === 1) {
9886
- const k0 = kids[0];
12025
+ const k0 = link(code[base]);
9887
12026
  if (fused) {
9888
12027
  return (input, pos, ctx) => {
9889
12028
  const v = k0(input, pos, ctx);
9890
12029
  if (v === FAIL) return FAIL;
9891
- return fn([v], { start: pos, end: EC.e });
12030
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
9892
12031
  };
9893
12032
  }
9894
12033
  if (wantValues) {
@@ -9905,7 +12044,7 @@ function assemble(t, prog, cfg) {
9905
12044
  };
9906
12045
  }
9907
12046
  if (n === 2) {
9908
- const k0 = kids[0], k1 = kids[1];
12047
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
9909
12048
  if (fused) {
9910
12049
  return (input, pos, ctx) => {
9911
12050
  const v0 = k0(input, pos, ctx);
@@ -9913,7 +12052,7 @@ function assemble(t, prog, cfg) {
9913
12052
  const cur = nextTerm(k1, input, EC.e, ctx);
9914
12053
  if (cur < 0) return FAIL;
9915
12054
  EC.e = cur;
9916
- return fn([v0, TERMV], { start: pos, end: cur });
12055
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
9917
12056
  };
9918
12057
  }
9919
12058
  if (wantValues) {
@@ -9936,7 +12075,7 @@ function assemble(t, prog, cfg) {
9936
12075
  };
9937
12076
  }
9938
12077
  if (n === 3) {
9939
- const k0 = kids[0], k1 = kids[1], k2 = kids[2];
12078
+ const k0 = link(code[base]), k1 = link(code[base + 1]), k2 = link(code[base + 2]);
9940
12079
  if (fused) {
9941
12080
  return (input, pos, ctx) => {
9942
12081
  const v0 = k0(input, pos, ctx);
@@ -9947,7 +12086,7 @@ function assemble(t, prog, cfg) {
9947
12086
  cur = nextTerm(k2, input, cur, ctx);
9948
12087
  if (cur < 0) return FAIL;
9949
12088
  EC.e = cur;
9950
- return fn([v0, v1, TERMV], { start: pos, end: cur });
12089
+ return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
9951
12090
  };
9952
12091
  }
9953
12092
  if (wantValues) {
@@ -9974,26 +12113,90 @@ function assemble(t, prog, cfg) {
9974
12113
  return void 0;
9975
12114
  };
9976
12115
  }
12116
+ const block = (count, k0, k1, k2, k3, next) => {
12117
+ if (count === 1) return (input, cur, ctx, values) => {
12118
+ cur = nextTerm(k0, input, cur, ctx);
12119
+ if (cur < 0) return -1;
12120
+ if (values !== void 0) values.push(TERMV);
12121
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12122
+ };
12123
+ if (count === 2) return (input, cur, ctx, values) => {
12124
+ cur = nextTerm(k0, input, cur, ctx);
12125
+ if (cur < 0) return -1;
12126
+ if (values !== void 0) values.push(TERMV);
12127
+ cur = nextTerm(k1, input, cur, ctx);
12128
+ if (cur < 0) return -1;
12129
+ if (values !== void 0) values.push(TERMV);
12130
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12131
+ };
12132
+ if (count === 3) return (input, cur, ctx, values) => {
12133
+ cur = nextTerm(k0, input, cur, ctx);
12134
+ if (cur < 0) return -1;
12135
+ if (values !== void 0) values.push(TERMV);
12136
+ cur = nextTerm(k1, input, cur, ctx);
12137
+ if (cur < 0) return -1;
12138
+ if (values !== void 0) values.push(TERMV);
12139
+ cur = nextTerm(k2, input, cur, ctx);
12140
+ if (cur < 0) return -1;
12141
+ if (values !== void 0) values.push(TERMV);
12142
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12143
+ };
12144
+ return (input, cur, ctx, values) => {
12145
+ cur = nextTerm(k0, input, cur, ctx);
12146
+ if (cur < 0) return -1;
12147
+ if (values !== void 0) values.push(TERMV);
12148
+ cur = nextTerm(k1, input, cur, ctx);
12149
+ if (cur < 0) return -1;
12150
+ if (values !== void 0) values.push(TERMV);
12151
+ cur = nextTerm(k2, input, cur, ctx);
12152
+ if (cur < 0) return -1;
12153
+ if (values !== void 0) values.push(TERMV);
12154
+ cur = nextTerm(k3, input, cur, ctx);
12155
+ if (cur < 0) return -1;
12156
+ if (values !== void 0) values.push(TERMV);
12157
+ return next === void 0 ? cur : next(input, cur, ctx, values);
12158
+ };
12159
+ };
12160
+ const bind = (start) => {
12161
+ const count = Math.min(4, n - start);
12162
+ const child = (offset) => link(code[base + start + offset]);
12163
+ return block(
12164
+ count,
12165
+ child(0),
12166
+ count > 1 ? child(1) : NEVER_PIECE,
12167
+ count > 2 ? child(2) : NEVER_PIECE,
12168
+ count > 3 ? child(3) : NEVER_PIECE,
12169
+ start + count < n ? bind(start + count) : void 0
12170
+ );
12171
+ };
12172
+ const first = link(code[base]);
12173
+ const tail = bind(1);
12174
+ const runDirectTerms = (input, pos, ctx, values) => {
12175
+ const v0 = first(input, pos, ctx);
12176
+ if (v0 === FAIL) return -1;
12177
+ if (values !== void 0) values.push(v0);
12178
+ return tail(input, EC.e, ctx, values);
12179
+ };
9977
12180
  if (fused) {
9978
12181
  return (input, pos, ctx) => {
9979
12182
  const values = [];
9980
- const cur = runTerms(input, pos, ctx, values);
12183
+ const cur = runDirectTerms(input, pos, ctx, values);
9981
12184
  if (cur < 0) return FAIL;
9982
12185
  EC.e = cur;
9983
- return fn(values, { start: pos, end: cur });
12186
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9984
12187
  };
9985
12188
  }
9986
12189
  if (wantValues) {
9987
12190
  return (input, pos, ctx) => {
9988
12191
  const values = [];
9989
- const cur = runTerms(input, pos, ctx, values);
12192
+ const cur = runDirectTerms(input, pos, ctx, values);
9990
12193
  if (cur < 0) return FAIL;
9991
12194
  EC.e = cur;
9992
12195
  return values;
9993
12196
  };
9994
12197
  }
9995
12198
  return (input, pos, ctx) => {
9996
- const cur = runTerms(input, pos, ctx, void 0);
12199
+ const cur = runDirectTerms(input, pos, ctx, void 0);
9997
12200
  if (cur < 0) return FAIL;
9998
12201
  EC.e = cur;
9999
12202
  return void 0;
@@ -10005,13 +12208,86 @@ function assemble(t, prog, cfg) {
10005
12208
  const n = code[ip + 2];
10006
12209
  const choiceFx = fx[code[ip + 3]];
10007
12210
  const base = ip + 4;
10008
- const arms = new Array(n);
10009
- for (let i = 0; i < n; i++) arms[i] = link(code[base + i]);
10010
- const armFx = new Array(n);
10011
- for (let i = 0; i < n; i++) armFx[i] = fx[code[base + n + i]];
10012
12211
  if (table.exclusive) {
10013
12212
  const ascii = table.ascii;
10014
12213
  const hi = table.hi;
12214
+ if (n === 2) {
12215
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
12216
+ return (input, pos, ctx) => {
12217
+ const c = lead(input, pos);
12218
+ let arm = -1;
12219
+ if (c >= 0 && c < 128) {
12220
+ const a = ascii[c];
12221
+ if (a !== 0) arm = a - 1;
12222
+ } else if (c >= 128) {
12223
+ for (let i = 0; i < hi.length; i += 3) {
12224
+ if (c >= hi[i] && c <= hi[i + 1]) {
12225
+ arm = hi[i + 2];
12226
+ break;
12227
+ }
12228
+ }
12229
+ }
12230
+ if (arm >= 0) {
12231
+ ctx._fc = false;
12232
+ const v = arm === 0 ? a0(input, pos, ctx) : a1(input, pos, ctx);
12233
+ if (v !== FAIL) return v;
12234
+ if (committed3(ctx)) return FAIL;
12235
+ const failed = ctx._fx;
12236
+ if (failed !== void 0 && failed.length > 0) {
12237
+ ctx._fe = pos;
12238
+ return FAIL;
12239
+ }
12240
+ }
12241
+ ctx._fe = pos;
12242
+ ctx._fx = choiceFx;
12243
+ return FAIL;
12244
+ };
12245
+ }
12246
+ if (n === 3) {
12247
+ const a0 = link(code[base]), a1 = link(code[base + 1]), a2 = link(code[base + 2]);
12248
+ return (input, pos, ctx) => {
12249
+ const c = lead(input, pos);
12250
+ let arm = -1;
12251
+ if (c >= 0 && c < 128) {
12252
+ const a = ascii[c];
12253
+ if (a !== 0) arm = a - 1;
12254
+ } else if (c >= 128) {
12255
+ for (let i = 0; i < hi.length; i += 3) {
12256
+ if (c >= hi[i] && c <= hi[i + 1]) {
12257
+ arm = hi[i + 2];
12258
+ break;
12259
+ }
12260
+ }
12261
+ }
12262
+ if (arm >= 0) {
12263
+ ctx._fc = false;
12264
+ const v = arm === 0 ? a0(input, pos, ctx) : arm === 1 ? a1(input, pos, ctx) : a2(input, pos, ctx);
12265
+ if (v !== FAIL) return v;
12266
+ if (committed3(ctx)) return FAIL;
12267
+ const failed = ctx._fx;
12268
+ if (failed !== void 0 && failed.length > 0) {
12269
+ ctx._fe = pos;
12270
+ return FAIL;
12271
+ }
12272
+ }
12273
+ ctx._fe = pos;
12274
+ ctx._fx = choiceFx;
12275
+ return FAIL;
12276
+ };
12277
+ }
12278
+ const bindExclusive = (start) => {
12279
+ const at = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12280
+ const next = start + 4 < n ? bindExclusive(start + 4) : void 0;
12281
+ return exclusiveChoiceBlock(
12282
+ start,
12283
+ at(start),
12284
+ at(start + 1),
12285
+ at(start + 2),
12286
+ at(start + 3),
12287
+ next
12288
+ );
12289
+ };
12290
+ const selected = bindExclusive(0);
10015
12291
  return (input, pos, ctx) => {
10016
12292
  const c = lead(input, pos);
10017
12293
  let arm = -1;
@@ -10028,11 +12304,11 @@ function assemble(t, prog, cfg) {
10028
12304
  }
10029
12305
  if (arm >= 0) {
10030
12306
  ctx._fc = false;
10031
- const v = arms[arm](input, pos, ctx);
12307
+ const v = selected(arm, input, pos, ctx);
10032
12308
  if (v !== FAIL) return v;
10033
- if (committed2(ctx)) return FAIL;
10034
- const armFx2 = ctx._fx;
10035
- if (armFx2 !== void 0 && armFx2.length > 0) {
12309
+ if (committed3(ctx)) return FAIL;
12310
+ const armFx = ctx._fx;
12311
+ if (armFx !== void 0 && armFx.length > 0) {
10036
12312
  ctx._fe = pos;
10037
12313
  return FAIL;
10038
12314
  }
@@ -10043,25 +12319,25 @@ function assemble(t, prog, cfg) {
10043
12319
  };
10044
12320
  }
10045
12321
  const armCls = table.armCls;
10046
- const gates = new Array(n);
10047
- for (let i = 0; i < n; i++) gates[i] = armCls[i] ?? null;
10048
- const maskable = n <= 32;
10049
- let cand;
10050
- if (maskable) {
10051
- const m = new Uint32Array(129);
10052
- for (let i = 0; i < n; i++) {
10053
- const cls = gates[i];
10054
- const bit = 1 << i;
12322
+ if (n === 2 || n === 3) {
12323
+ const a0 = link(code[base]), a1 = link(code[base + 1]);
12324
+ const a2 = n === 3 ? link(code[base + 2]) : void 0;
12325
+ const e0 = fx[code[base + n]];
12326
+ const e1 = fx[code[base + n + 1]];
12327
+ const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
12328
+ const g0 = armCls[0] ?? null, g1 = armCls[1] ?? null;
12329
+ const g2 = n === 3 ? armCls[2] ?? null : null;
12330
+ const mask = new Uint32Array(129);
12331
+ const addGate = (cls, bit) => {
10055
12332
  if (cls === null) {
10056
- for (let c = 0; c < 129; c++) m[c] |= bit;
10057
- continue;
12333
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
12334
+ return;
10058
12335
  }
10059
- for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) m[c] |= bit;
10060
- }
10061
- cand = m;
10062
- }
10063
- if (cand !== void 0) {
10064
- const mask = cand;
12336
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
12337
+ };
12338
+ addGate(g0, 1);
12339
+ addGate(g1, 2);
12340
+ if (n === 3) addGate(g2, 4);
10065
12341
  return (input, pos, ctx) => {
10066
12342
  const c = lead(input, pos);
10067
12343
  const need = markCst(ctx);
@@ -10074,50 +12350,206 @@ function assemble(t, prog, cfg) {
10074
12350
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10075
12351
  let acc;
10076
12352
  if (c < 128) {
10077
- const bits0 = mask[c < 0 ? 128 : c];
10078
- let bits = bits0;
12353
+ const bits = mask[c < 0 ? 128 : c];
10079
12354
  let prev = 0;
10080
- while (bits !== 0) {
10081
- const i = 31 - Math.clz32(bits & -bits);
10082
- bits &= bits - 1;
12355
+ if ((bits & 1) !== 0) {
12356
+ ctx._fc = false;
12357
+ const v = a0(input, pos, ctx);
12358
+ if (v !== FAIL) return v;
12359
+ prev = 1;
12360
+ acc = accSet(ctx._fx, acc);
12361
+ if (committed3(ctx)) {
12362
+ if (acc !== void 0) ctx._fx = acc;
12363
+ return FAIL;
12364
+ }
12365
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12366
+ }
12367
+ if ((bits & 2) !== 0) {
10083
12368
  ctx._fc = false;
10084
- const v = arms[i](input, pos, ctx);
12369
+ const v = a1(input, pos, ctx);
10085
12370
  if (v !== FAIL) return v;
10086
- for (let j = prev; j < i; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
10087
- prev = i + 1;
12371
+ if (prev < 1) acc = accSet(e0, acc);
12372
+ prev = 2;
10088
12373
  acc = accSet(ctx._fx, acc);
10089
- if (committed2(ctx)) {
12374
+ if (committed3(ctx)) {
10090
12375
  if (acc !== void 0) ctx._fx = acc;
10091
12376
  return FAIL;
10092
12377
  }
10093
12378
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10094
12379
  }
10095
- for (let j = prev; j < n; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
12380
+ if (n === 3 && (bits & 4) !== 0) {
12381
+ ctx._fc = false;
12382
+ const v = a2(input, pos, ctx);
12383
+ if (v !== FAIL) return v;
12384
+ if (prev < 1) acc = accSet(e0, acc);
12385
+ if (prev < 2) acc = accSet(e1, acc);
12386
+ prev = 3;
12387
+ acc = accSet(ctx._fx, acc);
12388
+ if (committed3(ctx)) {
12389
+ if (acc !== void 0) ctx._fx = acc;
12390
+ return FAIL;
12391
+ }
12392
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12393
+ }
12394
+ if (prev < 1) acc = accSet(e0, acc);
12395
+ if (prev < 2) acc = accSet(e1, acc);
12396
+ if (n === 3 && prev < 3) acc = accSet(e2, acc);
10096
12397
  ctx._fe = pos;
10097
12398
  ctx._fx = acc ?? choiceFx;
10098
12399
  return FAIL;
10099
12400
  }
10100
- for (let i = 0; i < n; i++) {
10101
- const cls = gates[i];
10102
- if (cls !== null && !classHas(cls, c)) {
10103
- acc = accSet(armFx[i], acc);
10104
- continue;
12401
+ if (g0 === null || classHas2(g0, c)) {
12402
+ ctx._fc = false;
12403
+ const v = a0(input, pos, ctx);
12404
+ if (v !== FAIL) return v;
12405
+ acc = accSet(ctx._fx, acc);
12406
+ if (committed3(ctx)) {
12407
+ if (acc !== void 0) ctx._fx = acc;
12408
+ return FAIL;
10105
12409
  }
12410
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12411
+ } else acc = accSet(e0, acc);
12412
+ if (g1 === null || classHas2(g1, c)) {
10106
12413
  ctx._fc = false;
10107
- const v = arms[i](input, pos, ctx);
12414
+ const v = a1(input, pos, ctx);
10108
12415
  if (v !== FAIL) return v;
10109
12416
  acc = accSet(ctx._fx, acc);
10110
- if (committed2(ctx)) {
12417
+ if (committed3(ctx)) {
10111
12418
  if (acc !== void 0) ctx._fx = acc;
10112
12419
  return FAIL;
10113
12420
  }
10114
12421
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12422
+ } else acc = accSet(e1, acc);
12423
+ if (n === 3) {
12424
+ if (g2 === null || classHas2(g2, c)) {
12425
+ ctx._fc = false;
12426
+ const v = a2(input, pos, ctx);
12427
+ if (v !== FAIL) return v;
12428
+ acc = accSet(ctx._fx, acc);
12429
+ if (committed3(ctx)) {
12430
+ if (acc !== void 0) ctx._fx = acc;
12431
+ return FAIL;
12432
+ }
12433
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12434
+ } else acc = accSet(e2, acc);
10115
12435
  }
10116
12436
  ctx._fe = pos;
10117
12437
  ctx._fx = acc ?? choiceFx;
10118
12438
  return FAIL;
10119
12439
  };
10120
12440
  }
12441
+ const bindGeneral = (start, prior) => {
12442
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12443
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
12444
+ const gate2 = (i) => i < n ? armCls[i] ?? null : NEVER_CLASS;
12445
+ const through = expectedBlock(
12446
+ start,
12447
+ expected(start),
12448
+ expected(start + 1),
12449
+ expected(start + 2),
12450
+ expected(start + 3),
12451
+ prior
12452
+ );
12453
+ const next = start + 4 < n ? bindGeneral(start + 4, through) : void 0;
12454
+ return generalChoiceBlock(
12455
+ start,
12456
+ arm(start),
12457
+ arm(start + 1),
12458
+ arm(start + 2),
12459
+ arm(start + 3),
12460
+ gate2(start),
12461
+ gate2(start + 1),
12462
+ gate2(start + 2),
12463
+ gate2(start + 3),
12464
+ through,
12465
+ next,
12466
+ n,
12467
+ choiceFx
12468
+ );
12469
+ };
12470
+ const general = bindGeneral(0, EMPTY_EXPECTED_PREFIX);
12471
+ if (n <= 32) {
12472
+ const mask = new Uint32Array(129);
12473
+ for (let i = 0; i < n; i++) {
12474
+ const cls = armCls[i] ?? null;
12475
+ const bit = 1 << i;
12476
+ if (cls === null) {
12477
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
12478
+ continue;
12479
+ }
12480
+ for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) mask[c] |= bit;
12481
+ }
12482
+ const bindMasked = (start, prior) => {
12483
+ const arm = (i) => i < n ? link(code[base + i]) : NEVER_PIECE;
12484
+ const expected = (i) => i < n ? fx[code[base + n + i]] : EMPTY_FX2;
12485
+ const through = expectedBlock(
12486
+ start,
12487
+ expected(start),
12488
+ expected(start + 1),
12489
+ expected(start + 2),
12490
+ expected(start + 3),
12491
+ prior
12492
+ );
12493
+ const next = start + 4 < n ? bindMasked(start + 4, through) : void 0;
12494
+ return maskedChoiceBlock(
12495
+ start,
12496
+ arm(start),
12497
+ arm(start + 1),
12498
+ arm(start + 2),
12499
+ arm(start + 3),
12500
+ through,
12501
+ next,
12502
+ n,
12503
+ choiceFx
12504
+ );
12505
+ };
12506
+ const masked = bindMasked(0, EMPTY_EXPECTED_PREFIX);
12507
+ return (input, pos, ctx) => {
12508
+ const c = lead(input, pos);
12509
+ const need = markCst(ctx);
12510
+ const mRaw = MRAW;
12511
+ const mTl = MTL;
12512
+ const mLv = MLV;
12513
+ const mFl = need ? ctx._fields?.length ?? 0 : 0;
12514
+ const mEr = need ? ctx._errors?.length ?? 0 : 0;
12515
+ const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
12516
+ const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
12517
+ if (c < 128) {
12518
+ return masked(
12519
+ input,
12520
+ pos,
12521
+ ctx,
12522
+ mask[c < 0 ? 128 : c],
12523
+ need,
12524
+ mRaw,
12525
+ mTl,
12526
+ mLv,
12527
+ mFl,
12528
+ mEr,
12529
+ mLog,
12530
+ mRoot,
12531
+ void 0,
12532
+ 0
12533
+ );
12534
+ }
12535
+ return general(
12536
+ input,
12537
+ pos,
12538
+ ctx,
12539
+ c,
12540
+ need,
12541
+ mRaw,
12542
+ mTl,
12543
+ mLv,
12544
+ mFl,
12545
+ mEr,
12546
+ mLog,
12547
+ mRoot,
12548
+ void 0,
12549
+ 0
12550
+ );
12551
+ };
12552
+ }
10121
12553
  return (input, pos, ctx) => {
10122
12554
  const c = lead(input, pos);
10123
12555
  const need = markCst(ctx);
@@ -10128,26 +12560,22 @@ function assemble(t, prog, cfg) {
10128
12560
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
10129
12561
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10130
12562
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10131
- let acc;
10132
- for (let i = 0; i < n; i++) {
10133
- const cls = gates[i];
10134
- if (cls !== null && !classHas(cls, c)) {
10135
- acc = accSet(armFx[i], acc);
10136
- continue;
10137
- }
10138
- ctx._fc = false;
10139
- const v = arms[i](input, pos, ctx);
10140
- if (v !== FAIL) return v;
10141
- acc = accSet(ctx._fx, acc);
10142
- if (committed2(ctx)) {
10143
- if (acc !== void 0) ctx._fx = acc;
10144
- return FAIL;
10145
- }
10146
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10147
- }
10148
- ctx._fe = pos;
10149
- ctx._fx = acc ?? choiceFx;
10150
- return FAIL;
12563
+ return general(
12564
+ input,
12565
+ pos,
12566
+ ctx,
12567
+ c,
12568
+ need,
12569
+ mRaw,
12570
+ mTl,
12571
+ mLv,
12572
+ mFl,
12573
+ mEr,
12574
+ mLog,
12575
+ mRoot,
12576
+ void 0,
12577
+ 0
12578
+ );
10151
12579
  };
10152
12580
  }
10153
12581
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -10216,7 +12644,7 @@ function assemble(t, prog, cfg) {
10216
12644
  if (nc !== 0) {
10217
12645
  const c = lead(input, end);
10218
12646
  for (let i = 0; i < nc; i++) {
10219
- if (!classHas(clss[i], c)) continue;
12647
+ if (!classHas2(clss[i], c)) continue;
10220
12648
  ctx._fc = false;
10221
12649
  ctx._fx = void 0;
10222
12650
  return FAIL;
@@ -10240,6 +12668,9 @@ function assemble(t, prog, cfg) {
10240
12668
  const reportItem = (flags & 4) !== 0;
10241
12669
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
10242
12670
  const collect = op === OP_REP;
12671
+ const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
12672
+ const itemClass = !REC2 && itemClassIndex >= 0 ? cc[itemClassIndex] : void 0;
12673
+ const itemMayStart = itemClass === void 0 ? void 0 : (input, pos) => classHas2(itemClass, lead(input, pos));
10243
12674
  const skipBeforeFirst = sepIp < 0 && min === 0;
10244
12675
  if (REC2) {
10245
12676
  const itemFx2 = fx[code[ip + 6]];
@@ -10273,7 +12704,7 @@ function assemble(t, prog, cfg) {
10273
12704
  const sv = sep(input, sp, ctx);
10274
12705
  if (sv === FAIL) {
10275
12706
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10276
- if (committed2(ctx)) return FAIL;
12707
+ if (committed3(ctx)) return FAIL;
10277
12708
  break;
10278
12709
  }
10279
12710
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -10290,7 +12721,7 @@ function assemble(t, prog, cfg) {
10290
12721
  ctx._fc = false;
10291
12722
  const v = child(input, itemStart, ctx);
10292
12723
  if (v === FAIL) {
10293
- if (committed2(ctx)) {
12724
+ if (committed3(ctx)) {
10294
12725
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10295
12726
  return FAIL;
10296
12727
  }
@@ -10336,11 +12767,13 @@ function assemble(t, prog, cfg) {
10336
12767
  const out = collect ? [] : void 0;
10337
12768
  const hasTrivia = ctx.trivia !== void 0;
10338
12769
  const needMark = rollbackNeeded(ctx);
12770
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
10339
12771
  let cur = pos;
10340
12772
  let count = 0;
10341
12773
  for (; ; ) {
10342
12774
  if (max >= 0 && count >= max) break;
10343
12775
  if (sep !== void 0 && count > 0 && count >= min && cur >= input.length) break;
12776
+ if (count >= min && sep === void 0 && !hasTrivia && gateItems && !itemMayStart(input, cur)) break;
10344
12777
  if (needMark) markCst(ctx);
10345
12778
  const mRaw = needMark ? MRAW : 0;
10346
12779
  const mTl = needMark ? MTL : 0;
@@ -10360,7 +12793,7 @@ function assemble(t, prog, cfg) {
10360
12793
  const sv = sep(input, sp, ctx);
10361
12794
  if (sv === FAIL) {
10362
12795
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10363
- if (committed2(ctx)) return FAIL;
12796
+ if (committed3(ctx)) return FAIL;
10364
12797
  break;
10365
12798
  }
10366
12799
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -10374,11 +12807,16 @@ function assemble(t, prog, cfg) {
10374
12807
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
10375
12808
  break;
10376
12809
  }
12810
+ if (count >= min && gateItems && !itemMayStart(input, itemStart)) {
12811
+ if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12812
+ if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
12813
+ break;
12814
+ }
10377
12815
  ctx._fc = false;
10378
12816
  const v = child(input, itemStart, ctx);
10379
12817
  if (v === FAIL) {
10380
12818
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10381
- if (committed2(ctx)) return FAIL;
12819
+ if (committed3(ctx)) return FAIL;
10382
12820
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
10383
12821
  break;
10384
12822
  }
@@ -10410,78 +12848,103 @@ function assemble(t, prog, cfg) {
10410
12848
  const otherRouted = code[ip + 4] === 1;
10411
12849
  const n = code[ip + 5];
10412
12850
  const armBase = ip + 6;
10413
- const arms = new Array(n);
10414
- for (let i = 0; i < n; i++) arms[i] = link(code[armBase + i]);
10415
12851
  const byKey = spec.byKey;
10416
12852
  const byFold = spec.byFold;
10417
12853
  const hasFold = spec.byFold.size > 0;
10418
12854
  const match = spec.match;
10419
12855
  const matchN = match.length;
10420
- const matchFn = new Array(matchN);
10421
- const matchArm = new Array(matchN);
10422
- for (let i = 0; i < matchN; i++) {
10423
- matchFn[i] = linkMatcher(match[i]);
10424
- matchArm[i] = match[i][3];
10425
- }
10426
12856
  const routed2 = spec.routed;
10427
12857
  const expected = spec.expected;
12858
+ const validArm = (arm) => Number.isInteger(arm) && arm >= 0 && arm < n;
12859
+ if (routed2.length !== n) throw new TypeError("table assembler: malformed dispatch routed arity");
12860
+ for (const arm of byKey.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch exact arm");
12861
+ for (const arm of byFold.values()) if (!validArm(arm)) throw new TypeError("table assembler: malformed dispatch folded arm");
12862
+ for (const m of match) if (!validArm(m[3])) throw new TypeError("table assembler: malformed dispatch matcher arm");
12863
+ const neverMatch = () => false;
12864
+ const bindMatchers = (start) => {
12865
+ const pred = (i) => i < matchN ? linkMatcher(match[i]) : neverMatch;
12866
+ const arm = (i) => i < matchN ? match[i][3] : -1;
12867
+ const next = start + 4 < matchN ? bindMatchers(start + 4) : void 0;
12868
+ return dispatchMatcherBlock(
12869
+ pred(start),
12870
+ arm(start),
12871
+ pred(start + 1),
12872
+ arm(start + 1),
12873
+ pred(start + 2),
12874
+ arm(start + 2),
12875
+ pred(start + 3),
12876
+ arm(start + 3),
12877
+ next
12878
+ );
12879
+ };
12880
+ const matchBlock = matchN === 0 ? void 0 : bindMatchers(0);
12881
+ const classify = hasFold ? matchBlock === void 0 ? (key) => byKey.get(key) ?? byFold.get(asciiFoldKey(key)) : (key) => byKey.get(key) ?? byFold.get(asciiFoldKey(key)) ?? matchBlock(key) : matchBlock === void 0 ? (key) => byKey.get(key) : (key) => byKey.get(key) ?? matchBlock(key);
12882
+ const neverBranch = () => FAIL;
12883
+ const bindArms = (start) => {
12884
+ const branch = (i) => i < n ? dispatchBranch(link(code[armBase + i]), routed2[i] === 1) : neverBranch;
12885
+ const next = start + 4 < n ? bindArms(start + 4) : void 0;
12886
+ return dispatchArmBlock(
12887
+ start,
12888
+ branch(start),
12889
+ branch(start + 1),
12890
+ branch(start + 2),
12891
+ branch(start + 3),
12892
+ next
12893
+ );
12894
+ };
12895
+ const runArm = n === 0 ? void 0 : bindArms(0);
12896
+ const runOther = other === void 0 ? void 0 : dispatchBranch(other, otherRouted);
10428
12897
  return (input, pos, ctx) => {
10429
12898
  const selectorMark = saveTriviaMark(ctx);
10430
12899
  const selVal = selector(input, pos, ctx);
10431
12900
  if (selVal === FAIL) return FAIL;
10432
12901
  const selEnd = EC.e;
10433
12902
  const key = selVal;
10434
- let arm = byKey.get(key);
10435
- if (arm === void 0 && hasFold) arm = byFold.get(asciiFoldKey(key));
12903
+ const arm = classify(key);
10436
12904
  if (arm === void 0) {
10437
- for (let i = 0; i < matchN; i++) {
10438
- if (matchFn[i](key)) {
10439
- arm = matchArm[i];
10440
- break;
10441
- }
10442
- }
10443
- }
10444
- let target;
10445
- let usesRouted;
10446
- if (arm === void 0) {
10447
- if (other === void 0) {
12905
+ if (runOther === void 0) {
10448
12906
  ctx._fe = selEnd;
10449
12907
  ctx._fx = expected;
10450
12908
  return FAIL;
10451
12909
  }
10452
- target = other;
10453
- usesRouted = otherRouted;
10454
- } else {
10455
- target = arms[arm];
10456
- usesRouted = routed2[arm] === 1;
10457
- }
10458
- let mark = saveTriviaMark(ctx);
10459
- let v;
10460
- if (usesRouted) {
10461
- const savedRouted = ctx._routed;
10462
- rollbackTrivia(ctx, selectorMark);
10463
- mark = saveTriviaMark(ctx);
10464
- ctx._routed = { value: key, span: { start: pos, end: selEnd } };
10465
- try {
10466
- v = target(input, pos, ctx);
10467
- } finally {
10468
- ctx._routed = savedRouted;
10469
- }
10470
- } else {
10471
- v = target(input, selEnd, ctx);
10472
- }
10473
- if (v === FAIL) {
10474
- rollbackTrivia(ctx, mark);
10475
- ctx._fc = true;
10476
- return FAIL;
12910
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
10477
12911
  }
10478
- return [key, v];
12912
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
10479
12913
  };
10480
12914
  }
10481
12915
  /* ── node ────────────────────────────────────────────────────────────── */
10482
12916
  case OP_NODE:
10483
12917
  case OP_NODE_TRACK: {
10484
12918
  const flags = code[ip + 3];
12919
+ const scalarChild = !hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines ? scalarTerminalNodeChild(code, ip) : -1;
12920
+ if (scalarChild >= 0) {
12921
+ const recognize = scalarFor(scalarChild);
12922
+ const spec = k[code[scalarChild + 1]];
12923
+ const regexValue = code[scalarChild] === OP_RX;
12924
+ const xf = fx[code[scalarChild + 2]];
12925
+ const build2 = fns[code[ip + 1]];
12926
+ return (input, pos, ctx) => {
12927
+ const end = recognize(input, pos);
12928
+ if (end < 0) {
12929
+ ctx._fe = pos;
12930
+ ctx._fx = xf;
12931
+ if (ctx._probe !== void 0) failAt(ctx, xf, pos);
12932
+ return FAIL;
12933
+ }
12934
+ const value = regexValue ? input.slice(pos, end) : spec;
12935
+ const leaf2 = { _tag: "leaf", value, span: { start: pos, end } };
12936
+ const kids = [leaf2];
12937
+ const rawKids = [leaf2];
12938
+ const span = { start: pos, end };
12939
+ EC.e = end;
12940
+ const nd = build2(kids, void 0, span, rawKids, EMPTY_TL2, void 0);
12941
+ if (ctx._cstBuf !== void 0 || ctx._cstChildren !== void 0) {
12942
+ pushCstChild(ctx, nd, ctx._cstRawChildren !== void 0 || ctx._cstBuf !== void 0 ? rawEntry(nd, input, pos, end) : void 0);
12943
+ }
12944
+ EC.e = end;
12945
+ return nd;
12946
+ };
12947
+ }
10485
12948
  const child = link(code[ip + 2]);
10486
12949
  const proj = code[ip + 4];
10487
12950
  const buildIdx = code[ip + 1];
@@ -10496,6 +12959,26 @@ function assemble(t, prog, cfg) {
10496
12959
  const unwrap = (flags & 64) !== 0;
10497
12960
  const trailingTrivia = (flags & 128) !== 0;
10498
12961
  const build = buildIdx >= 0 ? fns[buildIdx] : void 0;
12962
+ if (!hostCst && !tracked) {
12963
+ if (build !== void 0 && proj < 0 && flags === 0) {
12964
+ return plainBuildNode(child, build);
12965
+ }
12966
+ if (build !== void 0 && proj < 0 && flags === 2) {
12967
+ return childrenOnlyBuildNode(child, build);
12968
+ }
12969
+ if (build !== void 0 && proj < 0 && flags === 18) {
12970
+ return childrenOnlyFieldsBuildNode(child, build);
12971
+ }
12972
+ if (build !== void 0 && proj < 0 && flags === 32) {
12973
+ return collapseBuildNode(child, build);
12974
+ }
12975
+ if (build !== void 0 && proj < 0 && flags === 34) {
12976
+ return childrenOnlyCollapseBuildNode(child, build);
12977
+ }
12978
+ if (build === void 0 && proj >= 0 && flags === 0) {
12979
+ return plainProjectNode(child, proj, type);
12980
+ }
12981
+ }
10499
12982
  const structural = build === void 0 && proj < 0;
10500
12983
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
10501
12984
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -10615,14 +13098,27 @@ function assemble(t, prog, cfg) {
10615
13098
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10616
13099
  }
10617
13100
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
10618
- const validationRoots = [...Object.values(prog.rules), ...extraIps];
10619
- for (const ip of reachableSites(code, validationRoots)) {
10620
- if (code[ip] !== OP_DISPATCH) continue;
10621
- validateDispatchSpec(dsp[code[ip + 2]], code[ip + 5], code[ip + 4]);
13101
+ const roots = [...Object.values(prog.rules), ...extraIps];
13102
+ for (const ip of reachableSites(code, roots)) {
13103
+ if (code[ip] === OP_DISPATCH) {
13104
+ const spec = dsp[code[ip + 2]];
13105
+ validateDispatchSpec(spec, code[ip + 5], code[ip + 4]);
13106
+ }
13107
+ if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
13108
+ if (code[ip] === OP_NODE) {
13109
+ const child = scalarTerminalNodeChild(code, ip);
13110
+ if (child >= 0) {
13111
+ rawScalarSpecs.add(code[child + 1]);
13112
+ scalarFor(child);
13113
+ }
13114
+ }
13115
+ }
13116
+ const notChild = scalarTerminalNotChild(code, ip);
13117
+ if (notChild >= 0) scalarFor(notChild);
10622
13118
  }
10623
13119
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10624
13120
  if (pre !== void 0) {
10625
- const pools = rebuildPools(t.cc, t.fx, pre.plan);
13121
+ const pools = rebuildPools(t.cc, t.fx, t.disp, pre.plan);
10626
13122
  emitted = pre.factory(
10627
13123
  EC,
10628
13124
  FAIL,
@@ -10648,7 +13144,7 @@ function assemble(t, prog, cfg) {
10648
13144
  rollbackTriviaAt,
10649
13145
  rollbackScannedTriviaAt,
10650
13146
  failAt,
10651
- classHas,
13147
+ classHas2,
10652
13148
  consumeTrivia,
10653
13149
  buildFieldMap,
10654
13150
  projectChild,
@@ -10669,7 +13165,13 @@ function assemble(t, prog, cfg) {
10669
13165
  matchesAt,
10670
13166
  recoverScan,
10671
13167
  orSentinel,
10672
- captureError
13168
+ captureError,
13169
+ scalarRecognizers,
13170
+ commitTriviaScan,
13171
+ scanTriviaCompact,
13172
+ t.lex,
13173
+ adjacencyHolds,
13174
+ t.lexPrograms
10673
13175
  );
10674
13176
  emitReached = new Set(pre.reached);
10675
13177
  }
@@ -10719,7 +13221,7 @@ function assemble(t, prog, cfg) {
10719
13221
  rollbackTriviaAt,
10720
13222
  rollbackScannedTriviaAt,
10721
13223
  failAt,
10722
- classHas,
13224
+ classHas2,
10723
13225
  consumeTrivia,
10724
13226
  buildFieldMap,
10725
13227
  projectChild,
@@ -10745,7 +13247,13 @@ function assemble(t, prog, cfg) {
10745
13247
  matchesAt,
10746
13248
  recoverScan,
10747
13249
  orSentinel,
10748
- captureError
13250
+ captureError,
13251
+ scalarRecognizers,
13252
+ commitTriviaScan,
13253
+ scanTriviaCompact,
13254
+ t.lex,
13255
+ adjacencyHolds,
13256
+ t.lexPrograms
10749
13257
  );
10750
13258
  emitReached = em.reached;
10751
13259
  } catch (e) {
@@ -10996,6 +13504,17 @@ function emitScanSpec(s) {
10996
13504
  function emitDispatchSpec(d) {
10997
13505
  return `{key:[${d.key.map(jsString).join(",")}],keyArm:[${d.keyArm.join(",")}],fold:[${d.fold.map(jsString).join(",")}],foldArm:[${d.foldArm.join(",")}],match:[${d.match.map((m) => `[${m[0]},${jsString(m[1])},${jsString(m[2])},${m[3]}]`).join(",")}],routed:[${d.routed.join(",")}],expected:[${d.expected.map(jsString).join(",")}]}`;
10998
13506
  }
13507
+ function defaultAssemblyCfgs(prog) {
13508
+ const hostCst = prog.hostMode === "cst";
13509
+ const trackLines = prog.lines === 1;
13510
+ return [false, true].map((tolerant) => ({
13511
+ hostCst,
13512
+ trackLines,
13513
+ tolerant,
13514
+ coverage: false,
13515
+ probe: false
13516
+ }));
13517
+ }
10999
13518
  function emitAssemblies(prog, cfgs) {
11000
13519
  if (cfgs.length === 0) return ["a:[],"];
11001
13520
  const t = resolveTable(prog);
@@ -11048,6 +13567,8 @@ function programFields(prog, fns, opts = {}) {
11048
13567
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
11049
13568
  // exact failure the root-trivia work exists to prevent, one hop downstream.
11050
13569
  ...prog.dsp.length === 0 ? [] : [`p:[${prog.dsp.map(emitDispatchSpec).join(",")}],`],
13570
+ ...prog.lex === void 0 ? [] : [`lx:[${prog.lex.map((row) => `[${row.join(",")}]`).join(",")}],`],
13571
+ ...prog.lexPrograms === void 0 ? [] : [`lp:[${prog.lexPrograms.map((row) => `[${row.join(",")}]`).join(",")}],`],
11051
13572
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
11052
13573
  ...prog.classified === 1 ? ["rc:1,"] : [],
11053
13574
  // Without this a recovery table's MODULE loads as a strict one: the extra
@@ -13271,6 +15792,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
13271
15792
  };
13272
15793
 
13273
15794
  // src/table/compile-rule-map.ts
15795
+ var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
13274
15796
  function resolveHostMode(ruleMap, explicit) {
13275
15797
  return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
13276
15798
  }
@@ -13360,10 +15882,11 @@ function compileRuleMap(ruleMap, opts = {}) {
13360
15882
  `compileRuleMap: got ${supplied.length} fnSources for a pool of ${fnSrcs.length}. The list is positional, in prog.fns order, so a longer one means it belongs to a different encode \u2014 and the entries would be silently misassigned.`
13361
15883
  );
13362
15884
  }
13363
- const replacementWithMetadata = (metadataSource) => emitTableExpression(artifact, {
15885
+ const replacementWithMetadata = (metadataSource, options = {}) => emitTableExpression(artifact, {
13364
15886
  entry: null,
13365
15887
  runtimeRef: opts.runtimeRef ?? "tableRules",
13366
15888
  fnSources: sources,
15889
+ ...options.precompileDefault === true && hostMode === "ast" && prog.lines !== 1 && prog.code.length >= DEFAULT_PRECOMPILE_MIN_WORDS ? { assemblies: defaultAssemblyCfgs(artifact).slice(0, 1) } : {},
13367
15890
  ...metadataSource === void 0 ? {} : { metadataSource }
13368
15891
  });
13369
15892
  const replacement = replacementWithMetadata();
@@ -13388,7 +15911,7 @@ function compileRuleMap(ruleMap, opts = {}) {
13388
15911
  }
13389
15912
 
13390
15913
  // src/version.ts
13391
- var PARSEMAN_VERSION = "0.47.1";
15914
+ var PARSEMAN_VERSION = "0.48.0";
13392
15915
 
13393
15916
  // src/compiler/compile-linkable-table.ts
13394
15917
  function isLocal(rule) {