parseman 0.47.0 → 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 +2955 -357
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +2946 -348
  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 +19 -1
  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 +2959 -348
  37. package/dist/index.js.map +3 -3
  38. package/dist/language-service/index.js +7 -1
  39. package/dist/language-service/index.js.map +1 -1
  40. package/dist/plugin/index.js +2969 -358
  41. package/dist/plugin/index.js.map +3 -3
  42. package/dist/spec/index.js +366 -49
  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 +13 -14
  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 +4839 -2232
  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 +47 -4
  61. package/dist/table/ops.d.ts.map +1 -1
  62. package/dist/table/program.d.ts +53 -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 +12 -11
  71. package/src/combinators/expect.ts +1 -0
  72. package/src/combinators/expected.ts +17 -0
  73. package/src/combinators/first-set.ts +82 -3
  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 +35 -16
  82. package/src/combinators/trivia-skip.ts +75 -11
  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 +1224 -222
  91. package/src/table/child-slots.ts +4 -3
  92. package/src/table/compile-rule-map.ts +21 -3
  93. package/src/table/emit-assembly.ts +363 -109
  94. package/src/table/emit.ts +26 -1
  95. package/src/table/encode.ts +246 -54
  96. package/src/table/exec-baseline.ts +3 -7
  97. package/src/table/exec.ts +140 -18
  98. package/src/table/lex-body.ts +30 -0
  99. package/src/table/lex-program.ts +422 -0
  100. package/src/table/ops.ts +50 -4
  101. package/src/table/program.ts +67 -2
  102. package/src/table/scalar-terminal.ts +51 -0
  103. package/src/table/site-labels.ts +13 -3
  104. package/src/table/stamp.ts +3 -3
  105. package/src/types.ts +1 -1
  106. package/src/version.ts +1 -1
  107. package/dist/analysis/diagnostics.cjs +0 -13736
  108. package/dist/analysis/diagnostics.cjs.map +0 -6
  109. package/dist/cli/index.cjs +0 -14837
  110. package/dist/cli/index.cjs.map +0 -6
  111. package/dist/index.cjs +0 -16303
  112. package/dist/index.cjs.map +0 -6
  113. package/dist/language-service/index.cjs +0 -1302
  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 -16009
  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 -6188
  122. package/dist/spec/index.cjs.map +0 -6
  123. package/dist/table/index.cjs +0 -11375
  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;
@@ -44,6 +80,13 @@ function empty() {
44
80
  function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve) {
45
81
  if (seen.has(p)) return true;
46
82
  seen.add(p);
83
+ try {
84
+ return matchesEmptyBody(p, seen, resolve);
85
+ } finally {
86
+ seen.delete(p);
87
+ }
88
+ }
89
+ function matchesEmptyBody(p, seen, resolve) {
47
90
  const me = (c) => matchesEmpty(c, seen, resolve);
48
91
  const d = p._def;
49
92
  switch (d.tag) {
@@ -145,6 +188,13 @@ function sequenceFirstSet(parsers) {
145
188
  function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve) {
146
189
  if (seen.has(p)) return any();
147
190
  seen.add(p);
191
+ try {
192
+ return firstSetBody(p, seen, resolve);
193
+ } finally {
194
+ seen.delete(p);
195
+ }
196
+ }
197
+ function firstSetBody(p, seen, resolve) {
148
198
  const fs = (c) => firstSetOf(c, seen, resolve);
149
199
  const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve);
150
200
  const d = p._def;
@@ -489,6 +539,21 @@ function pushTriviaLogEntry(ctx, start, end, kindIndex) {
489
539
  }
490
540
  }
491
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
+
492
557
  // src/combinators/literal.ts
493
558
  function asciiFoldEq(a, b) {
494
559
  if (a.length !== b.length) return false;
@@ -520,7 +585,7 @@ function literal(value, opts = {}) {
520
585
  { lo: firstUpper, hi: firstUpper }
521
586
  ] } : firstSet2;
522
587
  }
523
- const expected = [JSON.stringify(value)];
588
+ const expected = directTerminalFailureExpected({ tag: "literal", value, caseInsensitive });
524
589
  const parse2 = !caseInsensitive && value.length === 1 ? (() => {
525
590
  const code = value.charCodeAt(0);
526
591
  return function parse3(input, pos, ctx) {
@@ -998,14 +1063,15 @@ function regex(pattern, flags = "") {
998
1063
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
999
1064
  const canMatchNewline = raw.canMatchNewline;
1000
1065
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
1066
+ const def = { tag: "regex", source, flags: resolvedFlags };
1001
1067
  return {
1002
1068
  _tag: "regex",
1003
1069
  _meta: meta,
1004
- _def: { tag: "regex", source, flags: resolvedFlags },
1070
+ _def: def,
1005
1071
  parse(input, pos, ctx) {
1006
1072
  const scanEnd = scan?.(input, pos);
1007
1073
  if (scanEnd !== void 0) {
1008
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
1074
+ if (scanEnd === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
1009
1075
  const value = input.slice(pos, scanEnd);
1010
1076
  const span2 = { start: pos, end: scanEnd };
1011
1077
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, scanEnd);
@@ -1015,7 +1081,7 @@ function regex(pattern, flags = "") {
1015
1081
  anchored.lastIndex = pos;
1016
1082
  const m = anchored.exec(input);
1017
1083
  if (m === null) {
1018
- return failAt(ctx, [`/${source}/`], pos);
1084
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
1019
1085
  }
1020
1086
  const span = { start: pos, end: pos + m[0].length };
1021
1087
  if (canMatchNewline && ctx.trackLines) recordLineRangeFromContext(ctx, input, pos, span.end);
@@ -1074,12 +1140,14 @@ function makeWord(boundaryOrOpts = "_0-9A-Za-z", opts) {
1074
1140
  function escapeRe(s) {
1075
1141
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1076
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
+ }
1077
1148
  function keywords(words, opts = {}) {
1078
1149
  const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
1079
- const alt = sorted.map(escapeRe).join("|");
1080
- const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
1081
- const flags = opts.caseInsensitive ? "iy" : "uy";
1082
- const re = new RegExp(`(?:${alt})${boundary}`, flags);
1150
+ const re = keywordsRegExp(sorted, opts.boundary, opts.caseInsensitive ?? false);
1083
1151
  let firstSet2 = empty();
1084
1152
  for (const w of sorted) {
1085
1153
  if (w.length === 0) continue;
@@ -1090,15 +1158,21 @@ function keywords(words, opts = {}) {
1090
1158
  }
1091
1159
  }
1092
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
+ };
1093
1167
  return {
1094
1168
  _tag: "keywords",
1095
1169
  _meta: meta,
1096
- _def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
1170
+ _def: def,
1097
1171
  parse(input, pos, ctx) {
1098
1172
  re.lastIndex = pos;
1099
1173
  const m = re.exec(input);
1100
1174
  if (m === null || m.index !== pos) {
1101
- return failAt(ctx, ["keyword"], pos);
1175
+ return failAt(ctx, directTerminalFailureExpected(def), pos);
1102
1176
  }
1103
1177
  const value = m[0];
1104
1178
  const span = { start: pos, end: pos + value.length };
@@ -1153,6 +1227,179 @@ function createDetachedParseContext(trackLines, state) {
1153
1227
  return ctx;
1154
1228
  }
1155
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
+
1156
1403
  // src/cst/trivia-charscan.ts
1157
1404
  function inRanges2(cp, ranges) {
1158
1405
  for (let i = 0; i < ranges.length; i++) {
@@ -1306,6 +1553,35 @@ function classifyParser(p) {
1306
1553
  if (d.tag !== "regex" || d.flags) return null;
1307
1554
  return classifyArm(d.source);
1308
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
+ }
1309
1585
  var armSpec0;
1310
1586
  var armSpec1;
1311
1587
  var armSpec2;
@@ -1504,6 +1780,8 @@ function scanLabeledTriviaEnd(input, cur, spec, state) {
1504
1780
  }
1505
1781
  function visitLabeledTrivia(input, cur, spec, state, visit) {
1506
1782
  if (spec.minRepeats > 1) return void 0;
1783
+ const common = commonLabeledTriviaVisitor(spec);
1784
+ if (common !== null) return common(input, cur, visit);
1507
1785
  const chars = charArmsFor(spec);
1508
1786
  if (chars !== null) return charTriviaVisit(input, cur, chars, visit);
1509
1787
  let pos = cur;
@@ -1603,6 +1881,14 @@ function triviaKindMask(labels, keep) {
1603
1881
  // src/combinators/trivia-skip.ts
1604
1882
  var NOOP_COMMIT = () => {
1605
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
+ }
1606
1892
  var fastTrivia0;
1607
1893
  var fastTrivia1;
1608
1894
  var fastTrivia2;
@@ -1636,6 +1922,23 @@ function rollbackTrivia(ctx, mark) {
1636
1922
  if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
1637
1923
  if (ctx._rootTriviaLog && ctx._rootTriviaLog.length !== mark.rootLog) ctx._rootTriviaLog.length = mark.rootLog;
1638
1924
  }
1925
+ function removeNumberRange(values, start, end) {
1926
+ if (values === void 0 || end <= start) return;
1927
+ if (values.length > end) values.copyWithin(start, end);
1928
+ values.length -= end - start;
1929
+ }
1930
+ function rollbackScannedTriviaAt(ctx, tlogStart, tlogEnd, logStart, logEnd, rootLogStart, rootLogEnd) {
1931
+ const b = ctx._cstBuf;
1932
+ if (b !== void 0) {
1933
+ const tlog = b.tl;
1934
+ removeNumberRange(tlog, tlogStart, tlogEnd);
1935
+ if (tlog !== void 0 && tlog.length === 0) b.tl = void 0;
1936
+ } else {
1937
+ removeNumberRange(ctx._cstTriviaLog, tlogStart, tlogEnd);
1938
+ }
1939
+ removeNumberRange(ctx._triviaLog, logStart, logEnd);
1940
+ removeNumberRange(ctx._rootTriviaLog, rootLogStart, rootLogEnd);
1941
+ }
1639
1942
  function parseTriviaNoCapture(triviaP, input, cur, ctx) {
1640
1943
  const probeCtx = createDetachedParseContext(ctx.trackLines, ctx.state);
1641
1944
  probeCtx._lineIndex = ctx._lineIndex;
@@ -1655,7 +1958,7 @@ function rollbackLookahead(ctx, mark) {
1655
1958
  function scanWithLabels(input, cur, ctx) {
1656
1959
  const triviaP = ctx.trivia;
1657
1960
  const spec = analyzeLabeledTrivia(triviaP);
1658
- if (!spec) return { end: cur, commit: NOOP_COMMIT };
1961
+ if (!spec) return cur;
1659
1962
  const log = ctx._triviaLog;
1660
1963
  const rootLog = ctx._rootTriviaLog;
1661
1964
  const rootKinds = ctx._rootTriviaKindIndex;
@@ -1673,7 +1976,8 @@ function scanWithLabels(input, cur, ctx) {
1673
1976
  }
1674
1977
  });
1675
1978
  if (visitedEnd !== void 0) {
1676
- 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;
1677
1981
  return {
1678
1982
  end: visitedEnd,
1679
1983
  commit: () => {
@@ -1692,7 +1996,7 @@ function scanWithLabels(input, cur, ctx) {
1692
1996
  };
1693
1997
  }
1694
1998
  const { end, chunks } = scanLabeledTriviaChunks(input, cur, spec, ctx.state);
1695
- if (end === cur) return { end: cur, commit: NOOP_COMMIT };
1999
+ if (end === cur) return cur;
1696
2000
  return {
1697
2001
  end,
1698
2002
  commit: () => recordTriviaChunks(ctx, chunks)
@@ -1733,7 +2037,7 @@ function advanceTrivia(input, cur, ctx) {
1733
2037
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1734
2038
  return tr.ok && tr.span.end > cur ? tr.span.end : cur;
1735
2039
  }
1736
- function scanTrivia(input, cur, ctx) {
2040
+ function scanTriviaCompact(input, cur, ctx) {
1737
2041
  const triviaP = ctx.trivia;
1738
2042
  if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
1739
2043
  const log = ctx._triviaLog;
@@ -1774,7 +2078,7 @@ function scanTrivia(input, cur, ctx) {
1774
2078
  }
1775
2079
  if (ctx.triviaKindLabels && (log !== void 0 || rootLog !== void 0 || captureTl)) {
1776
2080
  const scan = scanWithLabels(input, cur, ctx);
1777
- if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, scan.end);
2081
+ if (trackTriviaLines) recordLineRangeFromContext(ctx, input, cur, triviaScanEnd(scan));
1778
2082
  return scan;
1779
2083
  }
1780
2084
  if (ctx.triviaKindLabels) {
@@ -1804,6 +2108,10 @@ function scanTrivia(input, cur, ctx) {
1804
2108
  const tr = parseTriviaNoCapture(triviaP, input, cur, ctx);
1805
2109
  return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
1806
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
+ }
1807
2115
  function skipTriviaScanned(s, input, cur, ctx) {
1808
2116
  const end = s(input, cur);
1809
2117
  if (end !== cur) {
@@ -1816,14 +2124,12 @@ function skipTriviaScanned(s, input, cur, ctx) {
1816
2124
  }
1817
2125
  function consumeTrivia(input, cur, ctx) {
1818
2126
  if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
1819
- const scan = scanTrivia(input, cur, ctx);
1820
- scan.commit();
1821
- return scan.end;
2127
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
1822
2128
  }
1823
2129
  function probeTriviaEnd(input, cur, ctx) {
1824
2130
  if (!ctx.trivia) return cur;
1825
2131
  const probeCtx = { ...ctx, trackLines: false };
1826
- if (needsDeferredTriviaCommit(probeCtx)) return scanTrivia(input, cur, probeCtx).end;
2132
+ if (needsDeferredTriviaCommit(probeCtx)) return triviaScanEnd(scanTriviaCompact(input, cur, probeCtx));
1827
2133
  return advanceTrivia(input, cur, probeCtx);
1828
2134
  }
1829
2135
  function fastTriviaScanner(trivia2) {
@@ -1851,10 +2157,16 @@ function buildFastTriviaScanner(trivia2) {
1851
2157
  const one = regexTriviaScanner(repeat);
1852
2158
  if (one) return loopScanner([one]);
1853
2159
  if (repeat._def.tag !== "choice") return null;
2160
+ const fused = commonCssTriviaScanner(repeat._def.parsers.map(triviaRegexSource));
2161
+ if (fused !== null) return fused;
1854
2162
  const arms = repeat._def.parsers.map(regexTriviaScanner);
1855
2163
  if (arms.some((s) => s === null)) return null;
1856
2164
  return loopScanner(arms);
1857
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
+ }
1858
2170
  function loopScanner(arms) {
1859
2171
  return (input, cur) => {
1860
2172
  let pos = cur;
@@ -2340,19 +2652,30 @@ function sequence(...parsers) {
2340
2652
  continue;
2341
2653
  }
2342
2654
  if (ctx.trivia && i > 0) {
2343
- const mark = saveTriviaMark(ctx);
2655
+ const mTlog = cstTlLen(ctx);
2656
+ const mLog = ctx._triviaLog?.length ?? 0;
2657
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2344
2658
  let scanEnd;
2345
2659
  if (needsDeferredTriviaCommit(ctx)) {
2346
- const scan = scanTrivia(input, cur, ctx);
2347
- scan.commit();
2348
- scanEnd = scan.end;
2660
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2349
2661
  } else {
2350
2662
  scanEnd = advanceTrivia(input, cur, ctx);
2351
2663
  }
2664
+ const scanTlog = cstTlLen(ctx);
2665
+ const scanLog = ctx._triviaLog?.length ?? 0;
2666
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2352
2667
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2353
2668
  if (!result2.ok) return result2;
2354
2669
  if (result2.span.end > scanEnd) cur = result2.span.end;
2355
- else rollbackTrivia(ctx, mark);
2670
+ else rollbackScannedTriviaAt(
2671
+ ctx,
2672
+ mTlog,
2673
+ scanTlog,
2674
+ mLog,
2675
+ scanLog,
2676
+ mRootLog,
2677
+ scanRootLog
2678
+ );
2356
2679
  if (values !== void 0) values.push(result2.value);
2357
2680
  continue;
2358
2681
  }
@@ -2383,18 +2706,29 @@ function sequence(...parsers) {
2383
2706
  }
2384
2707
  if (ctx.trivia && i > 0) {
2385
2708
  let scanEnd;
2386
- const mark = saveTriviaMark(ctx);
2709
+ const mTlog = cstTlLen(ctx);
2710
+ const mLog = ctx._triviaLog?.length ?? 0;
2711
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2387
2712
  if (needsDeferredTriviaCommit(ctx)) {
2388
- const scan = scanTrivia(input, cur, ctx);
2389
- scan.commit();
2390
- scanEnd = scan.end;
2713
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2391
2714
  } else {
2392
2715
  scanEnd = advanceTrivia(input, cur, ctx);
2393
2716
  }
2717
+ const scanTlog = cstTlLen(ctx);
2718
+ const scanLog = ctx._triviaLog?.length ?? 0;
2719
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2394
2720
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2395
2721
  if (!result2.ok) return result2;
2396
2722
  if (result2.span.end > scanEnd) cur = result2.span.end;
2397
- else rollbackTrivia(ctx, mark);
2723
+ else rollbackScannedTriviaAt(
2724
+ ctx,
2725
+ mTlog,
2726
+ scanTlog,
2727
+ mLog,
2728
+ scanLog,
2729
+ mRootLog,
2730
+ scanRootLog
2731
+ );
2398
2732
  if (values !== void 0) values.push(result2.value);
2399
2733
  continue;
2400
2734
  }
@@ -2422,20 +2756,31 @@ function sequence(...parsers) {
2422
2756
  for (let i = 0; i < parsers.length; i++) {
2423
2757
  if (ctx.trivia && i > 0) {
2424
2758
  let scanEnd;
2425
- let mark = saveTriviaMark(ctx);
2759
+ const mTlog = cstTlLen(ctx);
2760
+ const mLog = ctx._triviaLog?.length ?? 0;
2761
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2426
2762
  if (needsDeferredTriviaCommit(ctx)) {
2427
- const scan = scanTrivia(input, cur, ctx);
2428
- scan.commit();
2429
- scanEnd = scan.end;
2763
+ scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2430
2764
  } else {
2431
2765
  scanEnd = advanceTrivia(input, cur, ctx);
2432
2766
  }
2767
+ const scanTlog = cstTlLen(ctx);
2768
+ const scanLog = ctx._triviaLog?.length ?? 0;
2769
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2433
2770
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2434
2771
  if (!result2.ok) return result2;
2435
2772
  if (result2.span.end > scanEnd) {
2436
2773
  cur = result2.span.end;
2437
2774
  } else {
2438
- rollbackTrivia(ctx, mark);
2775
+ rollbackScannedTriviaAt(
2776
+ ctx,
2777
+ mTlog,
2778
+ scanTlog,
2779
+ mLog,
2780
+ scanLog,
2781
+ mRootLog,
2782
+ scanRootLog
2783
+ );
2439
2784
  }
2440
2785
  if (values !== void 0) values.push(result2.value);
2441
2786
  continue;
@@ -3133,9 +3478,7 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3133
3478
  let pos = cur;
3134
3479
  if (ctx.trivia) {
3135
3480
  if (needsDeferredTriviaCommit(ctx)) {
3136
- const scan = scanTrivia(input, cur, ctx);
3137
- scan.commit();
3138
- pos = scan.end;
3481
+ pos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3139
3482
  } else {
3140
3483
  pos = advanceTrivia(input, cur, ctx);
3141
3484
  }
@@ -3361,9 +3704,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3361
3704
  let sepPos = cur;
3362
3705
  if (ctx.trivia) {
3363
3706
  if (needsDeferredTriviaCommit(ctx)) {
3364
- const scan = scanTrivia(input, cur, ctx);
3365
- scan.commit();
3366
- sepPos = scan.end;
3707
+ sepPos = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3367
3708
  } else {
3368
3709
  sepPos = advanceTrivia(input, cur, ctx);
3369
3710
  }
@@ -3379,9 +3720,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3379
3720
  let nextPos = sep.span.end;
3380
3721
  if (ctx.trivia) {
3381
3722
  if (needsDeferredTriviaCommit(ctx)) {
3382
- const scan = scanTrivia(input, sep.span.end, ctx);
3383
- scan.commit();
3384
- nextPos = scan.end;
3723
+ nextPos = commitTriviaScan(scanTriviaCompact(input, sep.span.end, ctx));
3385
3724
  } else {
3386
3725
  nextPos = advanceTrivia(input, sep.span.end, ctx);
3387
3726
  }
@@ -3641,11 +3980,12 @@ function parser(opts, root) {
3641
3980
  const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
3642
3981
  const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
3643
3982
  const forceCaptureTrivia = opts.captureTrivia === true;
3644
- 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;
3645
3985
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
3646
3986
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
3647
3987
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
3648
- return {
3988
+ const grammar = {
3649
3989
  _tag: "grammar",
3650
3990
  _meta: {
3651
3991
  ...root._meta,
@@ -3664,7 +4004,9 @@ function parser(opts, root) {
3664
4004
  clearTrivia,
3665
4005
  ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
3666
4006
  ...opts.captureTrivia ? { captureTrivia: true } : {},
3667
- trackLines: opts.trackLines ?? false
4007
+ trackLines: opts.trackLines ?? false,
4008
+ constructionTrackLines: trackLinesPolicy,
4009
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
3668
4010
  },
3669
4011
  parse(input, pos, _ctx) {
3670
4012
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
@@ -3693,6 +4035,7 @@ function parser(opts, root) {
3693
4035
  return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
3694
4036
  }
3695
4037
  };
4038
+ return grammar;
3696
4039
  }
3697
4040
  function noTrivia(root) {
3698
4041
  return parser({ trivia: null }, root);
@@ -3952,7 +4295,11 @@ function not(combinator) {
3952
4295
  const result = combinator.parse(input, pos, ctx);
3953
4296
  rollbackLookahead(ctx, mark);
3954
4297
  if (result.ok) {
3955
- 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
+ };
3956
4303
  }
3957
4304
  return { ok: true, value: null, span: { start: pos, end: pos } };
3958
4305
  }
@@ -3976,7 +4323,11 @@ function peek(combinator) {
3976
4323
  const result = combinator.parse(input, pos, ctx);
3977
4324
  rollbackLookahead(ctx, mark);
3978
4325
  if (result.ok) return { ok: true, value: null, span: { start: pos, end: pos } };
3979
- 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
+ };
3980
4331
  }
3981
4332
  };
3982
4333
  }
@@ -4226,6 +4577,12 @@ function confirmedArityForDef(def) {
4226
4577
  });
4227
4578
  return null;
4228
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
+ }
4229
4586
  function buildReadsTrivia(def) {
4230
4587
  if (!def.build) return true;
4231
4588
  const arity = confirmedArityForDef(def);
@@ -5057,6 +5414,9 @@ var OP_LIVE = 37;
5057
5414
  var OP_ATTEMPT = 38;
5058
5415
  var OP_LABEL = 39;
5059
5416
  var OP_COV = 40;
5417
+ var OP_SCOPE_PLAIN = 41;
5418
+ var OP_LEX_BODY = 42;
5419
+ var OP_LEX_PROGRAM = 43;
5060
5420
  var OP_DISPATCH = 25;
5061
5421
  var OP_ROUTED = 26;
5062
5422
  var OP_NAMES = {
@@ -5099,9 +5459,391 @@ var OP_NAMES = {
5099
5459
  [OP_LIVE]: "LIVE",
5100
5460
  [OP_ATTEMPT]: "ATTEMPT",
5101
5461
  [OP_LABEL]: "LABEL",
5102
- [OP_COV]: "COV"
5462
+ [OP_COV]: "COV",
5463
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
5464
+ [OP_LEX_BODY]: "LEX_BODY",
5465
+ [OP_LEX_PROGRAM]: "LEX_PROGRAM"
5103
5466
  };
5104
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
+
5105
5847
  // src/table/program.ts
5106
5848
  function closureArtifact(prog) {
5107
5849
  return { ...prog, asm: [] };
@@ -5145,6 +5887,8 @@ function expandCompact(p) {
5145
5887
  fns: p.f,
5146
5888
  lines: p.l ?? 0,
5147
5889
  dsp: p.p ?? [],
5890
+ ...p.lx === void 0 ? {} : { lex: p.lx },
5891
+ ...p.lp === void 0 ? {} : { lexPrograms: p.lp },
5148
5892
  ...p.lb === void 0 ? {} : { labels: p.lb },
5149
5893
  ...p.rc === void 0 ? {} : { classified: p.rc },
5150
5894
  ...p.h === void 0 ? {} : { hostMode: p.h },
@@ -5157,6 +5901,15 @@ function expandCompact(p) {
5157
5901
  ...p.a === void 0 ? {} : { asm: p.a }
5158
5902
  });
5159
5903
  }
5904
+ function validateDispatchSpec(spec, arity, fallbackRouted) {
5905
+ const invalid = (arms) => {
5906
+ for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
5907
+ return false;
5908
+ };
5909
+ if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted !== 0 && fallbackRouted !== 1 || spec.routed.length !== arity || spec.routed.some((value) => value !== 0 && value !== 1) || invalid(spec.byKey.values()) || invalid(spec.byFold.values()) || spec.match.some((matcher) => invalid([matcher[3]]))) {
5910
+ throw new TypeError("table: malformed dispatch");
5911
+ }
5912
+ }
5160
5913
  var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
5161
5914
  function ownTableProgram(prog, resolved) {
5162
5915
  return { ...prog, [TABLE_RUNTIME]: { resolved } };
@@ -5227,7 +5980,7 @@ function resolveClass(spec) {
5227
5980
  }
5228
5981
  return { ascii, hi };
5229
5982
  }
5230
- function classHas(cls, code) {
5983
+ function classHas2(cls, code) {
5231
5984
  if (code < 0) return false;
5232
5985
  if (code < 128) return cls.ascii[code] === 1;
5233
5986
  const hi = cls.hi;
@@ -5280,6 +6033,7 @@ function resolveTable(prog) {
5280
6033
  if (hit !== void 0) return hit;
5281
6034
  const cc = prog.cc.map(resolveClass);
5282
6035
  const triviaBuilt = (prog.triviaSpecs ?? []).map(buildTrivia);
6036
+ const lex = (prog.lex ?? []).map((spec) => buildLexBodyRecognizer(spec, prog.k));
5283
6037
  const built = {
5284
6038
  prog,
5285
6039
  code: Int32Array.from(prog.code),
@@ -5298,13 +6052,377 @@ function resolveTable(prog) {
5298
6052
  routed: d.routed,
5299
6053
  expected: d.expected
5300
6054
  })),
6055
+ lex,
6056
+ lexPrograms: (prog.lexPrograms ?? []).map((spec) => buildLexProgramRunner(spec, lex, cc, prog.fx)),
5301
6057
  rules: prog.rules
5302
6058
  };
5303
6059
  if (owner !== void 0) owner.resolved = built;
5304
6060
  return built;
5305
6061
  }
5306
6062
 
5307
- // src/table/encode.ts
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;
6086
+ }
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
5308
6426
  function emittableConst(v) {
5309
6427
  const scalar = (x) => x === null || typeof x === "string" || typeof x === "number" || typeof x === "boolean";
5310
6428
  if (scalar(v) || v instanceof RegExp) return true;
@@ -5316,16 +6434,6 @@ function emittableConst(v) {
5316
6434
  }
5317
6435
  return false;
5318
6436
  }
5319
- function wrapsRef(winner, p) {
5320
- let cur = winner;
5321
- for (let n = 0; n < 16; n++) {
5322
- if (cur === p) return true;
5323
- const d = cur._def;
5324
- if (d.tag !== "grammar" && d.tag !== "trivia") return false;
5325
- cur = d.parser;
5326
- }
5327
- return false;
5328
- }
5329
6437
  var UnsupportedConstruct = class extends Error {
5330
6438
  tag;
5331
6439
  constructor(tag) {
@@ -5357,6 +6465,10 @@ var Encoder = class {
5357
6465
  fx = [];
5358
6466
  disp = [];
5359
6467
  dsp = [];
6468
+ lex = [];
6469
+ lexIndex = /* @__PURE__ */ new Map();
6470
+ lexPrograms = [];
6471
+ lexProgramIndex = /* @__PURE__ */ new Map();
5360
6472
  labels = void 0;
5361
6473
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
5362
6474
  activeTrivia = void 0;
@@ -5427,6 +6539,146 @@ var Encoder = class {
5427
6539
  this.triviaSpecs.push(this.triviaSpecOf(t));
5428
6540
  return idx;
5429
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
+ }
5430
6682
  triviaSpecOf(t) {
5431
6683
  const unlowered = (why) => {
5432
6684
  this.runtimeOnly.add(`rules({ trivia }) \u2014 ${why}`);
@@ -5510,6 +6762,9 @@ var Encoder = class {
5510
6762
  settings;
5511
6763
  /** Resolved once, HERE, at table-build time — never consulted at run time. */
5512
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;
5513
6768
  /**
5514
6769
  * Decides the extra operands laid down below. ALWAYS TRUE — see
5515
6770
  * `TableSettings.recovery`. Kept as a field rather than folded away because it
@@ -5517,9 +6772,10 @@ var Encoder = class {
5517
6772
  * row is stated.
5518
6773
  */
5519
6774
  rec;
5520
- constructor(settings) {
6775
+ constructor(settings, selectLexicalBodies) {
5521
6776
  this.settings = settings;
5522
6777
  this.track = settings.trackLines === true;
6778
+ this.selectLexicalBodies = selectLexicalBodies;
5523
6779
  this.rec = true;
5524
6780
  this.plan = settings.coverage;
5525
6781
  this.cov = settings.coverage === void 0 ? void 0 : settings.coverage.definitions.map((d) => [d.id, covKindCode(d.kind)]);
@@ -5634,6 +6890,13 @@ var Encoder = class {
5634
6890
  this.ccIndex.set(spec, i);
5635
6891
  return i;
5636
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
+ }
5637
6900
  /**
5638
6901
  * Wrap one choice arm in its `autoNot` checks (`OP_REJECT`).
5639
6902
  *
@@ -5715,14 +6978,14 @@ var Encoder = class {
5715
6978
  this.carryTriviaMeta(amb);
5716
6979
  this.carryTriviaMeta(p);
5717
6980
  if (p._def.tag === "grammar") this.carryTriviaMeta(p._def.triviaParser);
5718
- this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE, this.triviaSlot(amb), body);
6981
+ this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), body);
5719
6982
  }
5720
6983
  /**
5721
6984
  * The row a cross-rule `g.X` reference jumps to — the target's body, RE-WRAPPED
5722
6985
  * in the target rule's own ambient trivia when that differs from the trivia
5723
6986
  * lexically active at the reference.
5724
6987
  *
5725
- * `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`
5726
6989
  * reference resolves straight to the body's offset and jumps past it (the note
5727
6990
  * at `encodeRule`). So a rule referenced from inside a `noTrivia(...)` region ran
5728
6991
  * with NO ambient trivia of its own — the table scoped trivia DYNAMICALLY, by
@@ -5758,7 +7021,7 @@ var Encoder = class {
5758
7021
  const amb = p._meta.grammarTrivia ?? target._meta.grammarTrivia;
5759
7022
  if (amb === void 0 || this.activeTrivia !== void 0) return ip;
5760
7023
  if (!hasOwnTriviaBoundary(target)) return ip;
5761
- return this.emit(OP_SCOPE, this.triviaSlot(amb), ip);
7024
+ return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
5762
7025
  }
5763
7026
  node(p) {
5764
7027
  const lazyRef = p._def.tag === "lazy";
@@ -5799,6 +7062,19 @@ var Encoder = class {
5799
7062
  }
5800
7063
  encodeDef(p) {
5801
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
+ }
5802
7078
  const bal = p._balancedSpec;
5803
7079
  if (bal !== void 0) return this.emit(OP_SCAN, this.scanSlot({
5804
7080
  kind: 1,
@@ -5820,13 +7096,13 @@ var Encoder = class {
5820
7096
  switch (d.tag) {
5821
7097
  case "literal": {
5822
7098
  if (d.caseInsensitive) {
5823
- 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)));
5824
7100
  }
5825
- 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)));
5826
7102
  }
5827
7103
  case "regex": {
5828
7104
  const flags = d.flags.includes("y") ? d.flags : `${d.flags}y`;
5829
- 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)));
5830
7106
  }
5831
7107
  case "keywords": {
5832
7108
  const alt = d.words.map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
@@ -5840,7 +7116,7 @@ var Encoder = class {
5840
7116
  // failing keyword arm names the CATEGORY rather than reciting every
5841
7117
  // literal in the family. `deriveExpected` reports the literals, so the
5842
7118
  // table said `'"media"'` where both other engines say `'keyword'`.
5843
- this.expected(["keyword"])
7119
+ this.expected(directTerminalFailureExpected(d))
5844
7120
  );
5845
7121
  }
5846
7122
  case "expect": {
@@ -5887,7 +7163,8 @@ var Encoder = class {
5887
7163
  return this.covWrap(gated, armCovIds?.[src], 1);
5888
7164
  });
5889
7165
  const rr = this.refResolver();
5890
- 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]));
5891
7168
  const dispIdx = this.disp.length;
5892
7169
  this.disp.push(classes);
5893
7170
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
@@ -5903,9 +7180,11 @@ var Encoder = class {
5903
7180
  case "many":
5904
7181
  case "oneOrMore": {
5905
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));
5906
7185
  const op = d.valueUnused ? OP_REPV : OP_REP;
5907
7186
  const min = d.tag === "many" ? 0 : d.min;
5908
- 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);
5909
7188
  }
5910
7189
  case "sepBy": {
5911
7190
  const child = this.node(d.parser).ip;
@@ -5932,7 +7211,8 @@ var Encoder = class {
5932
7211
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
5933
7212
  const kids = inner.parsers.map((c) => this.node(c).ip);
5934
7213
  const head = this.emitHead(OP_SEQX, 2 + kids.length + (this.rec ? kids.length : 0));
5935
- 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;
5936
7216
  this.code[head + 2] = kids.length;
5937
7217
  for (let i = 0; i < kids.length; i++) this.code[head + 3 + i] = kids[i];
5938
7218
  if (this.rec) {
@@ -5953,10 +7233,11 @@ var Encoder = class {
5953
7233
  const cstOut = this.settings.hostMode === "cst";
5954
7234
  const noBuildCaptures = d.project === void 0;
5955
7235
  const derivedTrivia = d.build !== void 0 ? buildReadsTrivia(d) : noBuildCaptures;
7236
+ const omitsRaw = d.build !== void 0 && !buildReadsRaw(d);
5956
7237
  const derivedState = d.build !== void 0 ? buildReadsState(d) : noBuildCaptures;
5957
7238
  const derivedFields = d.build !== void 0 ? buildReadsFields(d) : noBuildCaptures;
5958
7239
  const wantsFields = parserHasOwnFields(d.parser) && (cstOut || derivedFields);
5959
- 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);
5960
7241
  const body = this.emit(
5961
7242
  this.track ? OP_NODE_TRACK : OP_NODE,
5962
7243
  d.build === void 0 ? -1 : this.fn(d.build, d.buildSrc ?? null),
@@ -5977,8 +7258,9 @@ var Encoder = class {
5977
7258
  const e = deriveExpected(d.parser);
5978
7259
  return this.emit(OP_GATE, cls, body, this.expected(e.length > 0 ? e : [d.parser._tag]));
5979
7260
  }
5980
- case "token":
7261
+ case "token": {
5981
7262
  return this.emit(OP_TOKEN, this.node(d.parser).ip);
7263
+ }
5982
7264
  case "routed":
5983
7265
  return this.emit(OP_ROUTED, d.fallback === void 0 ? -1 : this.node(d.fallback).ip);
5984
7266
  case "dispatch": {
@@ -6043,7 +7325,7 @@ var Encoder = class {
6043
7325
  case "lazy": {
6044
7326
  const refName = p._ruleName;
6045
7327
  const winner = refName === void 0 ? void 0 : this.winners?.[refName];
6046
- 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);
6047
7329
  let resolved;
6048
7330
  try {
6049
7331
  resolved = d.thunk();
@@ -6059,7 +7341,7 @@ var Encoder = class {
6059
7341
  // other engine reported `['not(literal)']`. It hid because `expected` is a
6060
7342
  // TOP-LEVEL field on `RunResult` and is NOT part of the identity digest.
6061
7343
  case "not":
6062
- 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)));
6063
7345
  case "guard":
6064
7346
  return this.emit(OP_GUARD, this.fn(d.predicate, d.predSrc ?? null), this.expected(["gate"]));
6065
7347
  case "adjacency":
@@ -6077,7 +7359,7 @@ var Encoder = class {
6077
7359
  return this.emit(OP_WITHCTX, this.constant(d.extra), this.node(d.parser).ip);
6078
7360
  }
6079
7361
  case "peek":
6080
- 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)));
6081
7363
  // A TRANSACTION IS A ROW. See `OP_ATTEMPT` for why the transparent
6082
7364
  // lowering was correct only for a choice arm.
6083
7365
  case "attempt": {
@@ -6163,6 +7445,7 @@ var Encoder = class {
6163
7445
  return [ip + 1];
6164
7446
  case OP_SCOPE:
6165
7447
  case OP_SCOPE_CAP:
7448
+ case OP_SCOPE_PLAIN:
6166
7449
  case OP_WITHCTX:
6167
7450
  case OP_XFORM:
6168
7451
  case OP_LEAF:
@@ -6237,6 +7520,8 @@ var Encoder = class {
6237
7520
  disp: this.disp,
6238
7521
  dsp: this.dsp,
6239
7522
  rules: this.rules,
7523
+ ...this.lex.length === 0 ? {} : { lex: this.lex },
7524
+ ...this.lexPrograms.length === 0 ? {} : { lexPrograms: this.lexPrograms },
6240
7525
  ...this.labels === void 0 ? {} : { labels: this.labels },
6241
7526
  ...this.classified ? { classified: 1 } : {},
6242
7527
  ...this.scanSkipSets.length === 0 ? {} : { scanSkip: this.scanSkipSets, scanSkipOf: this.scanSkipOf },
@@ -6291,7 +7576,11 @@ function encodeTableProgram(ruleMap, settings = {}) {
6291
7576
  ...hostMode === void 0 ? {} : { hostMode },
6292
7577
  ...track ? { trackLines: true } : {}
6293
7578
  };
6294
- 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);
6295
7584
  enc.winners = ruleMap;
6296
7585
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
6297
7586
  const prog = enc.finish();
@@ -7336,6 +8625,8 @@ function childSlots(code, ip, out) {
7336
8625
  case OP_GUARD:
7337
8626
  case OP_ADJ:
7338
8627
  case OP_LIVE:
8628
+ case OP_LEX_BODY:
8629
+ case OP_LEX_PROGRAM:
7339
8630
  return true;
7340
8631
  // Single child at `ip + 1`. `OP_COV` is a wrapper on the same footing as the
7341
8632
  // rest — a coverage-encoded program is a program, and omitting it made
@@ -7356,6 +8647,7 @@ function childSlots(code, ip, out) {
7356
8647
  case OP_GATE:
7357
8648
  case OP_SCOPE:
7358
8649
  case OP_SCOPE_CAP:
8650
+ case OP_SCOPE_PLAIN:
7359
8651
  case OP_WITHCTX:
7360
8652
  case OP_XFORM:
7361
8653
  case OP_NODE:
@@ -7444,7 +8736,7 @@ function reachableSites(code, roots) {
7444
8736
  }
7445
8737
  function transfer(code, ip, at, hostCst) {
7446
8738
  const op = code[ip];
7447
- if (op === OP_SCOPE || op === OP_SCOPE_CAP) {
8739
+ if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
7448
8740
  const ki = code[ip + 1];
7449
8741
  const tri = ki < 0 ? TRI_NONE : ki;
7450
8742
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
@@ -7452,7 +8744,12 @@ function transfer(code, ip, at, hostCst) {
7452
8744
  return { tri, buf: at.buf, cap };
7453
8745
  }
7454
8746
  if (op === OP_NODE || op === OP_NODE_TRACK) {
7455
- 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;
7456
8753
  if (at.buf && cap === at.cap) return at;
7457
8754
  return { tri: at.tri, buf: true, cap };
7458
8755
  }
@@ -7493,6 +8790,43 @@ function computeSiteLabels(code, roots, hostCst) {
7493
8790
  return { at: (ip) => labels.get(ip) ?? TOP };
7494
8791
  }
7495
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
+
7496
8830
  // src/table/emit-assembly.ts
7497
8831
  var Unemittable = class extends Error {
7498
8832
  construct;
@@ -7525,6 +8859,7 @@ var EMITTED_PARAMS = [
7525
8859
  "pushCstLeaf",
7526
8860
  "pushCstChild",
7527
8861
  "rollbackTriviaAt",
8862
+ "rollbackScannedTriviaAt",
7528
8863
  "failAt",
7529
8864
  "classHas",
7530
8865
  "consumeTrivia",
@@ -7553,7 +8888,19 @@ var EMITTED_PARAMS = [
7553
8888
  "matchesAt",
7554
8889
  "recoverScan",
7555
8890
  "orSentinel",
7556
- "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"
7557
8904
  ];
7558
8905
  var RUNTIME_PRELUDE = `
7559
8906
  let _pfScan=null
@@ -7564,7 +8911,7 @@ function _skipTrivia(input,cur,ctx){
7564
8911
  const s=_pfScan
7565
8912
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
7566
8913
  if(s!==null)return skipTriviaScanned(s,input,cur,ctx)
7567
- if(needsDeferredTriviaCommit(ctx)){const sc=scanTrivia(input,cur,ctx);sc.commit();return sc.end}
8914
+ if(needsDeferredTriviaCommit(ctx))return commitTriviaScan(scanTriviaCompact(input,cur,ctx))
7568
8915
  return advanceTrivia(input,cur,ctx)
7569
8916
  }
7570
8917
  function _pushLeaf(ctx,value,s,e){pushCstLeaf(ctx,{_tag:'leaf',value,span:{start:s,end:e}})}
@@ -7578,6 +8925,13 @@ if(b.raw!==undefined)b.raw.push(l)
7578
8925
  else if(b.rawSingle!==undefined){b.raw=[b.rawSingle,l];b.rawSingle=undefined}
7579
8926
  else b.rawSingle=l
7580
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
+ }
7581
8935
  function _accSet(ax,acc){
7582
8936
  if(ax===undefined||ax.length===0)return acc
7583
8937
  if(acc===undefined)return ax.slice()
@@ -7668,19 +9022,24 @@ if(ctx._errors!==undefined&&ctx._errors.length!==${t}er)ctx._errors.length=${t}e
7668
9022
  if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,0,undefined,${t}lg,${t}rt)`;
7669
9023
  return `if(${t}n){rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "0"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)}`;
7670
9024
  }
7671
- function emitTerm(callee, dst, t, l, skip, s) {
9025
+ function emitTerm(callee, dst, t, l, skip) {
7672
9026
  const fast = `const ${t}v=${callee}(input,cur,ctx)
7673
9027
  if(${t}v===FAIL)return FAIL
7674
9028
  ${dst}=${t}v
7675
9029
  cur=EC.e`;
7676
9030
  if (l.tri === TRI_NONE) return fast;
7677
- const scanned = `${emitMark(t, l.buf, s)}
9031
+ const scanned = `const ${t}tl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
9032
+ const ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
9033
+ const ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7678
9034
  const ${t}s=${skip}(input,cur,ctx)
9035
+ const ${t}stl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
9036
+ const ${t}slg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
9037
+ const ${t}srt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7679
9038
  const ${t}v=${callee}(input,${t}s,ctx)
7680
9039
  if(${t}v===FAIL)return FAIL
7681
9040
  ${dst}=${t}v
7682
9041
  if(EC.e>${t}s)cur=EC.e
7683
- else{${emitRollback(t, l.buf, s)}}`;
9042
+ else{rollbackScannedTriviaAt(ctx,${t}tl,${t}stl,${t}lg,${t}slg,${t}rt,${t}srt)}`;
7684
9043
  if (l.tri !== TRI_UNKNOWN) return scanned;
7685
9044
  return `if(ctx.trivia===undefined){
7686
9045
  ${fast}
@@ -7707,12 +9066,16 @@ function maskForClassRow(gates) {
7707
9066
  }
7708
9067
  return m;
7709
9068
  }
7710
- function rebuildPools(cc, fx, plan) {
9069
+ function rebuildPools(cc, fx, disp, plan) {
7711
9070
  const classes = plan.classes.map((row) => row.map((i) => i < 0 ? null : cc[i] ?? null));
7712
9071
  return {
7713
9072
  classes,
7714
9073
  armExpected: plan.armExpected.map((row) => row.map((i) => fx[i] ?? [])),
7715
- 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
+ })
7716
9079
  };
7717
9080
  }
7718
9081
  function emitAssemblySource(t, prog, cfg, extraIps = []) {
@@ -7723,6 +9086,14 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7723
9086
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
7724
9087
  const roots = [...Object.values(prog.rules), ...extraIps];
7725
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
+ }
7726
9097
  const sinks = (() => {
7727
9098
  let fd = false;
7728
9099
  let er = REC2;
@@ -7743,6 +9114,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7743
9114
  const reached = /* @__PURE__ */ new Set();
7744
9115
  const prelude = [];
7745
9116
  const skipDefs = [];
9117
+ const choiceDefs = [];
7746
9118
  const skipPool = /* @__PURE__ */ new Map();
7747
9119
  const pool = /* @__PURE__ */ new Map();
7748
9120
  const masks = [];
@@ -7762,6 +9134,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7762
9134
  const kRef = (i) => hoist("k", `K[${i}]`);
7763
9135
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
7764
9136
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
9137
+ const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
7765
9138
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
7766
9139
  let uid = 0;
7767
9140
  const tmp = () => `_t${uid++}_`;
@@ -7775,8 +9148,8 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
7775
9148
  const nm = `_sk${skipPool.size}`;
7776
9149
  skipPool.set(key, nm);
7777
9150
  if (!hasScan) {
7778
- 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){
7779
- 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))
7780
9153
  return advanceTrivia(input,cur,ctx)}`);
7781
9154
  return nm;
7782
9155
  }
@@ -7843,7 +9216,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7843
9216
  const op = code[ip];
7844
9217
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
7845
9218
  if (op === OP_RULE) return code[ip + 1];
7846
- if (op === OP_SCOPE && code[ip + 3] === 0 && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
9219
+ if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
7847
9220
  return code[ip + 2];
7848
9221
  }
7849
9222
  return void 0;
@@ -7863,6 +9236,19 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7863
9236
  const s = k[code[ip + 1]];
7864
9237
  const xf = fxRef(code[ip + 2]);
7865
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
+ }
7866
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)`;
7867
9253
  return `${head}
7868
9254
  if(${test}){
@@ -7912,6 +9298,20 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7912
9298
  case OP_RX_TRACK: {
7913
9299
  const xf = fxRef(code[ip + 2]);
7914
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
+ }
7915
9315
  const scanned = emitScan(code[ip + 1], xf, track, captureLeaf);
7916
9316
  if (scanned !== void 0) return `${head}${scanned}}`;
7917
9317
  const rxk = k[code[ip + 1]];
@@ -8011,10 +9411,11 @@ return r.value
8011
9411
  }`;
8012
9412
  }
8013
9413
  case OP_SCOPE:
8014
- case OP_SCOPE_CAP: {
9414
+ case OP_SCOPE_CAP:
9415
+ case OP_SCOPE_PLAIN: {
8015
9416
  const ki = code[ip + 1];
8016
9417
  const cap = op === OP_SCOPE_CAP;
8017
- const flags = code[ip + 3];
9418
+ const flags = op === OP_SCOPE_PLAIN ? 0 : code[ip + 3];
8018
9419
  const child = link(code[ip + 2]);
8019
9420
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
8020
9421
  const tri = ki < 0 ? "undefined" : hoist("tv", `TRIVIA[${ki}]`);
@@ -8072,6 +9473,73 @@ const out=${isToken ? "input.slice(pos,e)" : `${fn}(v,{start:pos,end:e})`}
8072
9473
  if(wasCap)pushCstLeaf(ctx,{_tag:'leaf',value:out,span:{start:pos,end:e}})
8073
9474
  EC.e=e
8074
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
8075
9543
  }`;
8076
9544
  }
8077
9545
  /* ── transaction ─────────────────────────────────────────────────────── */
@@ -8089,6 +9557,18 @@ return FAIL
8089
9557
  }`;
8090
9558
  }
8091
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
+ }
8092
9572
  const child = link(code[ip + 1]);
8093
9573
  const xf = fxRef(code[ip + 2]);
8094
9574
  const p = tmp();
@@ -8138,14 +9618,14 @@ return v
8138
9618
  const base = fused ? ip + 3 : ip + 2;
8139
9619
  const n = code[fused ? ip + 2 : ip + 1];
8140
9620
  const wantValues = op !== OP_SEQV;
8141
- for (let i = 1; i < n; i++) {
8142
- if (code[code[base + i]] === OP_ADJ) {
8143
- throw new Unemittable("a sequence carrying an adjacency assertion (OP_ADJ)");
8144
- }
8145
- }
8146
- 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;
8147
9624
  const kids = [];
8148
- 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
+ }
8149
9629
  const sy = REC2 ? `${tmp()}sy` : "";
8150
9630
  const pub = (i) => {
8151
9631
  const s = sentRef(code[base + n + i]);
@@ -8159,7 +9639,7 @@ return v
8159
9639
  }` : `${parts.join("\n")}
8160
9640
  }`;
8161
9641
  if (n === 1) {
8162
- 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");
8163
9643
  return close();
8164
9644
  }
8165
9645
  parts.push("let cur=EC.e");
@@ -8168,11 +9648,21 @@ return v
8168
9648
  const vn = `v${i}`;
8169
9649
  parts.push(`let ${vn}`);
8170
9650
  if (REC2) parts.push(pub(i));
8171
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L), sinks));
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)));
8172
9662
  names.push(vn);
8173
9663
  }
8174
9664
  parts.push("EC.e=cur");
8175
- 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");
8176
9666
  return close();
8177
9667
  }
8178
9668
  case OP_CHOICE: {
@@ -8182,11 +9672,6 @@ return v
8182
9672
  const base = ip + 4;
8183
9673
  const arms = [];
8184
9674
  for (let i = 0; i < n; i++) arms.push(link(code[base + i]));
8185
- const axi = armExpected.push(
8186
- Array.from({ length: n }, (_, i) => t.fx[code[base + n + i]])
8187
- ) - 1;
8188
- armExpectedPlan.push(Array.from({ length: n }, (_, i) => code[base + n + i]));
8189
- const afx = hoist("afx", `AFX[${axi}]`);
8190
9675
  if (table.exclusive) {
8191
9676
  const di = code[ip + 1];
8192
9677
  const asc = hoist("as", `DISP[${di}].ascii`);
@@ -8213,38 +9698,43 @@ ctx._fe=pos;ctx._fx=${choiceFx}
8213
9698
  return FAIL
8214
9699
  }`;
8215
9700
  }
8216
- const ci = classes.push(Array.from({ length: n }, (_, i) => table.armCls[i] ?? null)) - 1;
8217
- classPlan.push(Array.from({ length: n }, (_, i) => prog.disp[code[ip + 1]][i] ?? -1));
8218
- const gates = classes[ci];
8219
- const gRef = hoist("g", `CLS[${ci}]`);
8220
- const maskable = n <= 32;
8221
- let maskName = "";
8222
- if (maskable) {
8223
- maskName = hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`);
8224
- maskPlan.push(ci);
8225
- }
8226
- const p = tmp();
8227
- const maskArms = arms.map((a, i) => `
8228
- 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){
8229
9719
  ctx._fc=false
8230
- {const v=${a}(input,pos,ctx)
9720
+ {const v=${arm}(input,pos,ctx)
8231
9721
  if(v!==FAIL)return v}
8232
- for(let j=prev;j<${i};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9722
+ acc=${catchName}(${i},prev,acc)
8233
9723
  prev=${i + 1}
8234
9724
  acc=_accSet(ctx._fx,acc)
8235
9725
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8236
9726
  ${emitRollback(p, L.buf, sinks)}
8237
- }`).join("");
8238
- const generalArms = arms.map((a, i) => `
8239
- 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)){
8240
9730
  ctx._fc=false
8241
- {const v=${a}(input,pos,ctx)
9731
+ {const v=${arm}(input,pos,ctx)
8242
9732
  if(v!==FAIL)return v}
8243
9733
  acc=_accSet(ctx._fx,acc)
8244
9734
  if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
8245
9735
  ${emitRollback(p, L.buf, sinks)}
8246
- }else acc=_accSet(${afx}[${i}],acc)`).join("");
8247
- return `${head}
9736
+ }else acc=_accSet(${expected[i]},acc)`).join("\n");
9737
+ return `${head}
8248
9738
  const c=lead(input,pos)
8249
9739
  ${emitMark(p, L.buf, sinks)}
8250
9740
  let acc
@@ -8252,14 +9742,16 @@ ${maskable ? `if(c<128){
8252
9742
  const bits=${maskName}[c<0?128:c]
8253
9743
  let prev=0
8254
9744
  ${maskArms}
8255
- for(let j=prev;j<${n};j++)if((bits&(1<<j))===0)acc=_accSet(${afx}[j],acc)
9745
+ acc=${catchName}(${n},prev,acc)
8256
9746
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
8257
9747
  return FAIL
8258
9748
  }
8259
- ` : ""}${generalArms}
9749
+ ` : ""}
9750
+ ${generalArms}
8260
9751
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
8261
9752
  return FAIL
8262
9753
  }`;
9754
+ }
8263
9755
  }
8264
9756
  case OP_DISPATCH: {
8265
9757
  const di = code[ip + 2];
@@ -8269,11 +9761,11 @@ return FAIL
8269
9761
  const other = otherIp >= 0 ? link(otherIp) : void 0;
8270
9762
  const otherRouted = code[ip + 4] === 1;
8271
9763
  const n = code[ip + 5];
9764
+ validateDispatchSpec(spec, n, code[ip + 4]);
8272
9765
  const armBase = ip + 6;
8273
9766
  const arms = [];
8274
9767
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
8275
9768
  const bk = hoist("bk", `DSP[${di}].byKey`);
8276
- const rt = hoist("rt", `DSP[${di}].routed`);
8277
9769
  const dx = hoist("dx", `DSP[${di}].expected`);
8278
9770
  const claims = (m) => {
8279
9771
  switch (m[0]) {
@@ -8285,8 +9777,16 @@ return FAIL
8285
9777
  return `asciiFoldKey(key).startsWith(${q(m[1])})`;
8286
9778
  case 4:
8287
9779
  return `asciiFoldKey(key).endsWith(${q(m[1])})`;
8288
- 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
+ }
8289
9788
  return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
9789
+ }
8290
9790
  }
8291
9791
  };
8292
9792
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
@@ -8297,6 +9797,15 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
8297
9797
  ` : "";
8298
9798
  const m1 = tmp();
8299
9799
  const m2 = tmp();
9800
+ const routedCall = (target) => `{const savedRouted=ctx._routed
9801
+ ${emitRollback(m1, L.buf, sinks)}
9802
+ ${emitMark(m2, L.buf, sinks, false)}
9803
+ ctx._routed={value:key,span:{start:pos,end:selEnd}}
9804
+ try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
9805
+ break}`;
9806
+ const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
9807
+ const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
9808
+ const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
8300
9809
  return `${head}
8301
9810
  ${emitMark(m1, L.buf, sinks)}
8302
9811
  const sv=${selector}(input,pos,ctx)
@@ -8304,24 +9813,16 @@ if(sv===FAIL)return FAIL
8304
9813
  const selEnd=EC.e
8305
9814
  const key=sv
8306
9815
  let arm=${bk}.get(key)
8307
- ${fold}${chain}let ur
9816
+ ${fold}${chain}
8308
9817
  if(arm===undefined){
8309
- ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : `ur=${String(otherRouted)}`}
8310
- }else ur=${rt}[arm]===1
8311
- const savedRouted=ctx._routed
8312
- ${emitMark(m2, L.buf, sinks)}
8313
- if(ur){
8314
- ${emitRollback(m1, L.buf, sinks)}
8315
- ${emitMark(m2, L.buf, sinks, false)}
8316
- ctx._routed={value:key,span:{start:pos,end:selEnd}}
9818
+ ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
8317
9819
  }
8318
- const at=ur?pos:selEnd
9820
+ ${emitMark(m2, L.buf, sinks)}
8319
9821
  let v
8320
9822
  switch(arm){
8321
- ${arms.map((a, i) => `case ${i}:v=${a}(input,at,ctx);break`).join("\n")}
8322
- ${other === void 0 ? "" : `default:v=${other}(input,at,ctx)`}
9823
+ ${armCases}
9824
+ ${fallbackCase}
8323
9825
  }
8324
- if(ur)ctx._routed=savedRouted
8325
9826
  if(v===FAIL){
8326
9827
  ${emitRollback(m2, L.buf, sinks)}
8327
9828
  ctx._fc=true
@@ -8343,6 +9844,15 @@ return [key,v]
8343
9844
  const reportItem = (flags & 4) !== 0;
8344
9845
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
8345
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
+ }
8346
9856
  const skipBeforeFirst = sepIp < 0 && min === 0;
8347
9857
  const p = tmp();
8348
9858
  const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -8350,7 +9860,6 @@ return [key,v]
8350
9860
  const skip = skipFor(L);
8351
9861
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
8352
9862
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
8353
- const needMark = L.buf ? "true" : "needMark";
8354
9863
  const pfd = sinks.fd ? `${p}fd` : "0";
8355
9864
  const per = sinks.er ? `${p}er` : "undefined";
8356
9865
  const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
@@ -8395,11 +9904,13 @@ continue
8395
9904
  return `${head}
8396
9905
  const out=${collect ? "[]" : "undefined"}
8397
9906
  ${knownTrivia === void 0 ? "const hasTrivia=ctx.trivia!==undefined\n" : ""}${L.buf ? "" : "const needMark=_rollbackNeeded(ctx)\n"}${REC2 ? `const ${my}=ctx._sync
8398
- ` : ""}let cur=pos
9907
+ ` : ""}${itemCls === void 0 ? "" : `const ${p}gate=ctx._probe===undefined
9908
+ `}let cur=pos
8399
9909
  let count=0
8400
9910
  for(;;){
8401
9911
  ${max >= 0 ? `if(count>=${max})break
8402
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
8403
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` : ""}
8404
9915
  ${markBody}
8405
9916
  let itemStart=cur
@@ -8424,7 +9935,11 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
8424
9935
  ${rb}
8425
9936
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
8426
9937
  }
8427
- 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
8428
9943
  const v=${child}(input,itemStart,ctx)
8429
9944
  if(v===FAIL){
8430
9945
  ${REC2 ? `if(ctx._fc===true){
@@ -8453,6 +9968,26 @@ return out
8453
9968
  case OP_NODE:
8454
9969
  case OP_NODE_TRACK: {
8455
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
+ }
8456
9991
  const child = link(code[ip + 2]);
8457
9992
  const proj = code[ip + 4];
8458
9993
  const buildIdx = code[ip + 1];
@@ -8467,6 +10002,51 @@ return out
8467
10002
  const unwrap = (flags & 64) !== 0;
8468
10003
  const trailingTrivia = (flags & 128) !== 0;
8469
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
+ }
8470
10050
  const structural = build === void 0 && proj < 0;
8471
10051
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
8472
10052
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -8552,6 +10132,7 @@ return nd
8552
10132
  const source = `${RUNTIME_PRELUDE}
8553
10133
  ${prelude.join("\n")}
8554
10134
  ${skipDefs.join("\n")}
10135
+ ${choiceDefs.join("\n")}
8555
10136
  ${bodies.join("\n")}
8556
10137
  function _begin(ctx){
8557
10138
  const host=ctx.build
@@ -8792,12 +10373,12 @@ function reachableIps(prog) {
8792
10373
 
8793
10374
  // src/table/stamp.ts
8794
10375
  var EMPTY_FX = [];
8795
- function committed(c) {
10376
+ function committed2(c) {
8796
10377
  return c._fc === true;
8797
10378
  }
8798
10379
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
8799
10380
  const triviaOfRule = (ip) => {
8800
- if (prog.code[ip] !== OP_SCOPE) return void 0;
10381
+ if (prog.code[ip] !== OP_SCOPE_PLAIN && prog.code[ip] !== OP_SCOPE) return void 0;
8801
10382
  const slot = prog.code[ip + 1];
8802
10383
  return slot < 0 ? void 0 : resolved.trivia[slot];
8803
10384
  };
@@ -8842,7 +10423,7 @@ function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(pr
8842
10423
  const fe = ctx._fe;
8843
10424
  const at = fe === void 0 || fe < 0 ? pos : fe;
8844
10425
  const fspan = lines ? spanLines(ctx, at, at) : { start: at, end: at };
8845
- 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 };
8846
10427
  }
8847
10428
  return { ok: true, value: d.lastValue(), span: lines ? spanLines(ctx, pos, end) : { start: pos, end } };
8848
10429
  };
@@ -8888,11 +10469,15 @@ function linkMatcher(m) {
8888
10469
  return (key) => asciiFoldKey(key).startsWith(value);
8889
10470
  case 4:
8890
10471
  return (key) => asciiFoldKey(key).endsWith(value);
8891
- // A fresh RegExp per test, as `matchesDispatchMatcher` builds — a cached one
8892
- // would carry `lastIndex` across parses whenever the author's pattern was
8893
- // sticky or global.
8894
10472
  default: {
8895
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
+ }
8896
10481
  return (key) => new RegExp(value, flags).test(key);
8897
10482
  }
8898
10483
  }
@@ -8923,6 +10508,17 @@ function assemble(t, prog, cfg) {
8923
10508
  return made;
8924
10509
  }
8925
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
+ }
8926
10522
  let SCAN = null;
8927
10523
  const memo = /* @__PURE__ */ new Map();
8928
10524
  const reached = /* @__PURE__ */ new Set();
@@ -8930,10 +10526,238 @@ function assemble(t, prog, cfg) {
8930
10526
  const lf = { _tag: "leaf", value, span: { start: s, end: e } };
8931
10527
  pushCstLeaf(ctx, lf);
8932
10528
  }
8933
- function rollbackNeeded(ctx) {
8934
- 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
+ };
8935
10566
  }
8936
- let MRAW = 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;
8937
10761
  let MTL = 0;
8938
10762
  let MLV = 0;
8939
10763
  function markCst(ctx) {
@@ -8986,9 +10810,7 @@ function assemble(t, prog, cfg) {
8986
10810
  }
8987
10811
  if (s !== null) return skipTriviaScanned(s, input, cur, ctx);
8988
10812
  if (needsDeferredTriviaCommit(ctx)) {
8989
- const scan = scanTrivia(input, cur, ctx);
8990
- scan.commit();
8991
- return scan.end;
10813
+ return commitTriviaScan(scanTriviaCompact(input, cur, ctx));
8992
10814
  }
8993
10815
  return advanceTrivia(input, cur, ctx);
8994
10816
  }
@@ -9011,23 +10833,22 @@ function assemble(t, prog, cfg) {
9011
10833
  TERMV = v2;
9012
10834
  return EC.e > scanEnd2 ? EC.e : cur;
9013
10835
  }
9014
- const need = markCst(ctx);
9015
- const mRaw = MRAW;
9016
- const mTl = MTL;
9017
- const mLv = MLV;
9018
- const mFl = need ? ctx._fields?.length ?? 0 : 0;
9019
- const mEr = need ? ctx._errors?.length ?? 0 : 0;
10836
+ const need = rollbackNeeded(ctx);
10837
+ const mTl = need ? cstTlLen(ctx) : 0;
9020
10838
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9021
10839
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9022
10840
  const scanEnd = skipTrivia(input, cur, ctx);
10841
+ const scanTl = need ? cstTlLen(ctx) : 0;
10842
+ const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10843
+ const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9023
10844
  const v = child(input, scanEnd, ctx);
9024
10845
  if (v === FAIL) return -1;
9025
10846
  TERMV = v;
9026
10847
  if (EC.e > scanEnd) return EC.e;
9027
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10848
+ if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
9028
10849
  return cur;
9029
10850
  }
9030
- function committed2(c) {
10851
+ function committed3(c) {
9031
10852
  return c._fc === true;
9032
10853
  }
9033
10854
  function accSet(ax, acc) {
@@ -9036,6 +10857,207 @@ function assemble(t, prog, cfg) {
9036
10857
  for (const s of ax) acc.push(s);
9037
10858
  return acc;
9038
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
+ }
9039
11061
  function trackLinesInto(ctx, input, end) {
9040
11062
  const from = ctx._lineScannedTo ?? 0;
9041
11063
  if (end <= from) return;
@@ -9071,6 +11093,21 @@ function assemble(t, prog, cfg) {
9071
11093
  const s = k[code[ip + 1]];
9072
11094
  const len = s.length;
9073
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
+ }
9074
11111
  if (len === 1) {
9075
11112
  const c0 = s.charCodeAt(0);
9076
11113
  return (input, pos, ctx) => {
@@ -9198,6 +11235,22 @@ function assemble(t, prog, cfg) {
9198
11235
  case OP_RX: {
9199
11236
  const re = k[code[ip + 1]];
9200
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
+ }
9201
11254
  return (input, pos, ctx) => {
9202
11255
  re.lastIndex = pos;
9203
11256
  if (re.test(input)) {
@@ -9307,7 +11360,7 @@ function assemble(t, prog, cfg) {
9307
11360
  const child = link(code[ip + 2]);
9308
11361
  if (cfg.tolerant || cfg.probe) return child;
9309
11362
  return (input, pos, ctx) => {
9310
- if (!classHas(cls, lead(input, pos))) {
11363
+ if (!classHas2(cls, lead(input, pos))) {
9311
11364
  ctx._fe = pos;
9312
11365
  ctx._fx = xf;
9313
11366
  return FAIL;
@@ -9438,7 +11491,8 @@ function assemble(t, prog, cfg) {
9438
11491
  };
9439
11492
  }
9440
11493
  case OP_SCOPE:
9441
- case OP_SCOPE_CAP: {
11494
+ case OP_SCOPE_CAP:
11495
+ case OP_SCOPE_PLAIN: {
9442
11496
  const ki = code[ip + 1];
9443
11497
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
9444
11498
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
@@ -9472,7 +11526,7 @@ function assemble(t, prog, cfg) {
9472
11526
  SCAN = savedScan;
9473
11527
  return v;
9474
11528
  };
9475
- return scopeRootPolicy(scopePiece, code[ip + 3]);
11529
+ return scopeRootPolicy(scopePiece, code[ip] === OP_SCOPE_PLAIN ? 0 : code[ip + 3]);
9476
11530
  }
9477
11531
  case OP_ROUTED: {
9478
11532
  const fb = code[ip + 1];
@@ -9505,13 +11559,28 @@ function assemble(t, prog, cfg) {
9505
11559
  const v = child(input, pos, ctx);
9506
11560
  if (v !== FAIL) return v;
9507
11561
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9508
- if (committed2(ctx)) return FAIL;
11562
+ if (committed3(ctx)) return FAIL;
9509
11563
  ctx._fe = pos;
9510
11564
  return FAIL;
9511
11565
  };
9512
11566
  }
9513
11567
  /* ── zero-width ──────────────────────────────────────────────────────── */
9514
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
+ }
9515
11584
  const child = link(code[ip + 1]);
9516
11585
  const xf = fx[code[ip + 2]];
9517
11586
  return (input, pos, ctx) => {
@@ -9571,7 +11640,7 @@ function assemble(t, prog, cfg) {
9571
11640
  ctx._fc = false;
9572
11641
  const v = child(input, pos, ctx);
9573
11642
  if (v === FAIL) {
9574
- if (committed2(ctx)) return FAIL;
11643
+ if (committed3(ctx)) return FAIL;
9575
11644
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9576
11645
  EC.e = pos;
9577
11646
  return null;
@@ -9622,6 +11691,92 @@ function assemble(t, prog, cfg) {
9622
11691
  return value;
9623
11692
  };
9624
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
+ }
9625
11780
  case OP_LEAF: {
9626
11781
  const fn = fns[code[ip + 1]];
9627
11782
  const child = link(code[ip + 2]);
@@ -9662,38 +11817,73 @@ function assemble(t, prog, cfg) {
9662
11817
  const fused = op === OP_SEQX;
9663
11818
  const base = fused ? ip + 3 : ip + 2;
9664
11819
  const n = code[fused ? ip + 2 : ip + 1];
9665
- const kids = new Array(n);
9666
- for (let i = 0; i < n; i++) kids[i] = link(code[base + i]);
9667
11820
  const wantValues = op !== OP_SEQV;
9668
- const fn = fused ? fns[code[ip + 1]] : void 0;
9669
- const runTerms = (input, pos, ctx, values) => {
9670
- const v0 = kids[0](input, pos, ctx);
9671
- if (v0 === FAIL) return -1;
9672
- if (values !== void 0) values.push(v0);
9673
- let cur = EC.e;
9674
- for (let i = 1; i < n; i++) {
9675
- 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);
9676
11827
  if (cur < 0) return -1;
9677
11828
  if (values !== void 0) values.push(TERMV);
9678
- }
9679
- 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
+ };
9680
11867
  };
9681
11868
  if (REC2) {
9682
- const syncs = new Array(n);
9683
- for (let i = 0; i < n; i++) syncs[i] = sentinelFor(code[base + n + i]);
9684
- const runners = new Array(n);
9685
- 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]);
9686
11873
  const kidIp = code[base + i];
9687
11874
  if (code[kidIp] !== OP_ADJ) {
9688
- const kid = kids[i];
9689
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9690
- 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
+ };
9691
11880
  }
9692
11881
  const negated = code[kidIp + 1] === 1;
9693
11882
  const ki = code[kidIp + 2];
9694
11883
  const kinds = ki < 0 ? void 0 : k[ki];
9695
11884
  const xf = fx[code[kidIp + 3]];
9696
- runners[i] = (input, cur, ctx) => {
11885
+ return (input, cur, ctx, inherited) => {
11886
+ ctx._sync = sync ?? inherited;
9697
11887
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9698
11888
  ctx._fe = cur;
9699
11889
  ctx._fx = xf;
@@ -9702,25 +11892,34 @@ function assemble(t, prog, cfg) {
9702
11892
  TERMV = null;
9703
11893
  return cur;
9704
11894
  };
9705
- }
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;
9706
11910
  const runSyncTerms = (input, pos, ctx, values) => {
9707
11911
  const inherited = ctx._sync;
9708
- ctx._sync = syncs[0] ?? inherited;
9709
- const v0 = kids[0](input, pos, ctx);
11912
+ ctx._sync = firstSync ?? inherited;
11913
+ const v0 = first2(input, pos, ctx);
9710
11914
  if (v0 === FAIL) {
9711
11915
  ctx._sync = inherited;
9712
11916
  return -1;
9713
11917
  }
9714
11918
  if (values !== void 0) values.push(v0);
9715
- let cur = EC.e;
9716
- for (let i = 1; i < n; i++) {
9717
- ctx._sync = syncs[i] ?? inherited;
9718
- cur = runners[i](input, cur, ctx);
9719
- if (cur < 0) {
9720
- ctx._sync = inherited;
9721
- return -1;
9722
- }
9723
- 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;
9724
11923
  }
9725
11924
  ctx._sync = inherited;
9726
11925
  return cur;
@@ -9731,7 +11930,7 @@ function assemble(t, prog, cfg) {
9731
11930
  const cur = runSyncTerms(input, pos, ctx, values);
9732
11931
  if (cur < 0) return FAIL;
9733
11932
  EC.e = cur;
9734
- return fn(values, { start: pos, end: cur });
11933
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9735
11934
  };
9736
11935
  }
9737
11936
  if (wantValues) {
@@ -9756,19 +11955,18 @@ function assemble(t, prog, cfg) {
9756
11955
  break;
9757
11956
  }
9758
11957
  if (hasAdj) {
9759
- const runners = new Array(n);
9760
- for (let i = 1; i < n; i++) {
11958
+ const first2 = link(code[base]);
11959
+ const runnerAt = (i) => {
9761
11960
  const kidIp = code[base + i];
9762
11961
  if (code[kidIp] !== OP_ADJ) {
9763
- const kid = kids[i];
9764
- runners[i] = (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9765
- continue;
11962
+ const kid = link(kidIp);
11963
+ return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
9766
11964
  }
9767
11965
  const negated = code[kidIp + 1] === 1;
9768
11966
  const ki = code[kidIp + 2];
9769
11967
  const kinds = ki < 0 ? void 0 : k[ki];
9770
11968
  const xf = fx[code[kidIp + 3]];
9771
- runners[i] = (input, cur, ctx) => {
11969
+ return (input, cur, ctx) => {
9772
11970
  if (!adjacencyHolds(input, cur, ctx, negated, kinds)) {
9773
11971
  ctx._fe = cur;
9774
11972
  ctx._fx = xf;
@@ -9777,18 +11975,26 @@ function assemble(t, prog, cfg) {
9777
11975
  TERMV = null;
9778
11976
  return cur;
9779
11977
  };
9780
- }
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);
9781
11993
  const runAdjTerms = (input, pos, ctx, values) => {
9782
- const v0 = kids[0](input, pos, ctx);
11994
+ const v0 = first2(input, pos, ctx);
9783
11995
  if (v0 === FAIL) return -1;
9784
11996
  if (values !== void 0) values.push(v0);
9785
- let cur = EC.e;
9786
- for (let i = 1; i < n; i++) {
9787
- cur = runners[i](input, cur, ctx);
9788
- if (cur < 0) return -1;
9789
- if (values !== void 0) values.push(TERMV);
9790
- }
9791
- return cur;
11997
+ return tail2(input, EC.e, ctx, values);
9792
11998
  };
9793
11999
  if (fused) {
9794
12000
  return (input, pos, ctx) => {
@@ -9796,7 +12002,7 @@ function assemble(t, prog, cfg) {
9796
12002
  const cur = runAdjTerms(input, pos, ctx, values);
9797
12003
  if (cur < 0) return FAIL;
9798
12004
  EC.e = cur;
9799
- return fn(values, { start: pos, end: cur });
12005
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9800
12006
  };
9801
12007
  }
9802
12008
  if (wantValues) {
@@ -9816,12 +12022,12 @@ function assemble(t, prog, cfg) {
9816
12022
  };
9817
12023
  }
9818
12024
  if (n === 1) {
9819
- const k0 = kids[0];
12025
+ const k0 = link(code[base]);
9820
12026
  if (fused) {
9821
12027
  return (input, pos, ctx) => {
9822
12028
  const v = k0(input, pos, ctx);
9823
12029
  if (v === FAIL) return FAIL;
9824
- return fn([v], { start: pos, end: EC.e });
12030
+ return projection === 0 ? v : fn([v], { start: pos, end: EC.e });
9825
12031
  };
9826
12032
  }
9827
12033
  if (wantValues) {
@@ -9838,7 +12044,7 @@ function assemble(t, prog, cfg) {
9838
12044
  };
9839
12045
  }
9840
12046
  if (n === 2) {
9841
- const k0 = kids[0], k1 = kids[1];
12047
+ const k0 = link(code[base]), k1 = link(code[base + 1]);
9842
12048
  if (fused) {
9843
12049
  return (input, pos, ctx) => {
9844
12050
  const v0 = k0(input, pos, ctx);
@@ -9846,7 +12052,7 @@ function assemble(t, prog, cfg) {
9846
12052
  const cur = nextTerm(k1, input, EC.e, ctx);
9847
12053
  if (cur < 0) return FAIL;
9848
12054
  EC.e = cur;
9849
- return fn([v0, TERMV], { start: pos, end: cur });
12055
+ return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
9850
12056
  };
9851
12057
  }
9852
12058
  if (wantValues) {
@@ -9869,7 +12075,7 @@ function assemble(t, prog, cfg) {
9869
12075
  };
9870
12076
  }
9871
12077
  if (n === 3) {
9872
- 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]);
9873
12079
  if (fused) {
9874
12080
  return (input, pos, ctx) => {
9875
12081
  const v0 = k0(input, pos, ctx);
@@ -9880,7 +12086,7 @@ function assemble(t, prog, cfg) {
9880
12086
  cur = nextTerm(k2, input, cur, ctx);
9881
12087
  if (cur < 0) return FAIL;
9882
12088
  EC.e = cur;
9883
- 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 });
9884
12090
  };
9885
12091
  }
9886
12092
  if (wantValues) {
@@ -9907,26 +12113,90 @@ function assemble(t, prog, cfg) {
9907
12113
  return void 0;
9908
12114
  };
9909
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
+ };
9910
12180
  if (fused) {
9911
12181
  return (input, pos, ctx) => {
9912
12182
  const values = [];
9913
- const cur = runTerms(input, pos, ctx, values);
12183
+ const cur = runDirectTerms(input, pos, ctx, values);
9914
12184
  if (cur < 0) return FAIL;
9915
12185
  EC.e = cur;
9916
- return fn(values, { start: pos, end: cur });
12186
+ return projection >= 0 ? values[projection] : fn(values, { start: pos, end: cur });
9917
12187
  };
9918
12188
  }
9919
12189
  if (wantValues) {
9920
12190
  return (input, pos, ctx) => {
9921
12191
  const values = [];
9922
- const cur = runTerms(input, pos, ctx, values);
12192
+ const cur = runDirectTerms(input, pos, ctx, values);
9923
12193
  if (cur < 0) return FAIL;
9924
12194
  EC.e = cur;
9925
12195
  return values;
9926
12196
  };
9927
12197
  }
9928
12198
  return (input, pos, ctx) => {
9929
- const cur = runTerms(input, pos, ctx, void 0);
12199
+ const cur = runDirectTerms(input, pos, ctx, void 0);
9930
12200
  if (cur < 0) return FAIL;
9931
12201
  EC.e = cur;
9932
12202
  return void 0;
@@ -9938,13 +12208,86 @@ function assemble(t, prog, cfg) {
9938
12208
  const n = code[ip + 2];
9939
12209
  const choiceFx = fx[code[ip + 3]];
9940
12210
  const base = ip + 4;
9941
- const arms = new Array(n);
9942
- for (let i = 0; i < n; i++) arms[i] = link(code[base + i]);
9943
- const armFx = new Array(n);
9944
- for (let i = 0; i < n; i++) armFx[i] = fx[code[base + n + i]];
9945
12211
  if (table.exclusive) {
9946
12212
  const ascii = table.ascii;
9947
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);
9948
12291
  return (input, pos, ctx) => {
9949
12292
  const c = lead(input, pos);
9950
12293
  let arm = -1;
@@ -9961,11 +12304,11 @@ function assemble(t, prog, cfg) {
9961
12304
  }
9962
12305
  if (arm >= 0) {
9963
12306
  ctx._fc = false;
9964
- const v = arms[arm](input, pos, ctx);
12307
+ const v = selected(arm, input, pos, ctx);
9965
12308
  if (v !== FAIL) return v;
9966
- if (committed2(ctx)) return FAIL;
9967
- const armFx2 = ctx._fx;
9968
- 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) {
9969
12312
  ctx._fe = pos;
9970
12313
  return FAIL;
9971
12314
  }
@@ -9976,25 +12319,25 @@ function assemble(t, prog, cfg) {
9976
12319
  };
9977
12320
  }
9978
12321
  const armCls = table.armCls;
9979
- const gates = new Array(n);
9980
- for (let i = 0; i < n; i++) gates[i] = armCls[i] ?? null;
9981
- const maskable = n <= 32;
9982
- let cand;
9983
- if (maskable) {
9984
- const m = new Uint32Array(129);
9985
- for (let i = 0; i < n; i++) {
9986
- const cls = gates[i];
9987
- 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) => {
9988
12332
  if (cls === null) {
9989
- for (let c = 0; c < 129; c++) m[c] |= bit;
9990
- continue;
12333
+ for (let c = 0; c < 129; c++) mask[c] |= bit;
12334
+ return;
9991
12335
  }
9992
- for (let c = 0; c < 128; c++) if (cls.ascii[c] === 1) m[c] |= bit;
9993
- }
9994
- cand = m;
9995
- }
9996
- if (cand !== void 0) {
9997
- 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);
9998
12341
  return (input, pos, ctx) => {
9999
12342
  const c = lead(input, pos);
10000
12343
  const need = markCst(ctx);
@@ -10007,50 +12350,206 @@ function assemble(t, prog, cfg) {
10007
12350
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10008
12351
  let acc;
10009
12352
  if (c < 128) {
10010
- const bits0 = mask[c < 0 ? 128 : c];
10011
- let bits = bits0;
12353
+ const bits = mask[c < 0 ? 128 : c];
10012
12354
  let prev = 0;
10013
- while (bits !== 0) {
10014
- const i = 31 - Math.clz32(bits & -bits);
10015
- 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) {
12368
+ ctx._fc = false;
12369
+ const v = a1(input, pos, ctx);
12370
+ if (v !== FAIL) return v;
12371
+ if (prev < 1) acc = accSet(e0, acc);
12372
+ prev = 2;
12373
+ acc = accSet(ctx._fx, acc);
12374
+ if (committed3(ctx)) {
12375
+ if (acc !== void 0) ctx._fx = acc;
12376
+ return FAIL;
12377
+ }
12378
+ if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12379
+ }
12380
+ if (n === 3 && (bits & 4) !== 0) {
10016
12381
  ctx._fc = false;
10017
- const v = arms[i](input, pos, ctx);
12382
+ const v = a2(input, pos, ctx);
10018
12383
  if (v !== FAIL) return v;
10019
- for (let j = prev; j < i; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
10020
- prev = i + 1;
12384
+ if (prev < 1) acc = accSet(e0, acc);
12385
+ if (prev < 2) acc = accSet(e1, acc);
12386
+ prev = 3;
10021
12387
  acc = accSet(ctx._fx, acc);
10022
- if (committed2(ctx)) {
12388
+ if (committed3(ctx)) {
10023
12389
  if (acc !== void 0) ctx._fx = acc;
10024
12390
  return FAIL;
10025
12391
  }
10026
12392
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10027
12393
  }
10028
- for (let j = prev; j < n; j++) if ((bits0 & 1 << j) === 0) acc = accSet(armFx[j], acc);
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);
10029
12397
  ctx._fe = pos;
10030
12398
  ctx._fx = acc ?? choiceFx;
10031
12399
  return FAIL;
10032
12400
  }
10033
- for (let i = 0; i < n; i++) {
10034
- const cls = gates[i];
10035
- if (cls !== null && !classHas(cls, c)) {
10036
- acc = accSet(armFx[i], acc);
10037
- 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;
10038
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)) {
10039
12413
  ctx._fc = false;
10040
- const v = arms[i](input, pos, ctx);
12414
+ const v = a1(input, pos, ctx);
10041
12415
  if (v !== FAIL) return v;
10042
12416
  acc = accSet(ctx._fx, acc);
10043
- if (committed2(ctx)) {
12417
+ if (committed3(ctx)) {
10044
12418
  if (acc !== void 0) ctx._fx = acc;
10045
12419
  return FAIL;
10046
12420
  }
10047
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);
10048
12435
  }
10049
12436
  ctx._fe = pos;
10050
12437
  ctx._fx = acc ?? choiceFx;
10051
12438
  return FAIL;
10052
12439
  };
10053
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
+ }
10054
12553
  return (input, pos, ctx) => {
10055
12554
  const c = lead(input, pos);
10056
12555
  const need = markCst(ctx);
@@ -10061,26 +12560,22 @@ function assemble(t, prog, cfg) {
10061
12560
  const mEr = need ? ctx._errors?.length ?? 0 : 0;
10062
12561
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
10063
12562
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
10064
- let acc;
10065
- for (let i = 0; i < n; i++) {
10066
- const cls = gates[i];
10067
- if (cls !== null && !classHas(cls, c)) {
10068
- acc = accSet(armFx[i], acc);
10069
- continue;
10070
- }
10071
- ctx._fc = false;
10072
- const v = arms[i](input, pos, ctx);
10073
- if (v !== FAIL) return v;
10074
- acc = accSet(ctx._fx, acc);
10075
- if (committed2(ctx)) {
10076
- if (acc !== void 0) ctx._fx = acc;
10077
- return FAIL;
10078
- }
10079
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10080
- }
10081
- ctx._fe = pos;
10082
- ctx._fx = acc ?? choiceFx;
10083
- 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
+ );
10084
12579
  };
10085
12580
  }
10086
12581
  /* ── greedyClassify / autoNot ────────────────────────────────────────── */
@@ -10149,7 +12644,7 @@ function assemble(t, prog, cfg) {
10149
12644
  if (nc !== 0) {
10150
12645
  const c = lead(input, end);
10151
12646
  for (let i = 0; i < nc; i++) {
10152
- if (!classHas(clss[i], c)) continue;
12647
+ if (!classHas2(clss[i], c)) continue;
10153
12648
  ctx._fc = false;
10154
12649
  ctx._fx = void 0;
10155
12650
  return FAIL;
@@ -10173,6 +12668,9 @@ function assemble(t, prog, cfg) {
10173
12668
  const reportItem = (flags & 4) !== 0;
10174
12669
  const itemFx = reportItem ? fx[code[ip + 6]] : EMPTY_FX2;
10175
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));
10176
12674
  const skipBeforeFirst = sepIp < 0 && min === 0;
10177
12675
  if (REC2) {
10178
12676
  const itemFx2 = fx[code[ip + 6]];
@@ -10206,7 +12704,7 @@ function assemble(t, prog, cfg) {
10206
12704
  const sv = sep(input, sp, ctx);
10207
12705
  if (sv === FAIL) {
10208
12706
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10209
- if (committed2(ctx)) return FAIL;
12707
+ if (committed3(ctx)) return FAIL;
10210
12708
  break;
10211
12709
  }
10212
12710
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -10223,7 +12721,7 @@ function assemble(t, prog, cfg) {
10223
12721
  ctx._fc = false;
10224
12722
  const v = child(input, itemStart, ctx);
10225
12723
  if (v === FAIL) {
10226
- if (committed2(ctx)) {
12724
+ if (committed3(ctx)) {
10227
12725
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10228
12726
  return FAIL;
10229
12727
  }
@@ -10269,11 +12767,13 @@ function assemble(t, prog, cfg) {
10269
12767
  const out = collect ? [] : void 0;
10270
12768
  const hasTrivia = ctx.trivia !== void 0;
10271
12769
  const needMark = rollbackNeeded(ctx);
12770
+ const gateItems = itemMayStart !== void 0 && ctx._probe === void 0;
10272
12771
  let cur = pos;
10273
12772
  let count = 0;
10274
12773
  for (; ; ) {
10275
12774
  if (max >= 0 && count >= max) break;
10276
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;
10277
12777
  if (needMark) markCst(ctx);
10278
12778
  const mRaw = needMark ? MRAW : 0;
10279
12779
  const mTl = needMark ? MTL : 0;
@@ -10293,7 +12793,7 @@ function assemble(t, prog, cfg) {
10293
12793
  const sv = sep(input, sp, ctx);
10294
12794
  if (sv === FAIL) {
10295
12795
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10296
- if (committed2(ctx)) return FAIL;
12796
+ if (committed3(ctx)) return FAIL;
10297
12797
  break;
10298
12798
  }
10299
12799
  if (!keepSeparators) demoteCapturedToRaw(ctx, leavesBefore);
@@ -10307,11 +12807,16 @@ function assemble(t, prog, cfg) {
10307
12807
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
10308
12808
  break;
10309
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
+ }
10310
12815
  ctx._fc = false;
10311
12816
  const v = child(input, itemStart, ctx);
10312
12817
  if (v === FAIL) {
10313
12818
  if (needMark) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
10314
- if (committed2(ctx)) return FAIL;
12819
+ if (committed3(ctx)) return FAIL;
10315
12820
  if (trailingAllowed && sepEnd >= 0) cur = sepEnd;
10316
12821
  break;
10317
12822
  }
@@ -10343,72 +12848,103 @@ function assemble(t, prog, cfg) {
10343
12848
  const otherRouted = code[ip + 4] === 1;
10344
12849
  const n = code[ip + 5];
10345
12850
  const armBase = ip + 6;
10346
- const arms = new Array(n);
10347
- for (let i = 0; i < n; i++) arms[i] = link(code[armBase + i]);
10348
12851
  const byKey = spec.byKey;
10349
12852
  const byFold = spec.byFold;
10350
12853
  const hasFold = spec.byFold.size > 0;
10351
12854
  const match = spec.match;
10352
12855
  const matchN = match.length;
10353
- const matchFn = new Array(matchN);
10354
- const matchArm = new Array(matchN);
10355
- for (let i = 0; i < matchN; i++) {
10356
- matchFn[i] = linkMatcher(match[i]);
10357
- matchArm[i] = match[i][3];
10358
- }
10359
12856
  const routed2 = spec.routed;
10360
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);
10361
12897
  return (input, pos, ctx) => {
10362
12898
  const selectorMark = saveTriviaMark(ctx);
10363
12899
  const selVal = selector(input, pos, ctx);
10364
12900
  if (selVal === FAIL) return FAIL;
10365
12901
  const selEnd = EC.e;
10366
12902
  const key = selVal;
10367
- let arm = byKey.get(key);
10368
- if (arm === void 0 && hasFold) arm = byFold.get(asciiFoldKey(key));
10369
- if (arm === void 0) {
10370
- for (let i = 0; i < matchN; i++) {
10371
- if (matchFn[i](key)) {
10372
- arm = matchArm[i];
10373
- break;
10374
- }
10375
- }
10376
- }
10377
- let target;
10378
- let usesRouted;
12903
+ const arm = classify(key);
10379
12904
  if (arm === void 0) {
10380
- if (other === void 0) {
12905
+ if (runOther === void 0) {
10381
12906
  ctx._fe = selEnd;
10382
12907
  ctx._fx = expected;
10383
12908
  return FAIL;
10384
12909
  }
10385
- target = other;
10386
- usesRouted = otherRouted;
10387
- } else {
10388
- target = arms[arm];
10389
- usesRouted = routed2[arm] === 1;
10390
- }
10391
- const savedRouted = ctx._routed;
10392
- let mark = saveTriviaMark(ctx);
10393
- if (usesRouted) {
10394
- rollbackTrivia(ctx, selectorMark);
10395
- mark = saveTriviaMark(ctx);
10396
- ctx._routed = { value: key, span: { start: pos, end: selEnd } };
12910
+ return runOther(input, pos, selEnd, key, selectorMark, ctx);
10397
12911
  }
10398
- const v = target(input, usesRouted ? pos : selEnd, ctx);
10399
- if (usesRouted) ctx._routed = savedRouted;
10400
- if (v === FAIL) {
10401
- rollbackTrivia(ctx, mark);
10402
- ctx._fc = true;
10403
- return FAIL;
10404
- }
10405
- return [key, v];
12912
+ return runArm(arm, input, pos, selEnd, key, selectorMark, ctx);
10406
12913
  };
10407
12914
  }
10408
12915
  /* ── node ────────────────────────────────────────────────────────────── */
10409
12916
  case OP_NODE:
10410
12917
  case OP_NODE_TRACK: {
10411
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
+ }
10412
12948
  const child = link(code[ip + 2]);
10413
12949
  const proj = code[ip + 4];
10414
12950
  const buildIdx = code[ip + 1];
@@ -10423,6 +12959,26 @@ function assemble(t, prog, cfg) {
10423
12959
  const unwrap = (flags & 64) !== 0;
10424
12960
  const trailingTrivia = (flags & 128) !== 0;
10425
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
+ }
10426
12982
  const structural = build === void 0 && proj < 0;
10427
12983
  const grammarCapture = (flags & 1) !== 0 || trailingTrivia;
10428
12984
  const hostCapturesThisType = structural && cfg.hostCaptureTrivia !== void 0 ? cfg.hostCaptureTrivia(type) : void 0;
@@ -10542,9 +13098,27 @@ function assemble(t, prog, cfg) {
10542
13098
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10543
13099
  }
10544
13100
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
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);
13118
+ }
10545
13119
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10546
13120
  if (pre !== void 0) {
10547
- const pools = rebuildPools(t.cc, t.fx, pre.plan);
13121
+ const pools = rebuildPools(t.cc, t.fx, t.disp, pre.plan);
10548
13122
  emitted = pre.factory(
10549
13123
  EC,
10550
13124
  FAIL,
@@ -10568,8 +13142,9 @@ function assemble(t, prog, cfg) {
10568
13142
  pushCstLeaf,
10569
13143
  pushCstChild,
10570
13144
  rollbackTriviaAt,
13145
+ rollbackScannedTriviaAt,
10571
13146
  failAt,
10572
- classHas,
13147
+ classHas2,
10573
13148
  consumeTrivia,
10574
13149
  buildFieldMap,
10575
13150
  projectChild,
@@ -10590,7 +13165,13 @@ function assemble(t, prog, cfg) {
10590
13165
  matchesAt,
10591
13166
  recoverScan,
10592
13167
  orSentinel,
10593
- captureError
13168
+ captureError,
13169
+ scalarRecognizers,
13170
+ commitTriviaScan,
13171
+ scanTriviaCompact,
13172
+ t.lex,
13173
+ adjacencyHolds,
13174
+ t.lexPrograms
10594
13175
  );
10595
13176
  emitReached = new Set(pre.reached);
10596
13177
  }
@@ -10638,8 +13219,9 @@ function assemble(t, prog, cfg) {
10638
13219
  pushCstLeaf,
10639
13220
  pushCstChild,
10640
13221
  rollbackTriviaAt,
13222
+ rollbackScannedTriviaAt,
10641
13223
  failAt,
10642
- classHas,
13224
+ classHas2,
10643
13225
  consumeTrivia,
10644
13226
  buildFieldMap,
10645
13227
  projectChild,
@@ -10665,7 +13247,13 @@ function assemble(t, prog, cfg) {
10665
13247
  matchesAt,
10666
13248
  recoverScan,
10667
13249
  orSentinel,
10668
- captureError
13250
+ captureError,
13251
+ scalarRecognizers,
13252
+ commitTriviaScan,
13253
+ scanTriviaCompact,
13254
+ t.lex,
13255
+ adjacencyHolds,
13256
+ t.lexPrograms
10669
13257
  );
10670
13258
  emitReached = em.reached;
10671
13259
  } catch (e) {
@@ -10870,6 +13458,14 @@ function tableRules(source, artifactMetadata = {}) {
10870
13458
  function jsString(s) {
10871
13459
  return JSON.stringify(s);
10872
13460
  }
13461
+ function emitClassPool(classes) {
13462
+ const array = `[${classes.map(jsString).join(",")}]`;
13463
+ if (classes.length < 2) return array;
13464
+ const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
13465
+ if (delimiter === void 0) return array;
13466
+ const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
13467
+ return split.length < array.length ? split : array;
13468
+ }
10873
13469
  function emitConst(v) {
10874
13470
  if (v instanceof RegExp) return `/${v.source}/${v.flags}`;
10875
13471
  if (typeof v === "string") return jsString(v);
@@ -10908,6 +13504,17 @@ function emitScanSpec(s) {
10908
13504
  function emitDispatchSpec(d) {
10909
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(",")}]}`;
10910
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
+ }
10911
13518
  function emitAssemblies(prog, cfgs) {
10912
13519
  if (cfgs.length === 0) return ["a:[],"];
10913
13520
  const t = resolveTable(prog);
@@ -10948,7 +13555,7 @@ function programFields(prog, fns, opts = {}) {
10948
13555
  ...emitAssemblies(prog, opts.assemblies ?? []),
10949
13556
  `c:[${prog.code.join(",")}],`,
10950
13557
  `k:[${prog.k.map(emitConst).join(",")}],`,
10951
- `x:[${prog.cc.map(jsString).join(",")}],`,
13558
+ `x:${emitClassPool(prog.cc)},`,
10952
13559
  `e:[${prog.fx.map((f) => `[${f.map(jsString).join(",")}]`).join(",")}],`,
10953
13560
  `d:[${prog.disp.map((a) => `[${a.join(",")}]`).join(",")}],`,
10954
13561
  `r:${JSON.stringify(prog.rules)},`,
@@ -10960,6 +13567,8 @@ function programFields(prog, fns, opts = {}) {
10960
13567
  // `run({ rootTrivia })` rejected a grammar that plainly has labels — the
10961
13568
  // exact failure the root-trivia work exists to prevent, one hop downstream.
10962
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(",")}],`],
10963
13572
  ...prog.labels === void 0 ? [] : [`lb:[${prog.labels.map(jsString).join(",")}],`],
10964
13573
  ...prog.classified === 1 ? ["rc:1,"] : [],
10965
13574
  // Without this a recovery table's MODULE loads as a strict one: the extra
@@ -13183,6 +15792,7 @@ ${outerDecls.map((d) => " " + d).join("\n")}
13183
15792
  };
13184
15793
 
13185
15794
  // src/table/compile-rule-map.ts
15795
+ var DEFAULT_PRECOMPILE_MIN_WORDS = 1024;
13186
15796
  function resolveHostMode(ruleMap, explicit) {
13187
15797
  return explicit ?? ruleMap.map(([, r]) => r._meta.grammarHostMode).find(Boolean) ?? "ast";
13188
15798
  }
@@ -13272,10 +15882,11 @@ function compileRuleMap(ruleMap, opts = {}) {
13272
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.`
13273
15883
  );
13274
15884
  }
13275
- const replacementWithMetadata = (metadataSource) => emitTableExpression(artifact, {
15885
+ const replacementWithMetadata = (metadataSource, options = {}) => emitTableExpression(artifact, {
13276
15886
  entry: null,
13277
15887
  runtimeRef: opts.runtimeRef ?? "tableRules",
13278
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) } : {},
13279
15890
  ...metadataSource === void 0 ? {} : { metadataSource }
13280
15891
  });
13281
15892
  const replacement = replacementWithMetadata();
@@ -13300,7 +15911,7 @@ function compileRuleMap(ruleMap, opts = {}) {
13300
15911
  }
13301
15912
 
13302
15913
  // src/version.ts
13303
- var PARSEMAN_VERSION = "0.47.0";
15914
+ var PARSEMAN_VERSION = "0.48.0";
13304
15915
 
13305
15916
  // src/compiler/compile-linkable-table.ts
13306
15917
  function isLocal(rule) {