parseman 0.49.0 → 0.50.1

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 (77) hide show
  1. package/dist/analysis/commitment.d.ts +2 -1
  2. package/dist/analysis/commitment.d.ts.map +1 -1
  3. package/dist/analysis/diagnostics.js +1824 -737
  4. package/dist/analysis/diagnostics.js.map +3 -3
  5. package/dist/analysis/rebuild.d.ts.map +1 -1
  6. package/dist/cli/index.js +1252 -164
  7. package/dist/cli/index.js.map +3 -3
  8. package/dist/combinators/trivia-skip.d.ts +1 -1
  9. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  10. package/dist/compiler/build-arity.d.ts +16 -0
  11. package/dist/compiler/build-arity.d.ts.map +1 -1
  12. package/dist/compiler/degradation.d.ts +0 -2
  13. package/dist/compiler/degradation.d.ts.map +1 -1
  14. package/dist/compiler/ir-serialize.d.ts.map +1 -1
  15. package/dist/compiler/token-alphabet.d.ts +11 -0
  16. package/dist/compiler/token-alphabet.d.ts.map +1 -1
  17. package/dist/compiler/token-capability.js +185 -20
  18. package/dist/compiler/token-capability.js.map +1 -1
  19. package/dist/cst/capture-buffer.d.ts +5 -1
  20. package/dist/cst/capture-buffer.d.ts.map +1 -1
  21. package/dist/index.js +1365 -279
  22. package/dist/index.js.map +3 -3
  23. package/dist/language-service/index.js +2 -1
  24. package/dist/language-service/index.js.map +1 -1
  25. package/dist/plugin/entry-supercompiler.d.ts +48 -0
  26. package/dist/plugin/entry-supercompiler.d.ts.map +1 -0
  27. package/dist/plugin/evaluator.d.ts.map +1 -1
  28. package/dist/plugin/index.d.ts.map +1 -1
  29. package/dist/plugin/index.js +1957 -385
  30. package/dist/plugin/index.js.map +3 -3
  31. package/dist/run/index.js +2 -1
  32. package/dist/run/index.js.map +1 -1
  33. package/dist/spec/index.js +28 -7
  34. package/dist/spec/index.js.map +1 -1
  35. package/dist/table/assemble.d.ts.map +1 -1
  36. package/dist/table/compile-rule-map.d.ts +6 -5
  37. package/dist/table/compile-rule-map.d.ts.map +1 -1
  38. package/dist/table/emit-assembly.d.ts +6 -1
  39. package/dist/table/emit-assembly.d.ts.map +1 -1
  40. package/dist/table/encode.d.ts.map +1 -1
  41. package/dist/table/index.js +1315 -231
  42. package/dist/table/index.js.map +3 -3
  43. package/dist/table/ops.d.ts +3 -2
  44. package/dist/table/ops.d.ts.map +1 -1
  45. package/dist/table/program.d.ts +15 -1
  46. package/dist/table/program.d.ts.map +1 -1
  47. package/dist/table/scalar-terminal.d.ts +30 -0
  48. package/dist/table/scalar-terminal.d.ts.map +1 -1
  49. package/dist/table/site-labels.d.ts +8 -0
  50. package/dist/table/site-labels.d.ts.map +1 -1
  51. package/dist/types.d.ts +2 -1
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/version.d.ts +1 -1
  54. package/package.json +1 -1
  55. package/src/analysis/commitment.ts +19 -8
  56. package/src/analysis/rebuild.ts +1 -0
  57. package/src/combinators/trivia-skip.ts +2 -2
  58. package/src/compiler/build-arity.ts +50 -0
  59. package/src/compiler/degradation.ts +0 -6
  60. package/src/compiler/ir-serialize.ts +6 -4
  61. package/src/compiler/token-alphabet.ts +322 -28
  62. package/src/cst/capture-buffer.ts +34 -11
  63. package/src/plugin/entry-supercompiler.ts +567 -0
  64. package/src/plugin/evaluator.ts +10 -0
  65. package/src/plugin/index.ts +7 -3
  66. package/src/table/assemble.ts +125 -42
  67. package/src/table/compile-rule-map.ts +8 -7
  68. package/src/table/compile.ts +7 -8
  69. package/src/table/emit-assembly.ts +646 -126
  70. package/src/table/emit.ts +1 -1
  71. package/src/table/encode.ts +152 -7
  72. package/src/table/ops.ts +3 -2
  73. package/src/table/program.ts +44 -3
  74. package/src/table/scalar-terminal.ts +213 -1
  75. package/src/table/site-labels.ts +22 -9
  76. package/src/types.ts +1 -1
  77. package/src/version.ts +1 -1
package/dist/index.js CHANGED
@@ -392,7 +392,7 @@ function beginCstNodeCapture(ctx) {
392
392
  function finishCstBuf(buf) {
393
393
  if (!buf) return { children: EMPTY, rawChildren: EMPTY, triviaLog: EMPTY_TL };
394
394
  const children2 = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
395
- const rawChildren = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
395
+ const rawChildren = buf.noRaw === true ? EMPTY : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
396
396
  const triviaLog = buf.tl ?? EMPTY_TL;
397
397
  return { children: children2, rawChildren, triviaLog };
398
398
  }
@@ -424,7 +424,8 @@ function pushCstChild(ctx, built, rawEntry2) {
424
424
  b.single = void 0;
425
425
  } else b.single = built;
426
426
  }
427
- if (b.raw) b.raw.push(rawEntry2);
427
+ if (b.noRaw === true) b.rawLen = (b.rawLen ?? 0) + 1;
428
+ else if (b.raw) b.raw.push(rawEntry2);
428
429
  else if (b.rawSingle !== void 0) {
429
430
  b.raw = [b.rawSingle, rawEntry2];
430
431
  b.rawSingle = void 0;
@@ -438,6 +439,7 @@ function pushCstChild(ctx, built, rawEntry2) {
438
439
  function cstRawLen(ctx) {
439
440
  const b = ctx._cstBuf;
440
441
  if (b) {
442
+ if (b.noRaw === true) return b.rawLen ?? 0;
441
443
  if (b.raw) return b.raw.length;
442
444
  return b.rawSingle !== void 0 ? 1 : 0;
443
445
  }
@@ -497,19 +499,37 @@ function rollbackCstCaptureAt(ctx, raw, tlog, leaves, fields, errors) {
497
499
  if (ctx._errors && errors !== void 0 && ctx._errors.length !== errors) ctx._errors.length = errors;
498
500
  const b = ctx._cstBuf;
499
501
  if (b) {
500
- rollbackBufList(b, "raw", "rawSingle", raw);
501
- rollbackBufList(b, "ch", "single", leaves);
502
+ if (b.noRaw === true) {
503
+ if (b.rawLen !== raw) b.rawLen = raw;
504
+ } else {
505
+ const rawList = b.raw;
506
+ if (rawList) {
507
+ if (raw === 0) b.raw = void 0;
508
+ else if (raw === 1) {
509
+ b.rawSingle = rawList[0];
510
+ b.raw = void 0;
511
+ } else if (rawList.length !== raw) rawList.length = raw;
512
+ } else if (raw === 0) b.rawSingle = void 0;
513
+ }
514
+ const childList = b.ch;
515
+ if (childList) {
516
+ if (leaves === 0) b.ch = void 0;
517
+ else if (leaves === 1) {
518
+ b.single = childList[0];
519
+ b.ch = void 0;
520
+ } else if (childList.length !== leaves) childList.length = leaves;
521
+ } else if (leaves === 0) b.single = void 0;
502
522
  if (b.tl) {
503
523
  if (tlog === 0) b.tl = void 0;
504
524
  else if (b.tl.length !== tlog) b.tl.length = tlog;
505
525
  }
506
- if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
526
+ if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
507
527
  return;
508
528
  }
509
529
  if (ctx._cstRawChildren && ctx._cstRawChildren.length !== raw) ctx._cstRawChildren.length = raw;
510
530
  if (ctx._cstTriviaLog && ctx._cstTriviaLog.length !== tlog) ctx._cstTriviaLog.length = tlog;
511
531
  if (ctx._cstLeaves && ctx._cstLeaves.length !== leaves) ctx._cstLeaves.length = leaves;
512
- if (ctx._fields && ctx._fields.length !== fields) ctx._fields.length = fields;
532
+ if (ctx._fields && fields !== void 0 && ctx._fields.length !== fields) ctx._fields.length = fields;
513
533
  }
514
534
  function pushCstTriviaEntry(ctx, start, end, kindIndex) {
515
535
  const insertIdx = cstRawLen(ctx);
@@ -981,6 +1001,13 @@ function canConsumeNewline(n) {
981
1001
  return n.parts.some(canConsumeNewline);
982
1002
  }
983
1003
  }
1004
+ function regexCanMatchEmpty(source) {
1005
+ try {
1006
+ return nullable(parseRegex(source));
1007
+ } catch {
1008
+ return true;
1009
+ }
1010
+ }
984
1011
  function firstSetFromRegex(source) {
985
1012
  let ast;
986
1013
  try {
@@ -4588,6 +4615,7 @@ function confirmedArityForDef(def) {
4588
4615
  }
4589
4616
  function buildReadsRaw(def) {
4590
4617
  if (!def.build) return true;
4618
+ if (def.buildRawUnused === true) return false;
4591
4619
  const arity = confirmedArityForDef(def);
4592
4620
  if (arity === null) return true;
4593
4621
  return arity >= 4;
@@ -5384,6 +5412,399 @@ function ruleDependencies(ruleMap) {
5384
5412
  return deps;
5385
5413
  }
5386
5414
 
5415
+ // src/analysis/commitment.ts
5416
+ function mayFail(p, seen = /* @__PURE__ */ new Set()) {
5417
+ if (seen.has(p)) return true;
5418
+ seen.add(p);
5419
+ const d = p._def;
5420
+ switch (d.tag) {
5421
+ case "literal":
5422
+ return d.value.length > 0;
5423
+ case "trivia":
5424
+ return false;
5425
+ // `optional`/`many`/a min-0 `sepBy` swallow an ORDINARY failure — zero
5426
+ // repetitions is a match. They do NOT swallow a COMMITTED one: a dispatch
5427
+ // that has selected an arm and then failed inside it breaks out past every
5428
+ // enclosing repeat, straight to the fallible boundary. So these are total
5429
+ // exactly when their body cannot commit. (Measured: treating them as
5430
+ // unconditionally total left an extra zero-width leaf in
5431
+ // `BareInterpolatedSelector` on benchmark.less — a rollback the legacy
5432
+ // build fired and this one had deleted.)
5433
+ case "optional":
5434
+ case "many":
5435
+ return mayCommitFailure(d.parser);
5436
+ case "sepBy":
5437
+ return d.min >= 1 ? mayFail(d.parser, seen) : mayCommitFailure(d.parser) || mayCommitFailure(d.separator);
5438
+ case "oneOrMore":
5439
+ return mayFail(d.parser, seen);
5440
+ case "sequence":
5441
+ return d.parsers.some((x) => mayFail(x, seen));
5442
+ // Delegating wrappers: as fallible as what they wrap.
5443
+ case "node":
5444
+ case "transform":
5445
+ case "label":
5446
+ case "field":
5447
+ case "expect":
5448
+ case "withCtx":
5449
+ case "grammar":
5450
+ case "token":
5451
+ case "leaf":
5452
+ return mayFail(d.parser, seen);
5453
+ case "lazy": {
5454
+ try {
5455
+ return mayFail(d.thunk(), seen);
5456
+ } catch {
5457
+ return true;
5458
+ }
5459
+ }
5460
+ // An adjacency assertion is a TEST — failing is its whole job.
5461
+ case "adjacency":
5462
+ return true;
5463
+ default:
5464
+ return true;
5465
+ }
5466
+ }
5467
+ function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set(), triviaActive = true) {
5468
+ if (seen.has(p)) return false;
5469
+ seen.add(p);
5470
+ const d = p._def;
5471
+ switch (d.tag) {
5472
+ // Atomic / non-capturing-then-failing: a failure happens before any push.
5473
+ case "literal":
5474
+ case "regex":
5475
+ case "keywords":
5476
+ case "guard":
5477
+ // Adjacency probes with `_cap = 0` / no `commit()`: it cannot push anything.
5478
+ case "adjacency":
5479
+ case "not":
5480
+ // peek(): emitted under a non-capturing probe ctx and zero-width on both
5481
+ // outcomes, so it can never leave a partial capture behind.
5482
+ case "peek":
5483
+ case "trivia":
5484
+ case "token":
5485
+ case "leaf":
5486
+ case "scanTo":
5487
+ case "unknown":
5488
+ return false;
5489
+ // node() captures into its own private buffers and rolls them back on
5490
+ // failure (emitNode restores _ctx.* and never pushes on the !ok path).
5491
+ case "node":
5492
+ return false;
5493
+ // choice/firstMatch already roll back each failed arm; on overall failure
5494
+ // nothing committed remains.
5495
+ case "choice":
5496
+ return false;
5497
+ case "dispatch":
5498
+ return capturesLeaf(d.selector, new Set(seen)) || d.cases.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) || (d.matchers ? d.matchers.some((x) => mayLeavePartialCapture(x.parser, new Set(seen), triviaActive) || capturesLeaf(x.parser, new Set(seen))) : false) || (d.otherwise ? mayLeavePartialCapture(d.otherwise, new Set(seen), triviaActive) || capturesLeaf(d.otherwise, new Set(seen)) : false);
5499
+ case "attempt":
5500
+ return false;
5501
+ // optional never fails; many/oneOrMore only "fail" with zero captured items.
5502
+ case "optional":
5503
+ case "many":
5504
+ case "oneOrMore":
5505
+ return false;
5506
+ // sepBy emits its own per-iteration rollback in emitSepBy.
5507
+ case "sepBy":
5508
+ return false;
5509
+ // A sequence is the real case: an earlier capturing term followed by a term
5510
+ // that can fail leaves the earlier captures buffered.
5511
+ //
5512
+ // BOTH halves of that sentence are load-bearing, and the second half is what
5513
+ // this walk exists to exploit. "Some earlier term captures" alone was the old
5514
+ // test, and it is true of very nearly every sequence in a real grammar — a
5515
+ // sequence almost always opens with a literal or a node. The rollback is only
5516
+ // reachable if something AFTER the capture can still fail; once the remainder
5517
+ // is total (`optional`/`many`/trivia/a min-0 `sepBy`), the sequence has no
5518
+ // failure path left to roll back from, and the save+restore is dead code.
5519
+ //
5520
+ // `captured` tracks whether anything is in the buffers yet as the scan moves
5521
+ // left to right. Two things put it there:
5522
+ // - a term that captures (`capturesLeaf`/`hasNodeDef`), and
5523
+ // - the inter-term TRIVIA scan, which under `capturing` pushes into
5524
+ // `_cstRawChildren`/`_cstTriviaLog` BEFORE the term at each boundary
5525
+ // i >= 1. `emitSeqValues` only rewinds that push on the term's SUCCESS
5526
+ // path (the "matched empty, so leave the whitespace out of the span"
5527
+ // branch); a term that FAILS breaks straight out with the trivia still
5528
+ // buffered, so from boundary 1 onward the buffers are dirty regardless of
5529
+ // what the earlier terms did.
5530
+ // Each term is also asked about itself: a nested sequence can leave its own
5531
+ // partial capture behind, and its terms are emitted inline into this same
5532
+ // block with no boundary of their own to roll them back.
5533
+ case "sequence": {
5534
+ const parts = d.parsers;
5535
+ let captured = false;
5536
+ for (let i = 0; i < parts.length; i++) {
5537
+ const part = parts[i];
5538
+ if (i > 0 && triviaActive) captured = true;
5539
+ if (captured && mayFail(part)) return true;
5540
+ if (mayLeavePartialCapture(part, seen, triviaActive)) return true;
5541
+ if (capturesLeaf(part) || hasNodeDef(part)) captured = true;
5542
+ }
5543
+ return false;
5544
+ }
5545
+ // Delegating wrappers: defer to the wrapped parser.
5546
+ case "transform":
5547
+ case "label":
5548
+ case "field":
5549
+ case "expect":
5550
+ case "withCtx":
5551
+ case "grammar":
5552
+ return mayLeavePartialCapture(d.parser, seen, triviaActive);
5553
+ case "recover":
5554
+ return mayLeavePartialCapture(d.parser, seen, triviaActive);
5555
+ case "lazy": {
5556
+ try {
5557
+ return mayLeavePartialCapture(d.thunk(), seen, triviaActive);
5558
+ } catch {
5559
+ return true;
5560
+ }
5561
+ }
5562
+ // Unknown shapes: be safe and keep the rollback.
5563
+ default:
5564
+ return true;
5565
+ }
5566
+ }
5567
+ function capturesLeaf(p, seen = /* @__PURE__ */ new Set()) {
5568
+ if (seen.has(p)) return false;
5569
+ seen.add(p);
5570
+ const d = p._def;
5571
+ switch (d.tag) {
5572
+ case "literal":
5573
+ case "regex":
5574
+ case "keywords":
5575
+ case "node":
5576
+ case "token":
5577
+ case "routed":
5578
+ case "leaf":
5579
+ return true;
5580
+ case "not":
5581
+ case "peek":
5582
+ case "guard":
5583
+ case "adjacency":
5584
+ case "trivia":
5585
+ case "unknown":
5586
+ return false;
5587
+ case "sequence":
5588
+ case "choice":
5589
+ return d.parsers.some((x) => capturesLeaf(x, seen));
5590
+ case "dispatch":
5591
+ return capturesLeaf(d.selector, seen) || d.cases.some((x) => capturesLeaf(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => capturesLeaf(entry.parser, seen)) : false) || (d.otherwise ? capturesLeaf(d.otherwise, seen) : false);
5592
+ case "sepBy":
5593
+ return capturesLeaf(d.parser, seen) || capturesLeaf(d.separator, seen);
5594
+ case "many":
5595
+ case "oneOrMore":
5596
+ case "optional":
5597
+ case "attempt":
5598
+ case "transform":
5599
+ case "label":
5600
+ case "field":
5601
+ case "expect":
5602
+ case "withCtx":
5603
+ case "grammar":
5604
+ case "recover":
5605
+ return capturesLeaf(d.parser, seen);
5606
+ case "scanTo":
5607
+ return true;
5608
+ case "lazy": {
5609
+ try {
5610
+ return capturesLeaf(d.thunk(), seen);
5611
+ } catch {
5612
+ return true;
5613
+ }
5614
+ }
5615
+ default:
5616
+ return true;
5617
+ }
5618
+ }
5619
+ function hasNodeDef(p, seen = /* @__PURE__ */ new Set()) {
5620
+ if (seen.has(p)) return false;
5621
+ seen.add(p);
5622
+ const d = p._def;
5623
+ switch (d.tag) {
5624
+ case "node":
5625
+ return true;
5626
+ case "lazy": {
5627
+ try {
5628
+ return hasNodeDef(d.thunk(), seen);
5629
+ } catch {
5630
+ return false;
5631
+ }
5632
+ }
5633
+ case "grammar":
5634
+ case "trivia":
5635
+ case "token":
5636
+ case "leaf":
5637
+ case "label":
5638
+ case "field":
5639
+ case "optional":
5640
+ case "many":
5641
+ case "oneOrMore":
5642
+ case "not":
5643
+ case "peek":
5644
+ case "transform":
5645
+ return hasNodeDef(d.parser, seen);
5646
+ case "sequence":
5647
+ case "choice":
5648
+ return d.parsers.some((x) => hasNodeDef(x, seen));
5649
+ case "dispatch":
5650
+ return hasNodeDef(d.selector, seen) || d.cases.some((x) => hasNodeDef(x.parser, seen)) || (d.matchers ? d.matchers.some((entry) => hasNodeDef(entry.parser, seen)) : false) || (d.otherwise ? hasNodeDef(d.otherwise, seen) : false);
5651
+ case "sepBy":
5652
+ return hasNodeDef(d.parser, seen) || hasNodeDef(d.separator, seen);
5653
+ case "scanTo":
5654
+ return hasNodeDef(d.sentinel, seen) || d.skip.some((x) => hasNodeDef(x, seen));
5655
+ case "recover":
5656
+ return hasNodeDef(d.parser, seen) || hasNodeDef(d.sentinel, seen);
5657
+ case "expect":
5658
+ return hasNodeDef(d.parser, seen);
5659
+ case "withCtx":
5660
+ return hasNodeDef(d.parser, seen);
5661
+ default:
5662
+ return false;
5663
+ }
5664
+ }
5665
+ function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
5666
+ if (seen.has(p)) return false;
5667
+ seen.add(p);
5668
+ const d = p._def;
5669
+ switch (d.tag) {
5670
+ case "node":
5671
+ return d.build !== void 0 || hasDirectBuildDef(d.parser, seen);
5672
+ case "lazy": {
5673
+ try {
5674
+ return hasDirectBuildDef(d.thunk(), seen);
5675
+ } catch {
5676
+ return false;
5677
+ }
5678
+ }
5679
+ case "grammar":
5680
+ case "trivia":
5681
+ case "token":
5682
+ case "leaf":
5683
+ case "label":
5684
+ case "field":
5685
+ case "optional":
5686
+ case "many":
5687
+ case "oneOrMore":
5688
+ case "attempt":
5689
+ case "not":
5690
+ case "peek":
5691
+ case "withCtx":
5692
+ case "expect":
5693
+ case "transform":
5694
+ return hasDirectBuildDef(d.parser, seen);
5695
+ case "sequence":
5696
+ case "choice":
5697
+ return d.parsers.some((x) => hasDirectBuildDef(x, seen));
5698
+ case "dispatch":
5699
+ return hasDirectBuildDef(d.selector, seen) || d.cases.some((x) => hasDirectBuildDef(x.parser, seen)) || (d.matchers ? d.matchers.some((x) => hasDirectBuildDef(x.parser, seen)) : false) || (d.otherwise ? hasDirectBuildDef(d.otherwise, seen) : false);
5700
+ case "sepBy":
5701
+ return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
5702
+ case "scanTo":
5703
+ return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen));
5704
+ case "recover":
5705
+ return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
5706
+ case "routed":
5707
+ return d.fallback ? hasDirectBuildDef(d.fallback, seen) : false;
5708
+ default:
5709
+ return false;
5710
+ }
5711
+ }
5712
+ function mayCommitFailure(p, seen = /* @__PURE__ */ new Set(), resolve) {
5713
+ if (seen.has(p)) return false;
5714
+ seen.add(p);
5715
+ const d = p._def;
5716
+ switch (d.tag) {
5717
+ case "dispatch":
5718
+ return true;
5719
+ case "choice":
5720
+ case "sequence":
5721
+ return d.parsers.some((x) => mayCommitFailure(x, seen, resolve));
5722
+ case "many":
5723
+ case "oneOrMore":
5724
+ case "optional":
5725
+ case "attempt":
5726
+ case "transform":
5727
+ case "label":
5728
+ case "field":
5729
+ case "grammar":
5730
+ case "node":
5731
+ return mayCommitFailure(d.parser, seen, resolve);
5732
+ case "sepBy":
5733
+ return mayCommitFailure(d.parser, seen, resolve) || mayCommitFailure(d.separator, seen, resolve);
5734
+ case "token":
5735
+ case "leaf":
5736
+ return mayCommitFailure(d.parser, seen, resolve);
5737
+ case "withCtx":
5738
+ return mayCommitFailure(d.parser, seen, resolve);
5739
+ case "scanTo":
5740
+ return mayCommitFailure(d.sentinel, seen, resolve) || d.skip.some((x) => mayCommitFailure(x, seen, resolve));
5741
+ case "lazy": {
5742
+ try {
5743
+ return mayCommitFailure(d.thunk(), seen, resolve);
5744
+ } catch {
5745
+ const name = p._ruleName;
5746
+ const target = name === void 0 ? void 0 : resolve?.(name);
5747
+ return target === void 0 ? true : mayCommitFailure(target, seen, resolve);
5748
+ }
5749
+ }
5750
+ case "unknown":
5751
+ return true;
5752
+ default:
5753
+ return false;
5754
+ }
5755
+ }
5756
+ function hasSemanticReduction(roots, externalRefs) {
5757
+ const seen = /* @__PURE__ */ new Set();
5758
+ const visit = (parser2) => {
5759
+ if (seen.has(parser2)) return false;
5760
+ seen.add(parser2);
5761
+ const def = parser2._def;
5762
+ if (def.tag === "transform" && !def.recognitionOnly) return true;
5763
+ if (def.tag === "choice" && def.gates.some(Boolean)) return true;
5764
+ if (def.tag === "guard" || def.tag === "withCtx") return true;
5765
+ if (def.tag === "node" && def.build !== void 0) return true;
5766
+ if (def.tag === "lazy") {
5767
+ if (externalRefs?.has(parser2)) return false;
5768
+ try {
5769
+ return visit(def.thunk());
5770
+ } catch {
5771
+ return true;
5772
+ }
5773
+ }
5774
+ return childrenOf2(def).some(visit);
5775
+ };
5776
+ return roots.some(visit);
5777
+ }
5778
+ function classifyRuleMap(ruleMap) {
5779
+ const externalRefs = /* @__PURE__ */ new Set();
5780
+ const scanned = /* @__PURE__ */ new Set();
5781
+ const scanExternal = (p) => {
5782
+ if (scanned.has(p)) return;
5783
+ scanned.add(p);
5784
+ const def = p._def;
5785
+ if (def.tag === "lazy") {
5786
+ let resolved;
5787
+ try {
5788
+ resolved = def.thunk();
5789
+ } catch {
5790
+ resolved = void 0;
5791
+ }
5792
+ if (resolved === void 0) {
5793
+ if (p._ruleName) externalRefs.add(p);
5794
+ return;
5795
+ }
5796
+ scanExternal(resolved);
5797
+ return;
5798
+ }
5799
+ for (const child of childrenOf2(def)) scanExternal(child);
5800
+ };
5801
+ for (const [, rule] of ruleMap) scanExternal(rule);
5802
+ return {
5803
+ hasDirectBuilders: ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
5804
+ isRecognitionOnly: !hasSemanticReduction(ruleMap.map(([, rule]) => rule), externalRefs)
5805
+ };
5806
+ }
5807
+
5387
5808
  // src/table/ops.ts
5388
5809
  var OP_LIT = 1;
5389
5810
  var OP_RX = 2;
@@ -5939,8 +6360,26 @@ function validateDispatchSpec(spec, arity, fallbackRouted) {
5939
6360
  }
5940
6361
  }
5941
6362
  var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
5942
- function ownTableProgram(prog, resolved) {
5943
- return { ...prog, [TABLE_RUNTIME]: { resolved } };
6363
+ function ownTableProgram(prog, resolved, caches = {}) {
6364
+ const runtime = prog[TABLE_RUNTIME];
6365
+ return {
6366
+ ...prog,
6367
+ [TABLE_RUNTIME]: {
6368
+ resolved,
6369
+ choiceRollbackMasks: caches.choiceRollbackMasks ?? runtime?.choiceRollbackMasks,
6370
+ nonCommittingChoiceSites: caches.nonCommittingChoiceSites ?? runtime?.nonCommittingChoiceSites,
6371
+ failureRollbackCleanSites: caches.failureRollbackCleanSites ?? runtime?.failureRollbackCleanSites
6372
+ }
6373
+ };
6374
+ }
6375
+ function choiceRollbackMask(prog, ip) {
6376
+ return prog[TABLE_RUNTIME]?.choiceRollbackMasks?.get(ip);
6377
+ }
6378
+ function choiceCannotCommit(prog, ip) {
6379
+ return prog[TABLE_RUNTIME]?.nonCommittingChoiceSites?.has(ip) === true;
6380
+ }
6381
+ function failureRollbackClean(prog, ip) {
6382
+ return prog[TABLE_RUNTIME]?.failureRollbackCleanSites?.has(ip) === true;
5944
6383
  }
5945
6384
  var WIDE_CLASS_PREFIX_LO = 65535;
5946
6385
  var WIDE_CLASS_PREFIX_HI = 0;
@@ -6115,7 +6554,6 @@ function directArrayProjection(fn, fnSrc, arity) {
6115
6554
 
6116
6555
  // src/table/encode.ts
6117
6556
  import {
6118
- assertLexicalCapabilityClosure,
6119
6557
  collectLexicalCapabilities,
6120
6558
  winnerWrapsReference as winnerWrapsReference2
6121
6559
  } from "./compiler/token-capability.js";
@@ -6497,6 +6935,25 @@ var Encoder = class {
6497
6935
  lexIndex = /* @__PURE__ */ new Map();
6498
6936
  lexPrograms = [];
6499
6937
  lexProgramIndex = /* @__PURE__ */ new Map();
6938
+ choiceRollbackMasks = /* @__PURE__ */ new Map();
6939
+ nonCommittingChoiceSites = /* @__PURE__ */ new Set();
6940
+ failureRollbackCleanSites = /* @__PURE__ */ new Set();
6941
+ /**
6942
+ * `hasSideWriter` memo for `failureNeedsRollback`, shared across every call
6943
+ * for the lifetime of this `Encoder`. A cached entry is written only when
6944
+ * `complete` is true, which means the answer is a path-independent fact
6945
+ * about that combinator node — it does not depend on which root's traversal
6946
+ * asked, only on the node's own reachable subgraph. Scoping the memo per call
6947
+ * (as a local inside `failureNeedsRollback`) was correct but discarded that
6948
+ * fact after every arm, so a grammar with many ordered-choice arms / optional
6949
+ * / attempt sites re-walked the SAME shared rule graph from scratch for each
6950
+ * site — O(sites × graph size) instead of O(graph size). Measured on the
6951
+ * scss-parser grammar (composed CSS-base superset, the deepest/largest of the
6952
+ * four grammars): 47-50s for one `compileRuleMap` with the per-call memo,
6953
+ * versus the whole macro transform completing in under a second once this
6954
+ * memo is hoisted here.
6955
+ */
6956
+ sideWriterMemo = /* @__PURE__ */ new Map();
6500
6957
  labels = void 0;
6501
6958
  /** Trivia table in scope at the row being encoded — codegen's `ctx.activeTrivia`. */
6502
6959
  activeTrivia = void 0;
@@ -6907,6 +7364,72 @@ var Encoder = class {
6907
7364
  const w = this.winners;
6908
7365
  return w === void 0 ? void 0 : (name) => w[name];
6909
7366
  }
7367
+ /**
7368
+ * Whether a failed ordered-choice arm can leave state that the enclosing
7369
+ * choice must restore before trying its successor.
7370
+ *
7371
+ * `mayLeavePartialCapture` is the existing sound CST/trivia proof. The extra
7372
+ * writer census covers the side sinks that proof deliberately does not model:
7373
+ * fields, recovered errors, and interpreted scanners. Strict assemblies do
7374
+ * not run repeat recovery, but these rows can still publish through a caller's
7375
+ * context. Cycles are safe to stop: revisiting the same combinator cannot
7376
+ * discover a writer the first traversal did not already reach.
7377
+ */
7378
+ failureNeedsRollback(p, autoNot) {
7379
+ const refName = p._ruleName;
7380
+ const winner = refName === void 0 ? void 0 : this.winners?.[refName];
7381
+ const root = winner !== void 0 && !winnerWrapsReference2(winner, p) ? winner : p;
7382
+ const sideWriterMemo = this.sideWriterMemo;
7383
+ const seen = /* @__PURE__ */ new Set();
7384
+ const hasSideWriter = (current) => {
7385
+ const cached = sideWriterMemo.get(current);
7386
+ if (cached !== void 0) return { found: cached, complete: true };
7387
+ if (seen.has(current)) return { found: false, complete: false };
7388
+ seen.add(current);
7389
+ const def = current._def;
7390
+ let result;
7391
+ switch (def.tag) {
7392
+ case "field":
7393
+ case "expect":
7394
+ case "recover":
7395
+ case "scanTo":
7396
+ case "unknown":
7397
+ result = { found: true, complete: true };
7398
+ break;
7399
+ case "lazy": {
7400
+ const name = current._ruleName;
7401
+ const resolvedWinner = name === void 0 ? void 0 : this.winners?.[name];
7402
+ if (resolvedWinner !== void 0 && !winnerWrapsReference2(resolvedWinner, current)) {
7403
+ result = hasSideWriter(resolvedWinner);
7404
+ break;
7405
+ }
7406
+ try {
7407
+ result = hasSideWriter(def.thunk());
7408
+ } catch {
7409
+ result = { found: true, complete: true };
7410
+ }
7411
+ break;
7412
+ }
7413
+ default: {
7414
+ let complete = true;
7415
+ result = { found: false, complete: true };
7416
+ for (const child of childrenOf2(def)) {
7417
+ const childResult = hasSideWriter(child);
7418
+ if (childResult.found) {
7419
+ result = { found: true, complete: true };
7420
+ break;
7421
+ }
7422
+ complete &&= childResult.complete;
7423
+ }
7424
+ if (!result.found) result = { found: false, complete };
7425
+ }
7426
+ }
7427
+ seen.delete(current);
7428
+ if (result.found || result.complete) sideWriterMemo.set(current, result.found);
7429
+ return result;
7430
+ };
7431
+ return mayLeavePartialCapture(root, /* @__PURE__ */ new Set(), true) || hasSideWriter(root).found || (autoNot?.length ?? 0) > 0 && capturesLeaf(root);
7432
+ }
6910
7433
  /** A first set becomes a char class string, or −1 for `any`. */
6911
7434
  charClass(fs) {
6912
7435
  if (fs.kind !== "ranges" || fs.ranges.length === 0) return -1;
@@ -7192,9 +7715,39 @@ var Encoder = class {
7192
7715
  });
7193
7716
  const rr = this.refResolver();
7194
7717
  const finalChoice = classifyFinalChoice(arms, rr);
7195
- const classes = arms.map((_, i) => finalChoice.nullable[i] ? -1 : this.charClass(finalChoice.firstSets[i]));
7718
+ const transactionalFirst = arms.map((arm, i) => {
7719
+ if (!finalChoice.nullable[i]) return void 0;
7720
+ const def = arm._def;
7721
+ if (def.tag !== "attempt" || matchesEmpty(def.parser, /* @__PURE__ */ new Set(), rr)) return void 0;
7722
+ return firstSetOf(def.parser, /* @__PURE__ */ new Set(), rr);
7723
+ });
7724
+ const gateFirst = finalChoice.firstSets.map((first, i) => transactionalFirst[i] ?? first);
7725
+ const classes = gateFirst.map((first, i) => finalChoice.nullable[i] && transactionalFirst[i] === void 0 ? -1 : this.charClass(first));
7726
+ if (transactionalFirst.some((first) => first !== void 0) && classes.every((cls) => cls >= 0)) {
7727
+ let overlap = false;
7728
+ for (let i = 0; i < gateFirst.length && !overlap; i++) {
7729
+ for (let j = i + 1; j < gateFirst.length; j++) {
7730
+ if (intersects(gateFirst[i], gateFirst[j])) {
7731
+ overlap = true;
7732
+ break;
7733
+ }
7734
+ }
7735
+ }
7736
+ if (!overlap) for (let i = 0; i < classes.length; i++) {
7737
+ if (transactionalFirst[i] !== void 0) classes[i] = -1;
7738
+ }
7739
+ }
7196
7740
  const dispIdx = this.disp.length;
7197
7741
  this.disp.push(classes);
7742
+ let rollbackMask = kids.length > 31 ? -1 : 0;
7743
+ if (rollbackMask === 0) {
7744
+ for (let i = 0; i < arms.length; i++) {
7745
+ const src = order[i];
7746
+ if (this.failureNeedsRollback(arms[i], d.autoNot[src])) {
7747
+ rollbackMask |= 1 << i;
7748
+ }
7749
+ }
7750
+ }
7198
7751
  const head = this.emitHead(OP_CHOICE, 3 + 2 * kids.length);
7199
7752
  this.code[head + 1] = dispIdx;
7200
7753
  this.code[head + 2] = kids.length;
@@ -7203,6 +7756,10 @@ var Encoder = class {
7203
7756
  this.code[head + 4 + i] = kids[i];
7204
7757
  this.code[head + 4 + kids.length + i] = this.expected(deriveExpected(arms[i]));
7205
7758
  }
7759
+ this.choiceRollbackMasks.set(head, rollbackMask);
7760
+ if (arms.every((arm) => !mayCommitFailure(arm, /* @__PURE__ */ new Set(), rr))) {
7761
+ this.nonCommittingChoiceSites.add(head);
7762
+ }
7206
7763
  return head;
7207
7764
  }
7208
7765
  case "many":
@@ -7232,8 +7789,11 @@ var Encoder = class {
7232
7789
  }
7233
7790
  return d.min >= 2 ? this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags, this.expected(deriveExpected(d.parser))) : this.emit(OP_REP, child, d.min, d.max ?? -1, sep, flags);
7234
7791
  }
7235
- case "optional":
7236
- return this.emit(OP_OPT, this.node(d.parser).ip);
7792
+ case "optional": {
7793
+ const head = this.emit(OP_OPT, this.node(d.parser).ip);
7794
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(head);
7795
+ return head;
7796
+ }
7237
7797
  case "transform": {
7238
7798
  const inner = d.parser._def;
7239
7799
  if (inner.tag === "sequence" && !this.memo.has(d.parser) && !this.pending.has(d.parser)) {
@@ -7392,6 +7952,7 @@ var Encoder = class {
7392
7952
  // lowering was correct only for a choice arm.
7393
7953
  case "attempt": {
7394
7954
  const inner = this.emit(OP_ATTEMPT, this.node(d.parser).ip);
7955
+ if (!this.failureNeedsRollback(d.parser, void 0)) this.failureRollbackCleanSites.add(inner);
7395
7956
  const fs = d.parser._meta.firstSet;
7396
7957
  if (fs.kind === "any" || matchesEmpty(d.parser)) return inner;
7397
7958
  const cls = this.charClass(fs);
@@ -7560,6 +8121,10 @@ var Encoder = class {
7560
8121
  ...this.rec ? { rec: 1 } : {},
7561
8122
  ...this.cov === void 0 ? {} : { cov: this.cov },
7562
8123
  lines: this.track ? 1 : 0
8124
+ }, void 0, {
8125
+ choiceRollbackMasks: this.choiceRollbackMasks,
8126
+ failureRollbackCleanSites: this.failureRollbackCleanSites,
8127
+ nonCommittingChoiceSites: this.nonCommittingChoiceSites
7563
8128
  });
7564
8129
  }
7565
8130
  };
@@ -7607,7 +8172,6 @@ function encodeTableProgram(ruleMap, settings = {}) {
7607
8172
  const lexicalRoots = [...names].sort().map((name) => ruleMap[name]);
7608
8173
  const resolveLexical = (name) => ruleMap[name];
7609
8174
  const capabilities = collectLexicalCapabilities(lexicalRoots, resolveLexical);
7610
- assertLexicalCapabilityClosure(lexicalRoots, capabilities, resolveLexical);
7611
8175
  const enc = new Encoder(resolvedSettings, capabilities.capabilityComplete);
7612
8176
  enc.winners = ruleMap;
7613
8177
  for (const name of names) enc.encodeRule(name, ruleMap[name]);
@@ -8740,13 +9304,17 @@ var TRI_NONE = -1;
8740
9304
  var CAP_UNKNOWN = 0;
8741
9305
  var CAP_OFF = 1;
8742
9306
  var CAP_ON = 2;
8743
- var TOP = { tri: TRI_UNKNOWN, buf: false, cap: CAP_UNKNOWN };
9307
+ var RAW_UNKNOWN = 0;
9308
+ var RAW_CAPTURE = 1;
9309
+ var RAW_OMIT = 2;
9310
+ var TOP = { tri: TRI_UNKNOWN, buf: false, raw: RAW_UNKNOWN, cap: CAP_UNKNOWN };
8744
9311
  function meet(a, b) {
8745
9312
  const tri = a.tri === b.tri ? a.tri : TRI_UNKNOWN;
8746
9313
  const buf = a.buf && b.buf;
9314
+ const raw = a.raw === b.raw ? a.raw : RAW_UNKNOWN;
8747
9315
  const cap = a.cap === b.cap ? a.cap : CAP_UNKNOWN;
8748
- if (tri === a.tri && buf === a.buf && cap === a.cap) return a;
8749
- return { tri, buf, cap };
9316
+ if (tri === a.tri && buf === a.buf && raw === a.raw && cap === a.cap) return a;
9317
+ return { tri, buf, raw, cap };
8750
9318
  }
8751
9319
  function reachableSites(code, roots) {
8752
9320
  const seen = /* @__PURE__ */ new Set();
@@ -8769,25 +9337,26 @@ function transfer(code, ip, at, hostCst) {
8769
9337
  const tri = ki < 0 ? TRI_NONE : ki;
8770
9338
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
8771
9339
  if (tri === at.tri && cap === at.cap) return at;
8772
- return { tri, buf: at.buf, cap };
9340
+ return { tri, buf: at.buf, raw: at.raw, cap };
8773
9341
  }
8774
9342
  if (op === OP_NODE || op === OP_NODE_TRACK) {
8775
9343
  const flags = code[ip + 3];
8776
9344
  const directChildren = !hostCst && op === OP_NODE && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags === 2 || flags === 18 || flags === 34);
8777
9345
  if (directChildren) {
8778
- return { tri: at.tri, buf: false, cap: CAP_OFF };
9346
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: CAP_OFF };
8779
9347
  }
8780
9348
  const cap = (flags & 4) !== 0 || hostCst ? CAP_ON : CAP_OFF;
8781
- if (at.buf && cap === at.cap) return at;
8782
- return { tri: at.tri, buf: true, cap };
9349
+ const raw = !hostCst && code[ip + 1] >= 0 && code[ip + 4] < 0 && (flags & 2) !== 0 ? RAW_OMIT : RAW_CAPTURE;
9350
+ if (at.buf && raw === at.raw && cap === at.cap) return at;
9351
+ return { tri: at.tri, buf: true, raw, cap };
8783
9352
  }
8784
9353
  if (op === OP_TOKEN) {
8785
9354
  if (at.tri === TRI_NONE && !at.buf) return at;
8786
- return { tri: TRI_NONE, buf: false, cap: at.cap };
9355
+ return { tri: TRI_NONE, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
8787
9356
  }
8788
9357
  if (op === OP_LEAF) {
8789
9358
  if (!at.buf) return at;
8790
- return { tri: at.tri, buf: false, cap: at.cap };
9359
+ return { tri: at.tri, buf: false, raw: RAW_UNKNOWN, cap: at.cap };
8791
9360
  }
8792
9361
  return at;
8793
9362
  }
@@ -8854,6 +9423,162 @@ function scalarTerminalNotChild(code, ip) {
8854
9423
  const op = code[child];
8855
9424
  return op === OP_RX || op === OP_LIT ? child : -1;
8856
9425
  }
9426
+ function leadingScalarTerminal(code, ip, minDepth = 2, throughAttempt = true, throughPeek = false) {
9427
+ const seen = /* @__PURE__ */ new Set();
9428
+ let at = ip;
9429
+ let depth = 0;
9430
+ while (!seen.has(at)) {
9431
+ seen.add(at);
9432
+ const op = code[at];
9433
+ if (op === OP_LIT || op === OP_RX) return depth >= minDepth ? at : -1;
9434
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || throughAttempt && op === OP_ATTEMPT) {
9435
+ at = code[at + 1];
9436
+ depth++;
9437
+ continue;
9438
+ }
9439
+ if (throughPeek && op === OP_PEEK) {
9440
+ at = code[at + 1];
9441
+ depth++;
9442
+ continue;
9443
+ }
9444
+ if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9445
+ at = code[at + 2];
9446
+ depth++;
9447
+ continue;
9448
+ }
9449
+ if (op === OP_SEQ || op === OP_SEQV) {
9450
+ if (code[at + 1] < 1) return -1;
9451
+ at = code[at + 2];
9452
+ depth++;
9453
+ continue;
9454
+ }
9455
+ if (op === OP_SEQX) {
9456
+ if (code[at + 2] < 1) return -1;
9457
+ at = code[at + 3];
9458
+ depth++;
9459
+ continue;
9460
+ }
9461
+ return -1;
9462
+ }
9463
+ return -1;
9464
+ }
9465
+ function leadingScalarSequence(code, ip) {
9466
+ const wholeScalar = (start) => {
9467
+ const seen2 = /* @__PURE__ */ new Set();
9468
+ let at2 = start;
9469
+ while (!seen2.has(at2)) {
9470
+ seen2.add(at2);
9471
+ const op = code[at2];
9472
+ if (op === OP_LIT || op === OP_RX) return at2;
9473
+ if (op === OP_RULE || op === OP_TOKEN || op === OP_ATTEMPT) {
9474
+ at2 = code[at2 + 1];
9475
+ continue;
9476
+ }
9477
+ if (op === OP_GATE || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9478
+ at2 = code[at2 + 2];
9479
+ continue;
9480
+ }
9481
+ if (op === OP_SEQ || op === OP_SEQV) {
9482
+ if (code[at2 + 1] !== 1) return -1;
9483
+ at2 = code[at2 + 2];
9484
+ continue;
9485
+ }
9486
+ if (op === OP_SEQX) {
9487
+ if (code[at2 + 2] !== 1) return -1;
9488
+ at2 = code[at2 + 3];
9489
+ continue;
9490
+ }
9491
+ return -1;
9492
+ }
9493
+ return -1;
9494
+ };
9495
+ const seen = /* @__PURE__ */ new Set();
9496
+ let at = ip;
9497
+ let ambientTrivia;
9498
+ while (!seen.has(at)) {
9499
+ seen.add(at);
9500
+ const op = code[at];
9501
+ if (op === OP_RULE) {
9502
+ at = code[at + 1];
9503
+ continue;
9504
+ }
9505
+ if (op === OP_SCOPE_PLAIN) {
9506
+ ambientTrivia = code[at + 1];
9507
+ at = code[at + 2];
9508
+ continue;
9509
+ }
9510
+ if (op === OP_GATE || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9511
+ at = code[at + 2];
9512
+ continue;
9513
+ }
9514
+ const n = op === OP_SEQ || op === OP_SEQV ? code[at + 1] : op === OP_SEQX ? code[at + 2] : 0;
9515
+ if (n < 3 || ambientTrivia === void 0) return void 0;
9516
+ const base = op === OP_SEQX ? at + 3 : at + 2;
9517
+ const terminals = [
9518
+ wholeScalar(code[base]),
9519
+ wholeScalar(code[base + 1]),
9520
+ wholeScalar(code[base + 2])
9521
+ ];
9522
+ return terminals.every((terminal) => terminal >= 0) ? { terminals, trivia: ambientTrivia } : void 0;
9523
+ }
9524
+ return void 0;
9525
+ }
9526
+ function leadingLiteralFamily(code, constants, ip, minDepth = 2, limit = 4) {
9527
+ const active = /* @__PURE__ */ new Set();
9528
+ const walk = (at, depth) => {
9529
+ if (active.has(at)) return void 0;
9530
+ active.add(at);
9531
+ try {
9532
+ const op = code[at];
9533
+ if (op === OP_LIT) {
9534
+ const value = constants[code[at + 1]];
9535
+ return depth >= minDepth && typeof value === "string" && value.length > 0 ? [at] : void 0;
9536
+ }
9537
+ if (op === OP_RULE || op === OP_LABEL || op === OP_TOKEN || op === OP_ATTEMPT || op === OP_PEEK) {
9538
+ return walk(code[at + 1], depth + 1);
9539
+ }
9540
+ if (op === OP_GATE || op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN || op === OP_XFORM || op === OP_NODE || op === OP_FIELD || op === OP_LEAF) {
9541
+ return walk(code[at + 2], depth + 1);
9542
+ }
9543
+ if (op === OP_SEQ || op === OP_SEQV) {
9544
+ return code[at + 1] < 1 ? void 0 : walk(code[at + 2], depth + 1);
9545
+ }
9546
+ if (op === OP_SEQX) {
9547
+ return code[at + 2] < 1 ? void 0 : walk(code[at + 3], depth + 1);
9548
+ }
9549
+ if (op !== OP_CHOICE) return void 0;
9550
+ const n = code[at + 2];
9551
+ if (n < 1) return void 0;
9552
+ const out = [];
9553
+ for (let i = 0; i < n; i++) {
9554
+ const branch = walk(code[at + 4 + i], depth + 1);
9555
+ if (branch === void 0) return void 0;
9556
+ for (const terminal of branch) {
9557
+ const value = constants[code[terminal + 1]];
9558
+ let covered = false;
9559
+ for (let j = 0; j < out.length; j++) {
9560
+ const prior = constants[code[out[j] + 1]];
9561
+ if (value.startsWith(prior)) {
9562
+ covered = true;
9563
+ break;
9564
+ }
9565
+ }
9566
+ if (covered) continue;
9567
+ for (let j = out.length - 1; j >= 0; j--) {
9568
+ const prior = constants[code[out[j] + 1]];
9569
+ if (prior.startsWith(value)) out.splice(j, 1);
9570
+ }
9571
+ out.push(terminal);
9572
+ if (out.length > limit) return void 0;
9573
+ }
9574
+ }
9575
+ return out;
9576
+ } finally {
9577
+ active.delete(at);
9578
+ }
9579
+ };
9580
+ return walk(ip, 0);
9581
+ }
8857
9582
 
8858
9583
  // src/table/emit-assembly.ts
8859
9584
  var Unemittable = class extends Error {
@@ -8935,6 +9660,16 @@ let _pfScan=null
8935
9660
  let _pfHost
8936
9661
  let _pfDepth=0
8937
9662
  const _pfFrames=[]
9663
+ let _pfTokInput
9664
+ let _pfTokPos=-1
9665
+ let _pfTokBody=-1
9666
+ let _pfTokPacked=-1
9667
+ let _pfTokValue
9668
+ let _pfTokDispatch=-1
9669
+ let _pfTokArm=-1
9670
+ let _pfTokEnd=-1
9671
+ let _pfSeqEnd=-1
9672
+ function _asciiFoldCode(c){return c>=65&&c<=90?c+32:c}
8938
9673
  function _skipTrivia(input,cur,ctx){
8939
9674
  const s=_pfScan
8940
9675
  if(s!==null&&ctx._triviaLog===undefined&&!(ctx.captureTrivia===true&&(ctx._cstBuf!==undefined||ctx._cstTriviaLog!==undefined)))return s(input,cur)
@@ -8974,17 +9709,51 @@ if(starts===undefined)return
8974
9709
  for(let i=from;i<end;i++)if(input.charCodeAt(i)===10)starts.push(i+1)
8975
9710
  ctx._lineScannedTo=end
8976
9711
  }
8977
- function _rollbackNeeded(ctx){
8978
- return ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined||ctx._cstRawChildren!==undefined||ctx._cstTriviaLog!==undefined||ctx._fields!==undefined||ctx._errors!==undefined||ctx._triviaLog!==undefined||ctx._rootTriviaLog!==undefined
9712
+ function _rollbackNeeded(ctx){
9713
+ return ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined||ctx._cstRawChildren!==undefined||ctx._cstTriviaLog!==undefined||ctx._fields!==undefined||ctx._errors!==undefined||ctx._triviaLog!==undefined||ctx._rootTriviaLog!==undefined
9714
+ }
9715
+ function _rbBuf(ctx,raw,tl,lv,lg,rt){
9716
+ const b=ctx._cstBuf
9717
+ const ra=b.raw
9718
+ if(ra!==undefined){
9719
+ if(raw===0)b.raw=undefined
9720
+ else if(raw===1){b.rawSingle=ra[0];b.raw=undefined}
9721
+ else if(ra.length!==raw)ra.length=raw
9722
+ }else if(raw===0)b.rawSingle=undefined
9723
+ const ch=b.ch
9724
+ if(ch!==undefined){
9725
+ if(lv===0)b.ch=undefined
9726
+ else if(lv===1){b.single=ch[0];b.ch=undefined}
9727
+ else if(ch.length!==lv)ch.length=lv
9728
+ }else if(lv===0)b.single=undefined
9729
+ const bt=b.tl
9730
+ if(bt!==undefined){
9731
+ if(tl===0)b.tl=undefined
9732
+ else if(bt.length!==tl)bt.length=tl
9733
+ }
9734
+ if(ctx._triviaLog!==undefined&&ctx._triviaLog.length!==lg)ctx._triviaLog.length=lg
9735
+ if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTriviaLog.length=rt
9736
+ }
9737
+ `;
9738
+ var NO_RAW_RUNTIME_PRELUDE = `
9739
+ function _pushLeafNoRawBuf(ctx,value,s,e){
9740
+ const l={_tag:'leaf',value,span:{start:s,end:e}}
9741
+ const b=ctx._cstBuf
9742
+ if(b.ch!==undefined)b.ch.push(l)
9743
+ else if(b.single!==undefined){b.ch=[b.single,l];b.single=undefined}
9744
+ else b.single=l
9745
+ b.rawLen++
8979
9746
  }
8980
- function _rbBuf(ctx,raw,tl,lv,lg,rt){
9747
+ function _pushNodeNoRawBuf(ctx,value){
8981
9748
  const b=ctx._cstBuf
8982
- const ra=b.raw
8983
- if(ra!==undefined){
8984
- if(raw===0)b.raw=undefined
8985
- else if(raw===1){b.rawSingle=ra[0];b.raw=undefined}
8986
- else if(ra.length!==raw)ra.length=raw
8987
- }else if(raw===0)b.rawSingle=undefined
9749
+ if(b.ch!==undefined)b.ch.push(value)
9750
+ else if(b.single!==undefined){b.ch=[b.single,value];b.single=undefined}
9751
+ else b.single=value
9752
+ b.rawLen++
9753
+ }
9754
+ function _rbNoRawBuf(ctx,raw,tl,lv,lg,rt){
9755
+ const b=ctx._cstBuf
9756
+ if(b.rawLen!==raw)b.rawLen=raw
8988
9757
  const ch=b.ch
8989
9758
  if(ch!==undefined){
8990
9759
  if(lv===0)b.ch=undefined
@@ -9012,11 +9781,12 @@ function sinkReads(t, s) {
9012
9781
  ${t}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${s.er ? `
9013
9782
  ${t}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
9014
9783
  }
9015
- function emitMark(t, buf, s = NO_SINKS, decl = true) {
9784
+ function emitMark(t, buf, rawMode, s = NO_SINKS, decl = true) {
9016
9785
  if (buf) {
9786
+ const raw = rawMode === RAW_OMIT ? `${t}raw=b.rawLen` : rawMode === RAW_CAPTURE ? `const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${t}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
9017
9787
  return `${decl ? `let ${t}raw=0,${t}tl=0,${t}lv=0,${t}lg=0,${t}rt=0${sinkSlots(t, s)}
9018
9788
  ` : ""}{const b=ctx._cstBuf
9019
- const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
9789
+ ${raw}
9020
9790
  const h=b.ch;${t}lv=h!==undefined?h.length:b.single!==undefined?1:0
9021
9791
  const l=b.tl;${t}tl=l!==undefined?l.length:0
9022
9792
  ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
@@ -9026,7 +9796,7 @@ ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t,
9026
9796
  ` : `${t}n=false
9027
9797
  `}{const b=ctx._cstBuf
9028
9798
  if(b!==undefined){
9029
- const r=b.raw;${t}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
9799
+ const r=b.raw;${t}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
9030
9800
  const h=b.ch;${t}lv=h!==undefined?h.length:b.single!==undefined?1:0
9031
9801
  const l=b.tl;${t}tl=l!==undefined?l.length:0
9032
9802
  ${t}n=true
@@ -9041,14 +9811,16 @@ ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
9041
9811
  ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${sinkReads(t, s)}
9042
9812
  }}`;
9043
9813
  }
9044
- function emitRollback(t, buf, s = NO_SINKS) {
9814
+ function emitRollback(t, buf, rawMode, s = NO_SINKS) {
9045
9815
  const fd = s.fd ? `
9046
9816
  if(ctx._fields!==undefined&&ctx._fields.length!==${t}fd)ctx._fields.length=${t}fd` : "";
9047
9817
  const er = s.er ? `
9048
9818
  if(ctx._errors!==undefined&&ctx._errors.length!==${t}er)ctx._errors.length=${t}er` : "";
9049
- if (buf) return `_rbBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
9050
- if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,0,undefined,${t}lg,${t}rt)`;
9051
- 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)}`;
9819
+ if (buf && rawMode === RAW_OMIT) return `_rbNoRawBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
9820
+ if (buf && rawMode === RAW_CAPTURE) return `_rbBuf(ctx,${t}raw,${t}tl,${t}lv,${t}lg,${t}rt)${fd}${er}`;
9821
+ if (buf) return `rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "undefined"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)`;
9822
+ if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,undefined,undefined,${t}lg,${t}rt)`;
9823
+ return `if(${t}n){rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "undefined"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)}`;
9052
9824
  }
9053
9825
  function emitTerm(callee, dst, t, l, skip) {
9054
9826
  const fast = `const ${t}v=${callee}(input,cur,ctx)
@@ -9106,37 +9878,111 @@ function rebuildPools(cc, fx, disp, plan) {
9106
9878
  })
9107
9879
  };
9108
9880
  }
9109
- function emitAssemblySource(t, prog, cfg, extraIps = []) {
9110
- const { code, k, disp, dsp, triviaLabelled } = t;
9881
+ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false) {
9882
+ const { code, k, fx, disp, dsp, triviaLabelled } = t;
9111
9883
  const swapLegal = !cfg.trackLines;
9112
9884
  const hostCst = cfg.hostCst;
9113
9885
  const REC2 = prog.rec === 1 && cfg.tolerant;
9114
9886
  if (cfg.coverage) throw new Unemittable("a coverage assembly");
9115
9887
  const roots = [...Object.values(prog.rules), ...extraIps];
9888
+ const reachable = [...reachableSites(code, roots)];
9116
9889
  const labels = computeSiteLabels(code, roots, hostCst);
9117
9890
  const scalarSpecs = /* @__PURE__ */ new Set();
9891
+ const largeChoiceScalarSpecs = /* @__PURE__ */ new Set();
9892
+ const largeChoiceLiteralFamilies = /* @__PURE__ */ new Map();
9893
+ const largeChoiceScalarSequences = /* @__PURE__ */ new Map();
9894
+ const tokenChoiceCandidates = /* @__PURE__ */ new Map();
9895
+ const tokenChoiceDispatches = /* @__PURE__ */ new Set();
9896
+ const tokenChoiceBodies = /* @__PURE__ */ new Set();
9118
9897
  if (!hostCst && !cfg.tolerant && !cfg.probe && !cfg.coverage && !cfg.trackLines) {
9119
- for (const ip of reachableSites(code, roots)) {
9120
- if (code[ip] !== OP_NODE) continue;
9121
- const child = scalarTerminalNodeChild(code, ip);
9122
- if (child >= 0) scalarSpecs.add(code[child + 1]);
9898
+ for (const ip of reachable) {
9899
+ if (code[ip] === OP_NODE) {
9900
+ const child = scalarTerminalNodeChild(code, ip);
9901
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
9902
+ continue;
9903
+ }
9904
+ if (code[ip] !== OP_CHOICE || disp[code[ip + 1]].exclusive) continue;
9905
+ const n = code[ip + 2];
9906
+ for (let i = 0; i < n; i++) {
9907
+ const armIp = code[ip + 4 + i];
9908
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
9909
+ if (n === 2 || n === 3) {
9910
+ if (child >= 0) scalarSpecs.add(code[child + 1]);
9911
+ continue;
9912
+ }
9913
+ if (child >= 0) {
9914
+ const spec = k[code[child + 1]];
9915
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
9916
+ largeChoiceScalarSpecs.add(code[child + 1]);
9917
+ continue;
9918
+ }
9919
+ }
9920
+ const family = leadingLiteralFamily(code, k, armIp);
9921
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
9922
+ const value = k[code[terminal + 1]];
9923
+ return typeof value === "string" && value.length >= 2;
9924
+ })) {
9925
+ largeChoiceLiteralFamilies.set(armIp, family);
9926
+ }
9927
+ const sequence6 = leadingScalarSequence(code, armIp);
9928
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || swapLegal && t.triviaScan[sequence6.trivia] != null)) {
9929
+ largeChoiceScalarSequences.set(armIp, sequence6);
9930
+ }
9931
+ }
9932
+ let candidate;
9933
+ let ambiguous = false;
9934
+ for (let i = 0; i < n; i++) {
9935
+ const armIp = code[ip + 4 + i];
9936
+ if (code[armIp] !== OP_XFORM) continue;
9937
+ const dispatchIp = code[armIp + 2];
9938
+ if (code[dispatchIp] !== OP_DISPATCH) continue;
9939
+ const selectorIp = code[dispatchIp + 1];
9940
+ if (code[selectorIp] !== OP_LEX_BODY) continue;
9941
+ if (candidate !== void 0) {
9942
+ ambiguous = true;
9943
+ break;
9944
+ }
9945
+ candidate = { arm: i, dispatchIp };
9946
+ }
9947
+ if (!ambiguous && candidate !== void 0) {
9948
+ tokenChoiceCandidates.set(ip, candidate);
9949
+ tokenChoiceDispatches.add(candidate.dispatchIp);
9950
+ tokenChoiceBodies.add(code[code[candidate.dispatchIp + 1] + 1]);
9951
+ }
9123
9952
  }
9124
9953
  }
9125
- const sinks = (() => {
9126
- let fd = false;
9127
- let er = REC2;
9128
- for (const ip of reachableSites(code, roots)) {
9129
- const op = code[ip];
9130
- if (op === OP_SCAN) {
9131
- fd = true;
9132
- er = true;
9133
- break;
9954
+ const needsNoRawPrelude = !hostCst && reachable.some((ip) => {
9955
+ const op = code[ip];
9956
+ return (op === OP_NODE || op === OP_NODE_TRACK) && code[ip + 1] >= 0 && code[ip + 4] < 0 && (code[ip + 3] & 2) !== 0;
9957
+ });
9958
+ const sinkSites = reachable;
9959
+ const sinkBits = /* @__PURE__ */ new Map();
9960
+ for (const ip of sinkSites) {
9961
+ const op = code[ip];
9962
+ sinkBits.set(
9963
+ ip,
9964
+ op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC2 && (op === OP_REP || op === OP_REPV) ? 2 : 0)
9965
+ );
9966
+ }
9967
+ const sinkKids = [];
9968
+ let sinkChanged = true;
9969
+ while (sinkChanged) {
9970
+ sinkChanged = false;
9971
+ for (const ip of sinkSites) {
9972
+ let bits = sinkBits.get(ip) ?? 0;
9973
+ sinkKids.length = 0;
9974
+ childSlots(code, ip, sinkKids);
9975
+ for (let i = 0; i < sinkKids.length; i++) bits |= sinkBits.get(sinkKids[i]) ?? 0;
9976
+ if (bits !== sinkBits.get(ip)) {
9977
+ sinkBits.set(ip, bits);
9978
+ sinkChanged = true;
9134
9979
  }
9135
- if (op === OP_FIELD) fd = true;
9136
- else if (op === OP_EXPECT) er = true;
9137
9980
  }
9138
- return { fd, er };
9139
- })();
9981
+ }
9982
+ const sinksAt = (ip) => {
9983
+ const bits = sinkBits.get(ip) ?? 0;
9984
+ return bits === 0 ? NO_SINKS : { fd: (bits & 1) !== 0, er: (bits & 2) !== 0 };
9985
+ };
9140
9986
  const bodies = [];
9141
9987
  const byIp = /* @__PURE__ */ new Map();
9142
9988
  const reached = /* @__PURE__ */ new Set();
@@ -9163,9 +10009,117 @@ function emitAssemblySource(t, prog, cfg, extraIps = []) {
9163
10009
  const fxRef = (i) => hoist("fx", `FX[${i}]`);
9164
10010
  const fnRef = (i) => hoist("fn", `FNS[${i}]`);
9165
10011
  const recognizerRef = (i) => hoist("rec", `RECOG[${i}]`);
10012
+ const scalarSequenceRefs = /* @__PURE__ */ new Map();
10013
+ const scalarSequenceRef = (sequence6) => {
10014
+ const key = `${sequence6.trivia}:${sequence6.terminals.map((terminal) => code[terminal + 1]).join(",")}`;
10015
+ const prior = scalarSequenceRefs.get(key);
10016
+ if (prior !== void 0) return prior;
10017
+ const recognizers = sequence6.terminals.map((terminal) => recognizerRef(code[terminal + 1]));
10018
+ const expected = sequence6.terminals.map((terminal) => fxRef(code[terminal + 2]));
10019
+ const scan = sequence6.trivia < 0 ? void 0 : hoist("ts", `TRIVIASCAN[${sequence6.trivia}]`);
10020
+ const name = `_sd${scalarSequenceRefs.size}_`;
10021
+ const steps = recognizers.map((recognize, i) => `${i === 0 ? "let " : ""}at=${i === 0 ? "pos" : scan === void 0 ? "cur" : `${scan}(input,cur)`}
10022
+ ${i === 0 ? "let " : ""}cur=${recognize}(input,at)
10023
+ if(cur<0){_pfSeqEnd=at;return ${~i}}`).join("\n");
10024
+ choiceDefs.push(`function ${name}(input,pos){
10025
+ ${steps}
10026
+ return cur
10027
+ }`);
10028
+ const made = { name, expected };
10029
+ scalarSequenceRefs.set(key, made);
10030
+ return made;
10031
+ };
9166
10032
  const sentRef = (cls) => cls < 0 ? "undefined" : hoist("sent", `SENTS[${cls}]`);
9167
10033
  let uid = 0;
9168
10034
  const tmp = () => `_t${uid++}_`;
10035
+ const dispatchClaim = (m) => {
10036
+ switch (m[0]) {
10037
+ case 0:
10038
+ return `key.startsWith(${q(m[1])})`;
10039
+ case 1:
10040
+ return `key.endsWith(${q(m[1])})`;
10041
+ case 3:
10042
+ return `asciiFoldKey(key).startsWith(${q(m[1])})`;
10043
+ case 4:
10044
+ return `asciiFoldKey(key).endsWith(${q(m[1])})`;
10045
+ default: {
10046
+ if (!m[2].includes("g") && !m[2].includes("y")) {
10047
+ try {
10048
+ new RegExp(m[1], m[2]);
10049
+ return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
10050
+ } catch {
10051
+ }
10052
+ }
10053
+ return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
10054
+ }
10055
+ }
10056
+ };
10057
+ const tokenDecisionRefs = /* @__PURE__ */ new Map();
10058
+ function tokenDecisionFor(dispatchIp) {
10059
+ const prior = tokenDecisionRefs.get(dispatchIp);
10060
+ if (prior !== void 0) return prior;
10061
+ const selectorIp = code[dispatchIp + 1];
10062
+ const body = code[selectorIp + 1];
10063
+ const lineFlags = code[selectorIp + 4];
10064
+ const hasSuffix = (lineFlags & 4) !== 0;
10065
+ const di = code[dispatchIp + 2];
10066
+ const spec = dsp[di];
10067
+ const n = code[dispatchIp + 5];
10068
+ validateDispatchSpec(spec, n, code[dispatchIp + 4]);
10069
+ const recognize = hoist("lex", `LEX[${body}]`);
10070
+ const bk = hoist("bk", `DSP[${di}].byKey`);
10071
+ const expected = hoist("dx", `DSP[${di}].expected`);
10072
+ const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
10073
+ ` : "";
10074
+ const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
10075
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
10076
+ }
10077
+ `;
10078
+ const foldedEntries = [...spec.byFold.entries()];
10079
+ const fixedFunctionChoice = spec.byKey.size === 0 && foldedEntries.length === 1 && spec.match.length === 1 && spec.match[0][0] === 2 && spec.match[0][1] === "^(?!(?:url|calc)\\($).+\\($" && spec.match[0][2] === "i" && code[dispatchIp + 3] < 0;
10080
+ const foldedRangeEquals = (value) => {
10081
+ const folded = value.replace(/[A-Z]/g, (c) => c.toLowerCase());
10082
+ return `e-pos===${folded.length}&&${[...folded].map((c, i) => {
10083
+ const cc = c.charCodeAt(0);
10084
+ return `_asciiFoldCode(input.charCodeAt(pos+${i}))===${cc}`;
10085
+ }).join("&&")}`;
10086
+ };
10087
+ const classify = fixedFunctionChoice ? (() => {
10088
+ const [exact, exactArm] = foldedEntries[0];
10089
+ const genericArm = spec.match[0][3];
10090
+ return `let arm
10091
+ if(${foldedRangeEquals(exact)})arm=${exactArm}
10092
+ else if(sm&&e>pos+1){
10093
+ let clean=true
10094
+ for(let i=pos;i<e;i++){const c=input.charCodeAt(i);if(c===10||c===13||c===0x2028||c===0x2029){clean=false;break}}
10095
+ if(clean&&!(${foldedRangeEquals("url(")})&&!(${foldedRangeEquals("calc(")}))arm=${genericArm}
10096
+ }`;
10097
+ })() : `const key=input.slice(pos,e)
10098
+ let arm=${bk}.get(key)
10099
+ ${fold}${chain}`;
10100
+ const name = `_td${tokenDecisionRefs.size}_`;
10101
+ choiceDefs.push(`function ${name}(input,pos){
10102
+ const r=${recognize}(input,pos)
10103
+ if(r<0)return -1
10104
+ const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
10105
+ ${classify}
10106
+ if(arm===undefined){
10107
+ ${code[dispatchIp + 3] < 0 ? "_pfTokEnd=e;return 0" : `arm=${n}`}
10108
+ }
10109
+ ${fixedFunctionChoice ? "const key=input.slice(pos,e)" : ""}
10110
+ _pfTokInput=input
10111
+ _pfTokPos=pos
10112
+ _pfTokBody=${body}
10113
+ _pfTokPacked=r
10114
+ _pfTokValue=key
10115
+ _pfTokDispatch=${dispatchIp}
10116
+ _pfTokArm=arm
10117
+ return 1
10118
+ }`);
10119
+ const made = { name, expected };
10120
+ tokenDecisionRefs.set(dispatchIp, made);
10121
+ return made;
10122
+ }
9169
10123
  function skipFor(l) {
9170
10124
  if (l.tri < 0) return "_skipTrivia";
9171
10125
  const ki = l.tri;
@@ -9253,7 +10207,8 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
9253
10207
  const op = code[ip];
9254
10208
  const head = `function ${fname}(input,pos,ctx){`;
9255
10209
  const L = labels.at(ip);
9256
- const pushLeaf = L.buf && !cfg.trackLines ? "_pushLeafBuf" : "_pushLeaf";
10210
+ const sinks = sinksAt(ip);
10211
+ const pushLeaf = L.buf && !cfg.trackLines ? L.raw === RAW_OMIT ? "_pushLeafNoRawBuf" : L.raw === RAW_CAPTURE ? "_pushLeafBuf" : "_pushLeaf" : "_pushLeaf";
9257
10212
  const captureLeaf = (value) => {
9258
10213
  const call = `${pushLeaf}(ctx,${value},pos,e)`;
9259
10214
  return L.buf ? call : `if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)${call}`;
@@ -9504,20 +10459,24 @@ return out
9504
10459
  }`;
9505
10460
  }
9506
10461
  case OP_LEX_BODY: {
9507
- const recognize = hoist("lex", `LEX[${code[ip + 1]}]`);
10462
+ const body = code[ip + 1];
10463
+ const recognize = hoist("lex", `LEX[${body}]`);
9508
10464
  const expected = fxRef(code[ip + 2]);
9509
10465
  const suffixExpected = fxRef(code[ip + 3]);
9510
10466
  const lineFlags = code[ip + 4];
9511
10467
  const hasSuffix = (lineFlags & 4) !== 0;
10468
+ const pending = tokenChoiceBodies.has(body);
9512
10469
  return `${head}
9513
- const r=${recognize}(input,pos)
10470
+ ${pending ? `const tp=_pfTokBody===${body}&&_pfTokInput===input&&_pfTokPos===pos
10471
+ const r=tp?_pfTokPacked:${recognize}(input,pos)` : `const r=${recognize}(input,pos)`}
9514
10472
  if(r<0){ctx._fe=pos;ctx._fx=${expected};if(ctx._probe!==undefined)failAt(ctx,${expected},pos);return FAIL}
9515
10473
  const sm=${hasSuffix ? "r%2===1" : "false"},e=(r-(sm?1:0))/2
9516
10474
  ${(lineFlags & 1) !== 0 ? "_trackLines(ctx,input,sm?e-1:e)" : ""}
9517
10475
  ${hasSuffix ? "ctx._fc=false" : ""}
9518
10476
  ${hasSuffix && (lineFlags & 2) !== 0 ? "if(sm)_trackLines(ctx,input,e)" : ""}
9519
10477
  ${hasSuffix ? `if(!sm){ctx._fe=e;ctx._fx=${suffixExpected};if(ctx._probe!==undefined)failAt(ctx,${suffixExpected},e)}` : ""}
9520
- const v=input.slice(pos,e)
10478
+ const v=${pending ? "tp?_pfTokValue:" : ""}input.slice(pos,e)
10479
+ ${pending ? "if(tp){_pfTokBody=-1;_pfTokValue=undefined}" : ""}
9521
10480
  if(ctx._cstBuf!==undefined||ctx._cstLeaves!==undefined)pushCstLeaf(ctx,{_tag:'leaf',value:v,span:{start:pos,end:e}})
9522
10481
  EC.e=e
9523
10482
  return v
@@ -9573,12 +10532,13 @@ return v
9573
10532
  /* ── transaction ─────────────────────────────────────────────────────── */
9574
10533
  case OP_ATTEMPT: {
9575
10534
  const child = link(code[ip + 1]);
10535
+ const clean = !REC2 && failureRollbackClean(prog, ip);
9576
10536
  const p = tmp();
9577
10537
  return `${head}
9578
- ${emitMark(p, L.buf, sinks)}
10538
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
9579
10539
  const v=${child}(input,pos,ctx)
9580
10540
  if(v!==FAIL)return v
9581
- ${emitRollback(p, L.buf, sinks)}
10541
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
9582
10542
  if(ctx._fc===true)return FAIL
9583
10543
  ctx._fe=pos
9584
10544
  return FAIL
@@ -9601,9 +10561,9 @@ return FAIL
9601
10561
  const xf = fxRef(code[ip + 2]);
9602
10562
  const p = tmp();
9603
10563
  return `${head}
9604
- ${emitMark(p, L.buf, sinks)}
10564
+ ${emitMark(p, L.buf, L.raw, sinks)}
9605
10565
  const v=${child}(input,pos,ctx)
9606
- ${emitRollback(p, L.buf, sinks)}
10566
+ ${emitRollback(p, L.buf, L.raw, sinks)}
9607
10567
  if(v===FAIL){EC.e=pos;return null}
9608
10568
  ctx._fe=pos
9609
10569
  ctx._fx=${xf}
@@ -9615,9 +10575,9 @@ return FAIL
9615
10575
  const xf = fxRef(code[ip + 2]);
9616
10576
  const p = tmp();
9617
10577
  return `${head}
9618
- ${emitMark(p, L.buf, sinks)}
10578
+ ${emitMark(p, L.buf, L.raw, sinks)}
9619
10579
  const v=${child}(input,pos,ctx)
9620
- ${emitRollback(p, L.buf, sinks)}
10580
+ ${emitRollback(p, L.buf, L.raw, sinks)}
9621
10581
  if(v===FAIL){ctx._fe=pos;ctx._fx=${xf};return FAIL}
9622
10582
  EC.e=pos
9623
10583
  return null
@@ -9625,14 +10585,15 @@ return null
9625
10585
  }
9626
10586
  case OP_OPT: {
9627
10587
  const child = link(code[ip + 1]);
10588
+ const clean = !REC2 && failureRollbackClean(prog, ip);
9628
10589
  const p = tmp();
9629
10590
  return `${head}
9630
- ${emitMark(p, L.buf, sinks)}
10591
+ ${clean ? "" : emitMark(p, L.buf, L.raw, sinks)}
9631
10592
  ctx._fc=false
9632
10593
  const v=${child}(input,pos,ctx)
9633
10594
  if(v===FAIL){
9634
10595
  if(ctx._fc===true)return FAIL
9635
- ${emitRollback(p, L.buf, sinks)}
10596
+ ${clean ? "" : emitRollback(p, L.buf, L.raw, sinks)}
9636
10597
  EC.e=pos
9637
10598
  return null
9638
10599
  }
@@ -9731,57 +10692,193 @@ return FAIL
9731
10692
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
9732
10693
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
9733
10694
  const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
10695
+ const tokenCandidate = tokenChoiceCandidates.get(ip);
10696
+ const pretests = Array.from({ length: n }, (_, i) => {
10697
+ if (tokenCandidate?.arm === i) {
10698
+ return { token: tokenDecisionFor(tokenCandidate.dispatchIp) };
10699
+ }
10700
+ const terminal = leadingScalarTerminal(code, code[base + i], 2, true, true);
10701
+ if (terminal >= 0) {
10702
+ const spec = code[terminal + 1];
10703
+ if ((n === 2 || n === 3 ? scalarSpecs : largeChoiceScalarSpecs).has(spec)) {
10704
+ return { scalar: [recognizerRef(spec)] };
10705
+ }
10706
+ }
10707
+ const family = largeChoiceLiteralFamilies.get(code[base + i]);
10708
+ if (family !== void 0) {
10709
+ return { scalar: family.map((member) => recognizerRef(code[member + 1])) };
10710
+ }
10711
+ const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
10712
+ return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
10713
+ });
9734
10714
  const maskable = n <= 32;
9735
10715
  const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
9736
10716
  if (maskable) maskPlan.push(~di);
9737
10717
  const p = tmp();
9738
- const catchName = maskable ? `_cx${uid++}_` : "";
9739
- if (maskable) {
10718
+ const encodedRollbackMask = choiceRollbackMask(prog, ip) ?? -1;
10719
+ const rollbackMask = REC2 ? -1 : encodedRollbackMask;
10720
+ const hasRollback = rollbackMask !== 0;
10721
+ const startFailureExact = arms.every((_arm, i) => {
10722
+ const terminal = leadingScalarTerminal(code, code[base + i], 0, false);
10723
+ if (terminal < 0) return false;
10724
+ const op2 = code[terminal];
10725
+ const spec = k[code[terminal + 1]];
10726
+ const terminalFx = fx[code[terminal + 2]];
10727
+ const armFx = fx[code[base + n + i]];
10728
+ if (terminalFx.length !== armFx.length || terminalFx.some((expected2, at) => expected2 !== armFx[at])) return false;
10729
+ if (op2 === OP_LIT) return typeof spec === "string" && spec.length > 0;
10730
+ return op2 === OP_RX && spec instanceof RegExp && !regexCanMatchEmpty(spec.source);
10731
+ });
10732
+ const rollbackFor = (i) => rollbackMask === -1 || (rollbackMask & 1 << i) !== 0 ? emitRollback(p, L.buf, L.raw, sinks) : "";
10733
+ if (choiceCannotCommit(prog, ip) && !startFailureExact) {
10734
+ const deepAt = Array.from({ length: n }, () => tmp());
10735
+ const deepFx = Array.from({ length: n }, () => tmp());
10736
+ const remember = (i, at, expectedSet) => `${deepAt[i]}=${at};${deepFx[i]}=${expectedSet}`;
10737
+ const lazyArms = (ascii) => arms.map((arm, i) => {
10738
+ const pretest = pretests[i];
10739
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10740
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
10741
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10742
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10743
+ const gate2 = ascii ? `(bits&${1 << i})!==0${condition}` : `(${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}`;
10744
+ const routeMiss = pretest?.token === void 0 ? "" : `
10745
+ if(${decision}===0){
10746
+ ctx._fc=false
10747
+ {const at=_pfTokEnd
10748
+ ${remember(i, "at", pretest.token.expected)}}
10749
+ }`;
10750
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
10751
+ else if(${ascii ? `(bits&${1 << i})!==0&&` : ""}${decision}<0){
10752
+ ctx._fc=false
10753
+ {const at=_pfSeqEnd
10754
+ ${remember(i, "at", pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("") + pretest.sequence.expected.at(-1))}}
10755
+ }`;
10756
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10757
+ `}if(${gate2}){
10758
+ ctx._fc=false
10759
+ {const v=${arm}(input,pos,ctx)
10760
+ if(v!==FAIL)return v}
10761
+ {const at=ctx._fe??pos
10762
+ ${remember(i, "at", "ctx._fx")}}
10763
+ ${rollbackFor(i)}
10764
+ }${routeMiss}${sequenceMiss}`;
10765
+ }).join("\n");
10766
+ const merge2 = deepAt.map((at, i) => `{const at=${at}??pos
10767
+ const ex=${at}===undefined?${expected[i]}:${deepFx[i]}
10768
+ if(at>best){best=at;acc=_accSet(ex,undefined)}
10769
+ else if(at===best)acc=_accSet(ex,acc)
10770
+ }`).join("\n");
10771
+ const finish = `let best=pos,acc
10772
+ ${merge2}
10773
+ ctx._fe=pos;ctx._fx=acc??${choiceFx}
10774
+ return FAIL`;
10775
+ return `${head}
10776
+ const c=lead(input,pos)
10777
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
10778
+ ${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
10779
+ ${maskable ? `if(c<128){
10780
+ const bits=${maskName}[c<0?128:c]
10781
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10782
+ ${lazyArms(true)}
10783
+ }else{
10784
+ ${lazyArms(false)}
10785
+ }
10786
+ ` : lazyArms(false)}
10787
+ ${finish}
10788
+ }`;
10789
+ }
10790
+ const needsCatch = maskable || startFailureExact;
10791
+ const catchName = needsCatch ? `_cx${uid++}_` : "";
10792
+ if (needsCatch) {
9740
10793
  const catchCases = expected.map((e, i) => `case ${i}:if(target<=${i})return acc;acc=_accSet(${e},acc)`).join("\n");
9741
10794
  choiceDefs.push(`function ${catchName}(target,prev,acc){switch(prev){
9742
10795
  ${catchCases}
9743
10796
  }return acc}`);
9744
10797
  }
9745
10798
  const maskArms = maskable ? arms.map((arm, i) => {
9746
- return `if((bits&${1 << i})!==0){
10799
+ const pretest = pretests[i];
10800
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10801
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
10802
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10803
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10804
+ const routeMiss = pretest?.token === void 0 ? "" : `
10805
+ if(${decision}===0){
10806
+ ctx._fc=false
10807
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10808
+ prev=${i + 1}`}
10809
+ {const at=_pfTokEnd
10810
+ if(at>best){best=at;acc=undefined}
10811
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)}
10812
+ }`;
10813
+ const sequenceMiss = pretest?.sequence === void 0 ? "" : `
10814
+ else if((bits&${1 << i})!==0&&${decision}<0){
10815
+ ctx._fc=false
10816
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10817
+ prev=${i + 1}`}
10818
+ {const at=_pfSeqEnd
10819
+ if(at>best){best=at;acc=undefined}
10820
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)}
10821
+ }`;
10822
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10823
+ `}if((bits&${1 << i})!==0${condition}){
9747
10824
  ctx._fc=false
9748
10825
  {const v=${arm}(input,pos,ctx)
9749
10826
  if(v!==FAIL)return v}
9750
- if(best===pos)acc=${catchName}(${i},prev,acc)
9751
- prev=${i + 1}
10827
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${i},prev,acc)
10828
+ prev=${i + 1}`}
9752
10829
  {const at=ctx._fe??pos
9753
10830
  if(at>best){best=at;acc=undefined}
9754
- if(at===best)acc=_accSet(ctx._fx,acc)}
9755
- if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
9756
- ${emitRollback(p, L.buf, sinks)}
9757
- }`;
10831
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
10832
+ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
10833
+ ${rollbackFor(i)}
10834
+ }${routeMiss}${sequenceMiss}`;
9758
10835
  }).join("\n") : "";
9759
- const generalArms = arms.map((arm, i) => `if(${gateRefs[i]}===null||classHas(${gateRefs[i]},c)){
10836
+ const generalArms = arms.map((arm, i) => {
10837
+ const pretest = pretests[i];
10838
+ const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10839
+ const scalarCondition = pretest?.scalar === void 0 ? "" : pretest.scalar.length === 1 ? `&&${pretest.scalar[0]}(input,pos)>=0` : `&&(${pretest.scalar.map((recognize) => `${recognize}(input,pos)>=0`).join("||")})`;
10840
+ const sequenceCondition = pretest?.sequence === void 0 ? "" : `&&(${decision}=${pretest.sequence.name}(input,pos))>=0`;
10841
+ const condition = pretest?.token !== void 0 ? `&&(${decision}=${pretest.token.name}(input,pos))>0` : scalarCondition || sequenceCondition;
10842
+ const miss = pretest?.sequence !== void 0 ? `else if(${decision}<0){
10843
+ ctx._fc=false
10844
+ const at=_pfSeqEnd
10845
+ if(at>best){best=at;acc=undefined}
10846
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.sequence.expected.map((value, at) => `${decision}===${~at}?${value}:`).join("")}${pretest.sequence.expected.at(-1)},acc)
10847
+ }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}` : pretest?.token === void 0 ? startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)` : `else if(${decision}===0){
10848
+ ctx._fc=false
10849
+ const at=_pfTokEnd
10850
+ if(at>best){best=at;acc=undefined}
10851
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(${pretest.token.expected},acc)
10852
+ }${startFailureExact ? "" : `else if(best===pos)acc=_accSet(${expected[i]},acc)`}`;
10853
+ return `${decision === "" ? "" : `let ${decision}=${pretest?.sequence === void 0 ? -1 : 0}
10854
+ `}if((${gateRefs[i]}===null||classHas(${gateRefs[i]},c))${condition}){
9760
10855
  ctx._fc=false
9761
10856
  {const v=${arm}(input,pos,ctx)
9762
10857
  if(v!==FAIL)return v}
9763
10858
  {const at=ctx._fe??pos
9764
10859
  if(at>best){best=at;acc=undefined}
9765
- if(at===best)acc=_accSet(ctx._fx,acc)}
9766
- if(ctx._fc===true){if(acc!==undefined)ctx._fx=acc;return FAIL}
9767
- ${emitRollback(p, L.buf, sinks)}
9768
- }else if(best===pos)acc=_accSet(${expected[i]},acc)`).join("\n");
10860
+ if(at===best${startFailureExact ? "&&at>pos" : ""})acc=_accSet(ctx._fx,acc)}
10861
+ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0,undefined);acc=_accSet(ctx._fx,acc)}` : ""}if(acc!==undefined)ctx._fx=acc;return FAIL}
10862
+ ${rollbackFor(i)}
10863
+ }${miss}`;
10864
+ }).join("\n");
9769
10865
  return `${head}
9770
10866
  const c=lead(input,pos)
9771
- ${emitMark(p, L.buf, sinks)}
10867
+ ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
9772
10868
  let acc
9773
10869
  let best=pos
9774
10870
  ${maskable ? `if(c<128){
9775
10871
  const bits=${maskName}[c<0?128:c]
9776
- let prev=0
10872
+ if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10873
+ ${startFailureExact ? "" : "let prev=0"}
9777
10874
  ${maskArms}
9778
- if(best===pos)acc=${catchName}(${n},prev,acc)
9779
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
10875
+ ${startFailureExact ? "" : `if(best===pos)acc=${catchName}(${n},prev,acc)`}
10876
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
9780
10877
  return FAIL
9781
10878
  }
9782
10879
  ` : ""}
9783
10880
  ${generalArms}
9784
- ctx._fe=pos;ctx._fx=acc??${choiceFx}
10881
+ ctx._fe=pos;ctx._fx=${startFailureExact ? `best===pos?${choiceFx}:acc??${choiceFx}` : `acc??${choiceFx}`}
9785
10882
  return FAIL
9786
10883
  }`;
9787
10884
  }
@@ -9800,30 +10897,8 @@ return FAIL
9800
10897
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
9801
10898
  const bk = hoist("bk", `DSP[${di}].byKey`);
9802
10899
  const dx = hoist("dx", `DSP[${di}].expected`);
9803
- const claims = (m) => {
9804
- switch (m[0]) {
9805
- case 0:
9806
- return `key.startsWith(${q(m[1])})`;
9807
- case 1:
9808
- return `key.endsWith(${q(m[1])})`;
9809
- case 3:
9810
- return `asciiFoldKey(key).startsWith(${q(m[1])})`;
9811
- case 4:
9812
- return `asciiFoldKey(key).endsWith(${q(m[1])})`;
9813
- default: {
9814
- if (!m[2].includes("g") && !m[2].includes("y")) {
9815
- try {
9816
- new RegExp(m[1], m[2]);
9817
- return `${hoist("dm", `new RegExp(${q(m[1])},${q(m[2])})`)}.test(key)`;
9818
- } catch {
9819
- }
9820
- }
9821
- return `new RegExp(${q(m[1])},${q(m[2])}).test(key)`;
9822
- }
9823
- }
9824
- };
9825
10900
  const chain = spec.match.length === 0 ? "" : `if(arm===undefined){
9826
- ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}`).join("\n")}
10901
+ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${dispatchClaim(m)})arm=${m[3]}`).join("\n")}
9827
10902
  }
9828
10903
  `;
9829
10904
  const fold = spec.byFold.size > 0 ? `if(arm===undefined)arm=${hoist("bf", `DSP[${di}].byFold`)}.get(asciiFoldKey(key))
@@ -9831,33 +10906,43 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
9831
10906
  const m1 = tmp();
9832
10907
  const m2 = tmp();
9833
10908
  const routedCall = (target) => `{const savedRouted=ctx._routed
9834
- ${emitRollback(m1, L.buf, sinks)}
9835
- ${emitMark(m2, L.buf, sinks, false)}
10909
+ ${emitRollback(m1, L.buf, L.raw, sinks)}
10910
+ ${emitMark(m2, L.buf, L.raw, sinks, false)}
9836
10911
  ctx._routed={value:key,span:{start:pos,end:selEnd}}
9837
10912
  try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
9838
10913
  break}`;
9839
10914
  const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
9840
10915
  const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
9841
10916
  const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
10917
+ const armSelection = tokenChoiceDispatches.has(ip) ? `const tp=_pfTokDispatch===${ip}&&_pfTokInput===input&&_pfTokPos===pos
10918
+ let arm
10919
+ if(tp){
10920
+ arm=_pfTokArm
10921
+ _pfTokDispatch=-1
10922
+ _pfTokInput=undefined
10923
+ if(arm===${n})arm=undefined
10924
+ }else{
10925
+ arm=${bk}.get(key)
10926
+ ${fold}${chain}}` : `let arm=${bk}.get(key)
10927
+ ${fold}${chain}`;
9842
10928
  return `${head}
9843
- ${emitMark(m1, L.buf, sinks)}
10929
+ ${emitMark(m1, L.buf, L.raw, sinks)}
9844
10930
  const sv=${selector}(input,pos,ctx)
9845
10931
  if(sv===FAIL)return FAIL
9846
10932
  const selEnd=EC.e
9847
10933
  const key=sv
9848
- let arm=${bk}.get(key)
9849
- ${fold}${chain}
10934
+ ${armSelection}
9850
10935
  if(arm===undefined){
9851
10936
  ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
9852
10937
  }
9853
- ${emitMark(m2, L.buf, sinks)}
10938
+ ${emitMark(m2, L.buf, L.raw, sinks)}
9854
10939
  let v
9855
10940
  switch(arm){
9856
10941
  ${armCases}
9857
10942
  ${fallbackCase}
9858
10943
  }
9859
10944
  if(v===FAIL){
9860
- ${emitRollback(m2, L.buf, sinks)}
10945
+ ${emitRollback(m2, L.buf, L.raw, sinks)}
9861
10946
  ctx._fc=true
9862
10947
  return FAIL
9863
10948
  }
@@ -9893,23 +10978,25 @@ return [key,v]
9893
10978
  const skip = skipFor(L);
9894
10979
  const knownTrivia = L.tri === TRI_NONE ? false : L.tri !== TRI_UNKNOWN ? true : void 0;
9895
10980
  const hasTrivia = knownTrivia === void 0 ? "hasTrivia" : String(knownTrivia);
9896
- const pfd = sinks.fd ? `${p}fd` : "0";
10981
+ const pfd = sinks.fd ? `${p}fd` : "undefined";
9897
10982
  const per = sinks.er ? `${p}er` : "undefined";
9898
- const rb = L.buf ? `_rbBuf(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
10983
+ const rbHelper = L.raw === RAW_OMIT ? "_rbNoRawBuf" : "_rbBuf";
10984
+ const rb = L.buf && L.raw !== 0 ? `${rbHelper}(ctx,${p}raw,${p}tl,${p}lv,${p}lg,${p}rt)${sinks.fd ? `
9899
10985
  if(ctx._fields!==undefined&&ctx._fields.length!==${p}fd)ctx._fields.length=${p}fd` : ""}${sinks.er ? `
9900
- if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
10986
+ if(ctx._errors!==undefined&&ctx._errors.length!==${p}er)ctx._errors.length=${p}er` : ""}` : L.buf ? `rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)` : `if(needMark)rollbackTriviaAt(ctx,${p}raw,${p}tl,${p}lv,${pfd},${per},${p}lg,${p}rt)`;
9901
10987
  const markSinks = `${sinks.fd ? `
9902
10988
  ${p}fd=ctx._fields!==undefined?ctx._fields.length:0` : ""}${sinks.er ? `
9903
10989
  ${p}er=ctx._errors!==undefined?ctx._errors.length:0` : ""}`;
10990
+ const markRaw = L.raw === RAW_OMIT ? `${p}raw=b.rawLen` : L.raw === RAW_CAPTURE ? `const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0` : `const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)`;
9904
10991
  const markBody = L.buf ? `const b=ctx._cstBuf
9905
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
10992
+ ${markRaw}
9906
10993
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
9907
10994
  const l=b.tl;${p}tl=l!==undefined?l.length:0
9908
10995
  ${p}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
9909
10996
  ${p}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0${markSinks}` : `if(needMark){
9910
10997
  const b=ctx._cstBuf
9911
10998
  if(b!==undefined){
9912
- const r=b.raw;${p}raw=r!==undefined?r.length:b.rawSingle!==undefined?1:0
10999
+ const r=b.raw;${p}raw=b.noRaw===true?b.rawLen:(r!==undefined?r.length:b.rawSingle!==undefined?1:0)
9913
11000
  const h=b.ch;${p}lv=h!==undefined?h.length:b.single!==undefined?1:0
9914
11001
  const l=b.tl;${p}tl=l!==undefined?l.length:0
9915
11002
  }else{
@@ -10016,7 +11103,7 @@ const leaf={_tag:'leaf',value,span:{start:pos,end}}
10016
11103
  const kids=[leaf],rawKids=[leaf],span={start:pos,end}
10017
11104
  EC.e=end
10018
11105
  const nd=${build2}(kids,undefined,span,rawKids,EMPTY_TL,undefined)
10019
- ${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))"}
11106
+ ${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,ctx._cstBuf!==undefined&&ctx._cstBuf.noRaw===true?undefined:ctx._cstBuf!==undefined||ctx._cstRawChildren!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(ctx._cstBuf!==undefined||ctx._cstChildren!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
10020
11107
  EC.e=end
10021
11108
  return nd
10022
11109
  }`;
@@ -10038,7 +11125,22 @@ return nd
10038
11125
  if (!hostCst && !tracked && build !== void 0 && proj < 0 && (flags === 2 || flags === 18 || flags === 34)) {
10039
11126
  const fields = flags === 18;
10040
11127
  const collapseChildren = flags === 34;
10041
- const publish = `if(sBuf!==undefined){
11128
+ const publish = L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? `if(sBuf!==undefined){
11129
+ if(sBuf.rawOnly!==true){
11130
+ if(sBuf.ch!==undefined)sBuf.ch.push(nd)
11131
+ else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
11132
+ else sBuf.single=nd
11133
+ }
11134
+ const rawNd=rawEntry(nd,input,pos,end)
11135
+ if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
11136
+ else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
11137
+ else sBuf.rawSingle=rawNd
11138
+ }else if(sCh!==undefined){
11139
+ sCh.push(nd)
11140
+ if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
11141
+ }` : `if(sBuf!==undefined){
11142
+ if(sBuf.noRaw===true)_pushNodeNoRawBuf(ctx,nd)
11143
+ else{
10042
11144
  if(sBuf.rawOnly!==true){
10043
11145
  if(sBuf.ch!==undefined)sBuf.ch.push(nd)
10044
11146
  else if(sBuf.single!==undefined){sBuf.ch=[sBuf.single,nd];sBuf.single=undefined}
@@ -10048,6 +11150,7 @@ const rawNd=rawEntry(nd,input,pos,end)
10048
11150
  if(sBuf.raw!==undefined)sBuf.raw.push(rawNd)
10049
11151
  else if(sBuf.rawSingle!==undefined){sBuf.raw=[sBuf.rawSingle,rawNd];sBuf.rawSingle=undefined}
10050
11152
  else sBuf.rawSingle=rawNd
11153
+ }
10051
11154
  }else if(sCh!==undefined){
10052
11155
  sCh.push(nd)
10053
11156
  if(sRaw!==undefined)sRaw.push(rawEntry(nd,input,pos,end))
@@ -10086,6 +11189,7 @@ return nd
10086
11189
  const wantFields = hasFields || hostCst;
10087
11190
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
10088
11191
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
11192
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
10089
11193
  const ty = q(type);
10090
11194
  const stArg = readsState ? "st" : "(ctx.state!==undefined?Object.assign({},ctx.state):undefined)";
10091
11195
  const hostCall = `_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,${stArg},${tags})`;
@@ -10099,7 +11203,12 @@ return nd
10099
11203
  value = `nd=_pfHost!==undefined?_pfHost(${ty},hostKids,fieldMap,span,rawKids,tlog,st,${tags}):{_tag:'node',type:${ty},span,state:st??null,children:kids}`;
10100
11204
  }
10101
11205
  const collapsible = keepChildren && (hostCst || build === void 0 && proj < 0);
10102
- const openCapture = keepChildren ? `const buf={}
11206
+ const openCapture = omitsRaw ? `const buf={noRaw:true,rawLen:0}
11207
+ ctx._cstBuf=buf
11208
+ ctx._cstChildren=undefined
11209
+ ctx._cstLeaves=undefined
11210
+ ctx._cstRawChildren=undefined
11211
+ ctx._cstTriviaLog=undefined` : keepChildren ? `const buf={}
10103
11212
  ctx._cstBuf=buf
10104
11213
  ctx._cstChildren=undefined
10105
11214
  ctx._cstLeaves=undefined
@@ -10110,7 +11219,10 @@ ctx._cstChildren=undefined
10110
11219
  ctx._cstLeaves=undefined
10111
11220
  ctx._cstRawChildren=undefined
10112
11221
  ctx._cstTriviaLog=undefined`;
10113
- const finishCapture = keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
11222
+ const finishCapture = omitsRaw ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
11223
+ const hostKids=kids
11224
+ const rawKids=EMPTY_CH
11225
+ const tlog=buf.tl??EMPTY_TLOG` : keepChildren ? `const kids=buf.ch??(buf.single!==undefined?[buf.single]:EMPTY_CH)
10114
11226
  const hostKids=kids
10115
11227
  const rawKids=buf.raw??(buf.rawSingle!==undefined?[buf.rawSingle]:EMPTY_CH)
10116
11228
  const tlog=buf.tl??EMPTY_TLOG` : `const kids=EMPTY_CH
@@ -10144,7 +11256,7 @@ const st=${readsState ? "(ctx.state!==undefined?Object.assign({},ctx.state):unde
10144
11256
  let nd
10145
11257
  ${unwrap ? "if(kids.length===1)nd=unwrapChild(kids[0])\nelse " : ""}${collapse ? "if(kids.length===1)nd=kids[0]\nelse " : ""}${collapsible ? `if(_pfHost!==undefined&&_pfHost._parsemanCstCollapse!==undefined&&kids.length===1&&rawKids.length===1&&_pfHost._parsemanCstCollapse(${ty},kids[0],kids,rawKids))nd=kids[0]
10146
11258
  else ` : ""}{${value}}
10147
- ${L.buf ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
11259
+ ${L.buf && L.raw === RAW_OMIT ? "_pushNodeNoRawBuf(ctx,nd)" : L.buf && L.raw === RAW_CAPTURE ? "pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))" : staticBuild ? "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,sBuf!==undefined?(sBuf.noRaw===true?undefined:rawEntry(nd,input,pos,end)):sRaw!==undefined?rawEntry(nd,input,pos,end):undefined)" : "if(sBuf!==undefined||sCh!==undefined)pushCstChild(ctx,nd,rawEntry(nd,input,pos,end))"}
10148
11260
  EC.e=end
10149
11261
  return nd
10150
11262
  }`;
@@ -10162,7 +11274,7 @@ return nd
10162
11274
  }
10163
11275
  const extra = [];
10164
11276
  for (const ip of extraIps) extra.push(`${ip}:${link(ip)}`);
10165
- const source = `${RUNTIME_PRELUDE}
11277
+ const source = `${RUNTIME_PRELUDE}${needsNoRawPrelude ? NO_RAW_RUNTIME_PRELUDE : ""}
10166
11278
  ${prelude.join("\n")}
10167
11279
  ${skipDefs.join("\n")}
10168
11280
  ${choiceDefs.join("\n")}
@@ -10177,7 +11289,13 @@ _pfHost=host
10177
11289
  function _finish(){
10178
11290
  if(_pfDepth<=0)throw new Error('parseman emitted table assembly frame underflow')
10179
11291
  _pfDepth--
10180
- if(_pfDepth===0)return
11292
+ if(_pfDepth===0){
11293
+ _pfTokInput=undefined
11294
+ _pfTokBody=-1
11295
+ _pfTokValue=undefined
11296
+ _pfTokDispatch=-1
11297
+ return
11298
+ }
10181
11299
  const prior=_pfFrames.pop()
10182
11300
  _pfScan=prior[0]
10183
11301
  _pfHost=prior[1]
@@ -10552,6 +11670,17 @@ function assemble(t, prog, cfg) {
10552
11670
  }
10553
11671
  return recognize;
10554
11672
  }
11673
+ const labelExtraIps = [];
11674
+ for (const s of prog.scans ?? []) {
11675
+ for (const r of s.skip) labelExtraIps.push(r[0]);
11676
+ if (s.sentinel !== void 0) labelExtraIps.push(s.sentinel[0]);
11677
+ }
11678
+ for (const set of prog.scanSkip ?? []) for (const r of set) labelExtraIps.push(r[0]);
11679
+ const closureLabels = computeSiteLabels(
11680
+ code,
11681
+ [...Object.values(prog.rules), ...labelExtraIps],
11682
+ hostCst
11683
+ );
10555
11684
  let SCAN = null;
10556
11685
  const memo = /* @__PURE__ */ new Map();
10557
11686
  const reached = /* @__PURE__ */ new Set();
@@ -10797,7 +11926,7 @@ function assemble(t, prog, cfg) {
10797
11926
  const b = ctx._cstBuf;
10798
11927
  if (b !== void 0) {
10799
11928
  const raw = b.raw;
10800
- MRAW = raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
11929
+ MRAW = b.noRaw === true ? b.rawLen ?? 0 : raw !== void 0 ? raw.length : b.rawSingle !== void 0 ? 1 : 0;
10801
11930
  const ch2 = b.ch;
10802
11931
  MLV = ch2 !== void 0 ? ch2.length : b.single !== void 0 ? 1 : 0;
10803
11932
  const tl = b.tl;
@@ -10881,6 +12010,31 @@ function assemble(t, prog, cfg) {
10881
12010
  if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
10882
12011
  return cur;
10883
12012
  }
12013
+ function nextTermBuffered(child, input, cur, ctx) {
12014
+ if (ctx.trivia === void 0) {
12015
+ const v2 = child(input, cur, ctx);
12016
+ if (v2 === FAIL) return -1;
12017
+ TERMV = v2;
12018
+ return EC.e;
12019
+ }
12020
+ const before = ctx._cstBuf;
12021
+ const beforeTl = before.tl;
12022
+ const mTl = beforeTl === void 0 ? 0 : beforeTl.length;
12023
+ const mLog = ctx._triviaLog?.length ?? 0;
12024
+ const mRoot = ctx._rootTriviaLog?.length ?? 0;
12025
+ const scanEnd = skipTrivia(input, cur, ctx);
12026
+ const scanned = ctx._cstBuf;
12027
+ const scannedTl = scanned.tl;
12028
+ const scanTl = scannedTl === void 0 ? 0 : scannedTl.length;
12029
+ const scanLog = ctx._triviaLog?.length ?? 0;
12030
+ const scanRoot = ctx._rootTriviaLog?.length ?? 0;
12031
+ const v = child(input, scanEnd, ctx);
12032
+ if (v === FAIL) return -1;
12033
+ TERMV = v;
12034
+ if (EC.e > scanEnd) return EC.e;
12035
+ rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
12036
+ return cur;
12037
+ }
10884
12038
  function committed3(c) {
10885
12039
  return c._fc === true;
10886
12040
  }
@@ -11151,7 +12305,8 @@ function assemble(t, prog, cfg) {
11151
12305
  target = p;
11152
12306
  } };
11153
12307
  inFlight.set(ip, holder);
11154
- const piece = lower(ip);
12308
+ const op = code[ip];
12309
+ const piece = (op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && closureLabels.at(ip).tri === code[ip + 1] ? link(code[ip + 2]) : lower(ip);
11155
12310
  inFlight.delete(ip);
11156
12311
  holder.set(piece);
11157
12312
  memo.set(ip, piece);
@@ -11894,6 +13049,7 @@ function assemble(t, prog, cfg) {
11894
13049
  const reducer = fused ? code[ip + 1] : -1;
11895
13050
  const projection = reducer < 0 ? ~reducer : -1;
11896
13051
  const fn = fused && projection < 0 ? fns[reducer] : void 0;
13052
+ const step = closureLabels.at(ip).buf ? nextTermBuffered : nextTerm;
11897
13053
  const runnerBlock = (count, r0, r1, r2, r3, next) => {
11898
13054
  if (count === 1) return (input, cur, ctx, values, inherited) => {
11899
13055
  cur = r0(input, cur, ctx, inherited);
@@ -11948,7 +13104,7 @@ function assemble(t, prog, cfg) {
11948
13104
  const kid = link(kidIp);
11949
13105
  return (input, cur, ctx, inherited) => {
11950
13106
  ctx._sync = sync ?? inherited;
11951
- return nextTerm(kid, input, cur, ctx);
13107
+ return step(kid, input, cur, ctx);
11952
13108
  };
11953
13109
  }
11954
13110
  const negated = code[kidIp + 1] === 1;
@@ -12033,7 +13189,7 @@ function assemble(t, prog, cfg) {
12033
13189
  const kidIp = code[base + i];
12034
13190
  if (code[kidIp] !== OP_ADJ) {
12035
13191
  const kid = link(kidIp);
12036
- return (input, cur, ctx) => nextTerm(kid, input, cur, ctx);
13192
+ return (input, cur, ctx) => step(kid, input, cur, ctx);
12037
13193
  }
12038
13194
  const negated = code[kidIp + 1] === 1;
12039
13195
  const ki = code[kidIp + 2];
@@ -12122,7 +13278,7 @@ function assemble(t, prog, cfg) {
12122
13278
  return (input, pos, ctx) => {
12123
13279
  const v0 = k0(input, pos, ctx);
12124
13280
  if (v0 === FAIL) return FAIL;
12125
- const cur = nextTerm(k1, input, EC.e, ctx);
13281
+ const cur = step(k1, input, EC.e, ctx);
12126
13282
  if (cur < 0) return FAIL;
12127
13283
  EC.e = cur;
12128
13284
  return projection === 0 ? v0 : projection === 1 ? TERMV : fn([v0, TERMV], { start: pos, end: cur });
@@ -12132,7 +13288,7 @@ function assemble(t, prog, cfg) {
12132
13288
  return (input, pos, ctx) => {
12133
13289
  const v0 = k0(input, pos, ctx);
12134
13290
  if (v0 === FAIL) return FAIL;
12135
- const cur = nextTerm(k1, input, EC.e, ctx);
13291
+ const cur = step(k1, input, EC.e, ctx);
12136
13292
  if (cur < 0) return FAIL;
12137
13293
  EC.e = cur;
12138
13294
  return [v0, TERMV];
@@ -12141,7 +13297,7 @@ function assemble(t, prog, cfg) {
12141
13297
  return (input, pos, ctx) => {
12142
13298
  const v0 = k0(input, pos, ctx);
12143
13299
  if (v0 === FAIL) return FAIL;
12144
- const cur = nextTerm(k1, input, EC.e, ctx);
13300
+ const cur = step(k1, input, EC.e, ctx);
12145
13301
  if (cur < 0) return FAIL;
12146
13302
  EC.e = cur;
12147
13303
  return void 0;
@@ -12153,10 +13309,10 @@ function assemble(t, prog, cfg) {
12153
13309
  return (input, pos, ctx) => {
12154
13310
  const v0 = k0(input, pos, ctx);
12155
13311
  if (v0 === FAIL) return FAIL;
12156
- let cur = nextTerm(k1, input, EC.e, ctx);
13312
+ let cur = step(k1, input, EC.e, ctx);
12157
13313
  if (cur < 0) return FAIL;
12158
13314
  const v1 = TERMV;
12159
- cur = nextTerm(k2, input, cur, ctx);
13315
+ cur = step(k2, input, cur, ctx);
12160
13316
  if (cur < 0) return FAIL;
12161
13317
  EC.e = cur;
12162
13318
  return projection === 0 ? v0 : projection === 1 ? v1 : projection === 2 ? TERMV : fn([v0, v1, TERMV], { start: pos, end: cur });
@@ -12166,10 +13322,10 @@ function assemble(t, prog, cfg) {
12166
13322
  return (input, pos, ctx) => {
12167
13323
  const v0 = k0(input, pos, ctx);
12168
13324
  if (v0 === FAIL) return FAIL;
12169
- let cur = nextTerm(k1, input, EC.e, ctx);
13325
+ let cur = step(k1, input, EC.e, ctx);
12170
13326
  if (cur < 0) return FAIL;
12171
13327
  const v1 = TERMV;
12172
- cur = nextTerm(k2, input, cur, ctx);
13328
+ cur = step(k2, input, cur, ctx);
12173
13329
  if (cur < 0) return FAIL;
12174
13330
  EC.e = cur;
12175
13331
  return [v0, v1, TERMV];
@@ -12178,9 +13334,9 @@ function assemble(t, prog, cfg) {
12178
13334
  return (input, pos, ctx) => {
12179
13335
  const v0 = k0(input, pos, ctx);
12180
13336
  if (v0 === FAIL) return FAIL;
12181
- let cur = nextTerm(k1, input, EC.e, ctx);
13337
+ let cur = step(k1, input, EC.e, ctx);
12182
13338
  if (cur < 0) return FAIL;
12183
- cur = nextTerm(k2, input, cur, ctx);
13339
+ cur = step(k2, input, cur, ctx);
12184
13340
  if (cur < 0) return FAIL;
12185
13341
  EC.e = cur;
12186
13342
  return void 0;
@@ -12188,43 +13344,43 @@ function assemble(t, prog, cfg) {
12188
13344
  }
12189
13345
  const block = (count, k0, k1, k2, k3, next) => {
12190
13346
  if (count === 1) return (input, cur, ctx, values) => {
12191
- cur = nextTerm(k0, input, cur, ctx);
13347
+ cur = step(k0, input, cur, ctx);
12192
13348
  if (cur < 0) return -1;
12193
13349
  if (values !== void 0) values.push(TERMV);
12194
13350
  return next === void 0 ? cur : next(input, cur, ctx, values);
12195
13351
  };
12196
13352
  if (count === 2) return (input, cur, ctx, values) => {
12197
- cur = nextTerm(k0, input, cur, ctx);
13353
+ cur = step(k0, input, cur, ctx);
12198
13354
  if (cur < 0) return -1;
12199
13355
  if (values !== void 0) values.push(TERMV);
12200
- cur = nextTerm(k1, input, cur, ctx);
13356
+ cur = step(k1, input, cur, ctx);
12201
13357
  if (cur < 0) return -1;
12202
13358
  if (values !== void 0) values.push(TERMV);
12203
13359
  return next === void 0 ? cur : next(input, cur, ctx, values);
12204
13360
  };
12205
13361
  if (count === 3) return (input, cur, ctx, values) => {
12206
- cur = nextTerm(k0, input, cur, ctx);
13362
+ cur = step(k0, input, cur, ctx);
12207
13363
  if (cur < 0) return -1;
12208
13364
  if (values !== void 0) values.push(TERMV);
12209
- cur = nextTerm(k1, input, cur, ctx);
13365
+ cur = step(k1, input, cur, ctx);
12210
13366
  if (cur < 0) return -1;
12211
13367
  if (values !== void 0) values.push(TERMV);
12212
- cur = nextTerm(k2, input, cur, ctx);
13368
+ cur = step(k2, input, cur, ctx);
12213
13369
  if (cur < 0) return -1;
12214
13370
  if (values !== void 0) values.push(TERMV);
12215
13371
  return next === void 0 ? cur : next(input, cur, ctx, values);
12216
13372
  };
12217
13373
  return (input, cur, ctx, values) => {
12218
- cur = nextTerm(k0, input, cur, ctx);
13374
+ cur = step(k0, input, cur, ctx);
12219
13375
  if (cur < 0) return -1;
12220
13376
  if (values !== void 0) values.push(TERMV);
12221
- cur = nextTerm(k1, input, cur, ctx);
13377
+ cur = step(k1, input, cur, ctx);
12222
13378
  if (cur < 0) return -1;
12223
13379
  if (values !== void 0) values.push(TERMV);
12224
- cur = nextTerm(k2, input, cur, ctx);
13380
+ cur = step(k2, input, cur, ctx);
12225
13381
  if (cur < 0) return -1;
12226
13382
  if (values !== void 0) values.push(TERMV);
12227
- cur = nextTerm(k3, input, cur, ctx);
13383
+ cur = step(k3, input, cur, ctx);
12228
13384
  if (cur < 0) return -1;
12229
13385
  if (values !== void 0) values.push(TERMV);
12230
13386
  return next === void 0 ? cur : next(input, cur, ctx, values);
@@ -12395,6 +13551,13 @@ function assemble(t, prog, cfg) {
12395
13551
  if (n === 2 || n === 3) {
12396
13552
  const a0 = link(code[base]), a1 = link(code[base + 1]);
12397
13553
  const a2 = n === 3 ? link(code[base + 2]) : void 0;
13554
+ const predecide = !hostCst && !REC2 && !cfg.probe && !cfg.coverage && !cfg.trackLines;
13555
+ const p0ip = predecide ? leadingScalarTerminal(code, code[base], 2, true, true) : -1;
13556
+ const p1ip = predecide ? leadingScalarTerminal(code, code[base + 1], 2, true, true) : -1;
13557
+ const p2ip = predecide && n === 3 ? leadingScalarTerminal(code, code[base + 2], 2, true, true) : -1;
13558
+ const p0 = p0ip < 0 ? void 0 : scalarFor(p0ip);
13559
+ const p1 = p1ip < 0 ? void 0 : scalarFor(p1ip);
13560
+ const p2 = p2ip < 0 ? void 0 : scalarFor(p2ip);
12398
13561
  const e0 = fx[code[base + n]];
12399
13562
  const e1 = fx[code[base + n + 1]];
12400
13563
  const e2 = n === 3 ? fx[code[base + n + 2]] : void 0;
@@ -12424,7 +13587,10 @@ function assemble(t, prog, cfg) {
12424
13587
  let acc;
12425
13588
  let best = pos;
12426
13589
  if (c < 128) {
12427
- const bits = mask[c < 0 ? 128 : c];
13590
+ let bits = mask[c < 0 ? 128 : c];
13591
+ if ((bits & 1) !== 0 && p0 !== void 0 && p0(input, pos) < 0) bits &= ~1;
13592
+ if ((bits & 2) !== 0 && p1 !== void 0 && p1(input, pos) < 0) bits &= ~2;
13593
+ if ((bits & 4) !== 0 && p2 !== void 0 && p2(input, pos) < 0) bits &= ~4;
12428
13594
  let prev = 0;
12429
13595
  if ((bits & 1) !== 0) {
12430
13596
  ctx._fc = false;
@@ -12487,7 +13653,7 @@ function assemble(t, prog, cfg) {
12487
13653
  ctx._fx = acc ?? choiceFx;
12488
13654
  return FAIL;
12489
13655
  }
12490
- if (g0 === null || classHas2(g0, c)) {
13656
+ if ((g0 === null || classHas2(g0, c)) && (p0 === void 0 || p0(input, pos) >= 0)) {
12491
13657
  ctx._fc = false;
12492
13658
  const v = a0(input, pos, ctx);
12493
13659
  if (v !== FAIL) return v;
@@ -12503,7 +13669,7 @@ function assemble(t, prog, cfg) {
12503
13669
  }
12504
13670
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12505
13671
  } else if (best === pos) acc = accSet(e0, acc);
12506
- if (g1 === null || classHas2(g1, c)) {
13672
+ if ((g1 === null || classHas2(g1, c)) && (p1 === void 0 || p1(input, pos) >= 0)) {
12507
13673
  ctx._fc = false;
12508
13674
  const v = a1(input, pos, ctx);
12509
13675
  if (v !== FAIL) return v;
@@ -12520,7 +13686,7 @@ function assemble(t, prog, cfg) {
12520
13686
  if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
12521
13687
  } else if (best === pos) acc = accSet(e1, acc);
12522
13688
  if (n === 3) {
12523
- if (g2 === null || classHas2(g2, c)) {
13689
+ if ((g2 === null || classHas2(g2, c)) && (p2 === void 0 || p2(input, pos) >= 0)) {
12524
13690
  ctx._fc = false;
12525
13691
  const v = a2(input, pos, ctx);
12526
13692
  if (v !== FAIL) return v;
@@ -13093,20 +14259,14 @@ function assemble(t, prog, cfg) {
13093
14259
  const captureWide = readsTrivia || hostCst ? !structural || grammarCapture || hostCapturesThisType !== false : hostCapturesThisType === true;
13094
14260
  const keepChildren = !structural || cfg.hostReadsChildren !== false || collapse || unwrap;
13095
14261
  const rawOnly = !keepChildren;
14262
+ const omitsRaw = !hostCst && build !== void 0 && proj < 0 && (flags & 2) !== 0;
13096
14263
  return (input, pos, ctx) => {
13097
14264
  const host = HOST;
13098
14265
  const sCh = ctx._cstChildren;
13099
- const sLv = ctx._cstLeaves;
13100
- const sRaw = ctx._cstRawChildren;
13101
- const sTl = ctx._cstTriviaLog;
13102
14266
  const sCap = ctx.captureTrivia;
13103
14267
  const sBuf = ctx._cstBuf;
13104
- const buf = rawOnly ? { rawOnly: true } : {};
14268
+ const buf = rawOnly ? { rawOnly: true } : omitsRaw ? { noRaw: true, rawLen: 0 } : {};
13105
14269
  ctx._cstBuf = buf;
13106
- ctx._cstChildren = void 0;
13107
- ctx._cstLeaves = void 0;
13108
- ctx._cstRawChildren = void 0;
13109
- ctx._cstTriviaLog = void 0;
13110
14270
  ctx.captureTrivia = captureWide;
13111
14271
  const savedFields = ctx._fields;
13112
14272
  ctx._fields = wantFields ? [] : void 0;
@@ -13121,13 +14281,9 @@ function assemble(t, prog, cfg) {
13121
14281
  if (structural) ctx._triviaCaptureMask = savedMask;
13122
14282
  const kids = rawOnly ? EMPTY_CH : buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY_CH);
13123
14283
  const hostKids = kids;
13124
- const rawKids = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
14284
+ const rawKids = omitsRaw ? EMPTY_CH : buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY_CH);
13125
14285
  const tlog = buf.tl ?? EMPTY_TLOG;
13126
14286
  ctx._cstBuf = sBuf;
13127
- ctx._cstChildren = sCh;
13128
- ctx._cstLeaves = sLv;
13129
- ctx._cstRawChildren = sRaw;
13130
- ctx._cstTriviaLog = sTl;
13131
14287
  ctx.captureTrivia = sCap;
13132
14288
  if (v === FAIL) return FAIL;
13133
14289
  const end = EC.e;
@@ -13218,6 +14374,34 @@ function assemble(t, prog, cfg) {
13218
14374
  rawScalarSpecs.add(code[child + 1]);
13219
14375
  scalarFor(child);
13220
14376
  }
14377
+ } else if (code[ip] === OP_CHOICE && !disp[code[ip + 1]].exclusive) {
14378
+ const n = code[ip + 2];
14379
+ for (let i = 0; i < n; i++) {
14380
+ const armIp = code[ip + 4 + i];
14381
+ const child = leadingScalarTerminal(code, armIp, 2, true, true);
14382
+ if (n === 2 || n === 3) {
14383
+ if (child >= 0) scalarFor(child);
14384
+ continue;
14385
+ }
14386
+ if (child >= 0) {
14387
+ const spec = k[code[child + 1]];
14388
+ if (code[child] === OP_LIT && typeof spec === "string" && spec.length >= 2) {
14389
+ scalarFor(child);
14390
+ continue;
14391
+ }
14392
+ }
14393
+ const family = leadingLiteralFamily(code, k, armIp);
14394
+ if (family !== void 0 && family.length >= 2 && family.every((terminal) => {
14395
+ const value = k[code[terminal + 1]];
14396
+ return typeof value === "string" && value.length >= 2;
14397
+ })) {
14398
+ for (const terminal of family) scalarFor(terminal);
14399
+ }
14400
+ const sequence6 = leadingScalarSequence(code, armIp);
14401
+ if (sequence6 !== void 0 && (sequence6.trivia < 0 || triviaScan[sequence6.trivia] != null)) {
14402
+ for (const terminal of sequence6.terminals) scalarFor(terminal);
14403
+ }
14404
+ }
13221
14405
  }
13222
14406
  }
13223
14407
  const notChild = scalarTerminalNotChild(code, ip);
@@ -13639,7 +14823,7 @@ function emitAssemblies(prog, cfgs) {
13639
14823
  seen.add(key);
13640
14824
  let em;
13641
14825
  try {
13642
- em = emitAssemblySource(t, prog, cfg, extraIps);
14826
+ em = emitAssemblySource(t, prog, cfg, extraIps, true);
13643
14827
  } catch (e) {
13644
14828
  if (e instanceof Unemittable) continue;
13645
14829
  throw e;
@@ -15175,7 +16359,7 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
15175
16359
  };
15176
16360
  const { prog, fnSrcs } = encodeTableProgram({ [ENTRY]: combinator }, settings);
15177
16361
  const artifact = closureArtifact(prog);
15178
- const entry = tableRules(artifact)[ENTRY];
16362
+ const entry = tableRules(prog)[ENTRY];
15179
16363
  const offered = opts.fnSources ?? mapFnSources;
15180
16364
  const supplied = offered !== void 0 && offered.length === fnSrcs.length ? offered : void 0;
15181
16365
  const sources = fnSrcs.map((s, i) => s ?? supplied?.[i] ?? ownSource(prog.fns[i]));
@@ -15224,106 +16408,6 @@ function compileImpl(combinator, mapFnSources, opts = {}) {
15224
16408
  };
15225
16409
  }
15226
16410
 
15227
- // src/analysis/commitment.ts
15228
- function hasDirectBuildDef(p, seen = /* @__PURE__ */ new Set()) {
15229
- if (seen.has(p)) return false;
15230
- seen.add(p);
15231
- const d = p._def;
15232
- switch (d.tag) {
15233
- case "node":
15234
- return d.build !== void 0 || hasDirectBuildDef(d.parser, seen);
15235
- case "lazy": {
15236
- try {
15237
- return hasDirectBuildDef(d.thunk(), seen);
15238
- } catch {
15239
- return false;
15240
- }
15241
- }
15242
- case "grammar":
15243
- case "trivia":
15244
- case "token":
15245
- case "leaf":
15246
- case "label":
15247
- case "field":
15248
- case "optional":
15249
- case "many":
15250
- case "oneOrMore":
15251
- case "attempt":
15252
- case "not":
15253
- case "peek":
15254
- case "withCtx":
15255
- case "expect":
15256
- case "transform":
15257
- return hasDirectBuildDef(d.parser, seen);
15258
- case "sequence":
15259
- case "choice":
15260
- return d.parsers.some((x) => hasDirectBuildDef(x, seen));
15261
- case "dispatch":
15262
- return hasDirectBuildDef(d.selector, seen) || d.cases.some((x) => hasDirectBuildDef(x.parser, seen)) || (d.matchers ? d.matchers.some((x) => hasDirectBuildDef(x.parser, seen)) : false) || (d.otherwise ? hasDirectBuildDef(d.otherwise, seen) : false);
15263
- case "sepBy":
15264
- return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.separator, seen);
15265
- case "scanTo":
15266
- return hasDirectBuildDef(d.sentinel, seen) || d.skip.some((x) => hasDirectBuildDef(x, seen));
15267
- case "recover":
15268
- return hasDirectBuildDef(d.parser, seen) || hasDirectBuildDef(d.sentinel, seen);
15269
- case "routed":
15270
- return d.fallback ? hasDirectBuildDef(d.fallback, seen) : false;
15271
- default:
15272
- return false;
15273
- }
15274
- }
15275
- function hasSemanticReduction(roots, externalRefs) {
15276
- const seen = /* @__PURE__ */ new Set();
15277
- const visit = (parser2) => {
15278
- if (seen.has(parser2)) return false;
15279
- seen.add(parser2);
15280
- const def = parser2._def;
15281
- if (def.tag === "transform" && !def.recognitionOnly) return true;
15282
- if (def.tag === "choice" && def.gates.some(Boolean)) return true;
15283
- if (def.tag === "guard" || def.tag === "withCtx") return true;
15284
- if (def.tag === "node" && def.build !== void 0) return true;
15285
- if (def.tag === "lazy") {
15286
- if (externalRefs?.has(parser2)) return false;
15287
- try {
15288
- return visit(def.thunk());
15289
- } catch {
15290
- return true;
15291
- }
15292
- }
15293
- return childrenOf2(def).some(visit);
15294
- };
15295
- return roots.some(visit);
15296
- }
15297
- function classifyRuleMap(ruleMap) {
15298
- const externalRefs = /* @__PURE__ */ new Set();
15299
- const scanned = /* @__PURE__ */ new Set();
15300
- const scanExternal = (p) => {
15301
- if (scanned.has(p)) return;
15302
- scanned.add(p);
15303
- const def = p._def;
15304
- if (def.tag === "lazy") {
15305
- let resolved;
15306
- try {
15307
- resolved = def.thunk();
15308
- } catch {
15309
- resolved = void 0;
15310
- }
15311
- if (resolved === void 0) {
15312
- if (p._ruleName) externalRefs.add(p);
15313
- return;
15314
- }
15315
- scanExternal(resolved);
15316
- return;
15317
- }
15318
- for (const child of childrenOf2(def)) scanExternal(child);
15319
- };
15320
- for (const [, rule] of ruleMap) scanExternal(rule);
15321
- return {
15322
- hasDirectBuilders: ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
15323
- isRecognitionOnly: !hasSemanticReduction(ruleMap.map(([, rule]) => rule), externalRefs)
15324
- };
15325
- }
15326
-
15327
16411
  // src/combinators/withCtx.ts
15328
16412
  function withCtx(extra, combinator) {
15329
16413
  const meta = {
@@ -15466,7 +16550,7 @@ function evalRuleMapIR(ir) {
15466
16550
  l._def.fnSrc = src;
15467
16551
  return l;
15468
16552
  };
15469
- const _nd = (type, child, src, opts, staticError, sigSrc, buildImports) => {
16553
+ const _nd = (type, child, src, opts, staticError, sigSrc, buildImports, rawUnused) => {
15470
16554
  if (staticError !== void 0 && staticError.length > 0) {
15471
16555
  throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
15472
16556
  }
@@ -15476,6 +16560,7 @@ function evalRuleMapIR(ir) {
15476
16560
  n._def.buildSrc = src;
15477
16561
  if (staticError !== void 0) n._def.buildStaticError = staticError;
15478
16562
  if (sigSrc !== void 0) n._def.buildSigSrc = sigSrc;
16563
+ if (rawUnused === true) n._def.buildRawUnused = true;
15479
16564
  if (buildImports !== void 0) n._def.buildImports = buildImports;
15480
16565
  return n;
15481
16566
  };
@@ -15868,12 +16953,13 @@ ${outerDecls.map((d) => " " + d).join("\n")}
15868
16953
  }
15869
16954
  if (def.buildSrc !== void 0) {
15870
16955
  const tail = [];
15871
- if (def.buildStaticError !== void 0 || def.buildSigSrc !== void 0 || def.buildImports !== void 0) {
16956
+ if (def.buildStaticError !== void 0 || def.buildSigSrc !== void 0 || def.buildImports !== void 0 || def.buildRawUnused === true) {
15872
16957
  if (!opts) tail.push("undefined");
15873
16958
  tail.push(def.buildStaticError === void 0 ? "undefined" : JSON.stringify(def.buildStaticError));
15874
16959
  }
15875
- if (def.buildSigSrc !== void 0 || def.buildImports !== void 0) tail.push(def.buildSigSrc === void 0 ? "undefined" : JSON.stringify(def.buildSigSrc));
15876
- if (def.buildImports !== void 0) tail.push(JSON.stringify(def.buildImports));
16960
+ if (def.buildSigSrc !== void 0 || def.buildImports !== void 0 || def.buildRawUnused === true) tail.push(def.buildSigSrc === void 0 ? "undefined" : JSON.stringify(def.buildSigSrc));
16961
+ if (def.buildImports !== void 0 || def.buildRawUnused === true) tail.push(def.buildImports === void 0 ? "undefined" : JSON.stringify(def.buildImports));
16962
+ if (def.buildRawUnused === true) tail.push("true");
15877
16963
  const trailing = tail.length > 0 ? `, ${tail.join(", ")}` : "";
15878
16964
  return `_nd(${JSON.stringify(def.type)}, ${kid(def.parser)}, ${JSON.stringify(def.buildSrc)}${opts}${trailing})`;
15879
16965
  }
@@ -15942,7 +17028,7 @@ function compileRuleMapRunnable(ruleMap, opts = {}) {
15942
17028
  hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
15943
17029
  reflection: collectGrammarReflection(ruleMap),
15944
17030
  ...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
15945
- rules: tableRules(artifact),
17031
+ rules: tableRules(prog),
15946
17032
  prog: artifact
15947
17033
  };
15948
17034
  }
@@ -16014,13 +17100,13 @@ function compileRuleMap(ruleMap, opts = {}) {
16014
17100
  hostBranchElided: hostMode === "ast" && ruleMap.some(([, rule]) => hasDirectBuildDef(rule)),
16015
17101
  reflection: collectGrammarReflection(ruleMap),
16016
17102
  ...plan === void 0 ? {} : { coverageDefinitions: plan.definitions },
16017
- rules: tableRules(artifact),
17103
+ rules: tableRules(prog),
16018
17104
  prog: artifact
16019
17105
  };
16020
17106
  }
16021
17107
 
16022
17108
  // src/version.ts
16023
- var PARSEMAN_VERSION = "0.49.0";
17109
+ var PARSEMAN_VERSION = "0.50.1";
16024
17110
 
16025
17111
  // src/compiler/compile-linkable-table.ts
16026
17112
  function isLocal(rule) {