parseman 0.50.1 → 0.50.3

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 (53) hide show
  1. package/README.md +14 -10
  2. package/dist/analysis/diagnostics.js +431 -219
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +421 -184
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/choice.d.ts.map +1 -1
  7. package/dist/combinators/grammar.d.ts.map +1 -1
  8. package/dist/combinators/keywords.d.ts.map +1 -1
  9. package/dist/combinators/literal.d.ts.map +1 -1
  10. package/dist/combinators/map.d.ts.map +1 -1
  11. package/dist/combinators/ref.d.ts.map +1 -1
  12. package/dist/combinators/regex.d.ts.map +1 -1
  13. package/dist/combinators/repeat.d.ts.map +1 -1
  14. package/dist/combinators/scalar.d.ts +6 -0
  15. package/dist/combinators/scalar.d.ts.map +1 -0
  16. package/dist/combinators/sequence.d.ts.map +1 -1
  17. package/dist/combinators/trivia-skip.d.ts +2 -0
  18. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  19. package/dist/compiler/token-capability.js +0 -3
  20. package/dist/compiler/token-capability.js.map +2 -2
  21. package/dist/index.js +422 -185
  22. package/dist/index.js.map +3 -3
  23. package/dist/language-service/index.js +68 -172
  24. package/dist/language-service/index.js.map +3 -3
  25. package/dist/parse-context.d.ts.map +1 -1
  26. package/dist/plugin/index.js +467 -299
  27. package/dist/plugin/index.js.map +3 -3
  28. package/dist/run/index.js +1 -0
  29. package/dist/run/index.js.map +1 -1
  30. package/dist/spec/index.js +399 -277
  31. package/dist/spec/index.js.map +3 -3
  32. package/dist/table/emit-assembly.d.ts.map +1 -1
  33. package/dist/table/index.js +307 -181
  34. package/dist/table/index.js.map +3 -3
  35. package/dist/types.d.ts +8 -0
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/version.d.ts +1 -1
  38. package/package.json +4 -2
  39. package/src/combinators/choice.ts +34 -1
  40. package/src/combinators/grammar.ts +39 -0
  41. package/src/combinators/keywords.ts +14 -3
  42. package/src/combinators/literal.ts +26 -0
  43. package/src/combinators/map.ts +60 -0
  44. package/src/combinators/ref.ts +26 -7
  45. package/src/combinators/regex.ts +23 -0
  46. package/src/combinators/repeat.ts +109 -16
  47. package/src/combinators/scalar.ts +30 -0
  48. package/src/combinators/sequence.ts +76 -161
  49. package/src/combinators/trivia-skip.ts +14 -1
  50. package/src/parse-context.ts +1 -0
  51. package/src/table/emit-assembly.ts +39 -16
  52. package/src/types.ts +8 -0
  53. package/src/version.ts +1 -1
package/dist/index.js CHANGED
@@ -595,6 +595,28 @@ function literal(value, opts = {}) {
595
595
  isTrivia: false
596
596
  };
597
597
  const canMatchNewline = meta.canMatchNewline;
598
+ const parseScalar = !caseInsensitive && value.length === 1 ? (() => {
599
+ const code = value.charCodeAt(0);
600
+ return (input, pos, ctx) => {
601
+ if (input.charCodeAt(pos) === code) {
602
+ ctx._sv = value;
603
+ return pos + 1;
604
+ }
605
+ ctx._fx = expected;
606
+ return ~pos;
607
+ };
608
+ })() : (input, pos, ctx) => {
609
+ const end = pos + value.length;
610
+ if (end <= input.length) {
611
+ const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
612
+ if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
613
+ ctx._sv = matchedValue;
614
+ return end;
615
+ }
616
+ }
617
+ ctx._fx = expected;
618
+ return ~pos;
619
+ };
598
620
  if (caseInsensitive) {
599
621
  const upper = value.toUpperCase();
600
622
  const lower = value.toLowerCase();
@@ -635,6 +657,7 @@ function literal(value, opts = {}) {
635
657
  _tag: "literal",
636
658
  _meta: meta,
637
659
  _def: { tag: "literal", value, caseInsensitive },
660
+ _parseScalar: parseScalar,
638
661
  parse: parse2
639
662
  };
640
663
  }
@@ -1091,10 +1114,32 @@ function regex(pattern, flags = "") {
1091
1114
  const canMatchNewline = raw.canMatchNewline;
1092
1115
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
1093
1116
  const def = { tag: "regex", source, flags: resolvedFlags };
1117
+ const expected = directTerminalFailureExpected(def);
1118
+ const parseScalar = (input, pos, ctx) => {
1119
+ const scanEnd = scan?.(input, pos);
1120
+ if (scanEnd !== void 0) {
1121
+ if (scanEnd === null) {
1122
+ ctx._fx = expected;
1123
+ return ~pos;
1124
+ }
1125
+ ctx._sv = input.slice(pos, scanEnd);
1126
+ return scanEnd;
1127
+ }
1128
+ anchored.lastIndex = pos;
1129
+ const match = anchored.exec(input);
1130
+ if (match === null) {
1131
+ ctx._fx = expected;
1132
+ return ~pos;
1133
+ }
1134
+ ctx._sv = match[0];
1135
+ return pos + match[0].length;
1136
+ };
1094
1137
  return {
1095
1138
  _tag: "regex",
1096
1139
  _meta: meta,
1097
1140
  _def: def,
1141
+ _stickyRegex: anchored,
1142
+ _parseScalar: parseScalar,
1098
1143
  parse(input, pos, ctx) {
1099
1144
  const scanEnd = scan?.(input, pos);
1100
1145
  if (scanEnd !== void 0) {
@@ -1191,16 +1236,26 @@ function keywords(words, opts = {}) {
1191
1236
  caseInsensitive: opts.caseInsensitive ?? false,
1192
1237
  boundary: opts.boundary
1193
1238
  };
1239
+ const expected = directTerminalFailureExpected(def);
1240
+ const parseScalar = (input, pos, ctx) => {
1241
+ re.lastIndex = pos;
1242
+ const m = re.exec(input);
1243
+ if (m === null) {
1244
+ ctx._fx = expected;
1245
+ return ~pos;
1246
+ }
1247
+ ctx._sv = m[0];
1248
+ return pos + m[0].length;
1249
+ };
1194
1250
  return {
1195
1251
  _tag: "keywords",
1196
1252
  _meta: meta,
1197
1253
  _def: def,
1254
+ _parseScalar: parseScalar,
1198
1255
  parse(input, pos, ctx) {
1199
1256
  re.lastIndex = pos;
1200
1257
  const m = re.exec(input);
1201
- if (m === null || m.index !== pos) {
1202
- return failAt(ctx, directTerminalFailureExpected(def), pos);
1203
- }
1258
+ if (m === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
1204
1259
  const value = m[0];
1205
1260
  const span = { start: pos, end: pos + value.length };
1206
1261
  if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
@@ -1227,6 +1282,7 @@ function createParseContext() {
1227
1282
  _fe: void 0,
1228
1283
  _fx: void 0,
1229
1284
  _fc: void 0,
1285
+ _sv: void 0,
1230
1286
  _probe: void 0,
1231
1287
  _cstChildren: void 0,
1232
1288
  _cstLeaves: void 0,
@@ -1927,6 +1983,9 @@ var fastScanner3;
1927
1983
  function needsDeferredTriviaCommit(ctx) {
1928
1984
  return ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
1929
1985
  }
1986
+ function needsTriviaRollback(ctx) {
1987
+ return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0 || ctx._cstRawChildren !== void 0 || ctx._cstTriviaLog !== void 0 || ctx._fields !== void 0 || ctx._errors !== void 0 || ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0;
1988
+ }
1930
1989
  function saveTriviaMark(ctx) {
1931
1990
  const m = saveCstMark(ctx);
1932
1991
  return {
@@ -2043,7 +2102,8 @@ function advanceTrivia(input, cur, ctx) {
2043
2102
  const triviaP = ctx.trivia;
2044
2103
  if (!triviaP) return cur;
2045
2104
  if (!ctx.trackLines) {
2046
- const fast2 = fastTriviaScanner(triviaP);
2105
+ const classified = triviaP._meta.triviaScanner;
2106
+ const fast2 = classified === void 0 ? fastTriviaScanner(triviaP) : classified;
2047
2107
  if (fast2) return fast2(input, cur);
2048
2108
  if (ctx.triviaKindLabels) return skipWithLabels(input, cur, ctx);
2049
2109
  const tr2 = triviaP.parse(input, cur, createDetachedParseContext(ctx.trackLines, ctx.state));
@@ -2634,6 +2694,28 @@ function notAdjacent(options) {
2634
2694
  );
2635
2695
  }
2636
2696
 
2697
+ // src/combinators/scalar.ts
2698
+ var SCALAR_TAG = /^(?:literal|regex|keywords|sequence|choice|many|oneOrMore|optional|transform|trivia|grammar|sepBy|lazy)$/;
2699
+ function scalarOf(combinator) {
2700
+ return combinator._parseScalar;
2701
+ }
2702
+ function scalarTree(parser2, seen) {
2703
+ if (seen.has(parser2)) return true;
2704
+ if (parser2._parseScalar === void 0) return false;
2705
+ seen.add(parser2);
2706
+ const def = parser2._def;
2707
+ if (!SCALAR_TAG.test(def.tag)) return false;
2708
+ if ("parsers" in def && !def.parsers.every((child) => scalarTree(child, seen))) return false;
2709
+ if ("parser" in def && !scalarTree(def.parser, seen)) return false;
2710
+ if ("separator" in def && !scalarTree(def.separator, seen)) return false;
2711
+ return def.tag !== "lazy" || scalarTree(def.thunk(), seen);
2712
+ }
2713
+ function scalarRootOf(combinator) {
2714
+ const scalar = combinator._parseScalar;
2715
+ const def = combinator._def;
2716
+ return scalar !== void 0 && def.tag === "grammar" && scalarTree(def.parser, /* @__PURE__ */ new Set()) ? scalar : void 0;
2717
+ }
2718
+
2637
2719
  // src/combinators/sequence.ts
2638
2720
  function sequence(...parsers) {
2639
2721
  let adjacency = null;
@@ -2649,6 +2731,7 @@ function sequence(...parsers) {
2649
2731
  (adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
2650
2732
  }
2651
2733
  const hasAdjacency = adjacency !== null;
2734
+ const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
2652
2735
  const meta = {
2653
2736
  // Union through the nullable prefix — a leading optional()/many() lets a later
2654
2737
  // term's first char start the sequence. Just `parsers[0]` under-approximates.
@@ -2657,165 +2740,96 @@ function sequence(...parsers) {
2657
2740
  isTrivia: false
2658
2741
  };
2659
2742
  const def = { tag: "sequence", parsers };
2660
- let followSentinels;
2661
- function parseTolerant(input, pos, ctx) {
2662
- followSentinels ??= parsers.map((_, i) => {
2663
- const fs = parsers.slice(i + 1).reduce(
2664
- (acc, p) => union(acc, firstSetOf(p)),
2665
- { kind: "empty" }
2666
- );
2667
- return firstSetSentinel(fs);
2668
- });
2669
- const values = def.valueUnused ? void 0 : [];
2743
+ const scalarParsers = parsers.map(scalarOf);
2744
+ const parseScalar = (input, pos, ctx) => {
2670
2745
  let cur = pos;
2671
- const inheritedSync = ctx._sync;
2672
- try {
2673
- for (let i = 0; i < parsers.length; i++) {
2674
- ctx._sync = followSentinels[i] ?? inheritedSync;
2675
- const adj = adjacency === null ? null : adjacency[i];
2676
- if (adj) {
2677
- if (!holdsAdjacency(input, cur, ctx, adj)) return adjacencyFail(cur, adj);
2678
- if (values !== void 0) values.push(null);
2679
- continue;
2680
- }
2681
- if (ctx.trivia && i > 0) {
2682
- const mTlog = cstTlLen(ctx);
2683
- const mLog = ctx._triviaLog?.length ?? 0;
2684
- const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2685
- let scanEnd;
2686
- if (needsDeferredTriviaCommit(ctx)) {
2687
- scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2688
- } else {
2689
- scanEnd = advanceTrivia(input, cur, ctx);
2690
- }
2691
- const scanTlog = cstTlLen(ctx);
2692
- const scanLog = ctx._triviaLog?.length ?? 0;
2693
- const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2694
- const result2 = parsers[i].parse(input, scanEnd, ctx);
2695
- if (!result2.ok) return result2;
2696
- if (result2.span.end > scanEnd) cur = result2.span.end;
2697
- else rollbackScannedTriviaAt(
2698
- ctx,
2699
- mTlog,
2700
- scanTlog,
2701
- mLog,
2702
- scanLog,
2703
- mRootLog,
2704
- scanRootLog
2705
- );
2706
- if (values !== void 0) values.push(result2.value);
2707
- continue;
2708
- }
2709
- const result = parsers[i].parse(input, cur, ctx);
2710
- if (!result.ok) return result;
2711
- if (values !== void 0) values.push(result.value);
2712
- cur = result.span.end;
2746
+ if (strictArity !== 0) {
2747
+ cur = scalarParsers[0](input, cur, ctx);
2748
+ if (cur < 0) return cur;
2749
+ const first = ctx._sv;
2750
+ if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
2751
+ cur = scalarParsers[1](input, cur, ctx);
2752
+ if (cur < 0) return cur;
2753
+ const second = ctx._sv;
2754
+ if (strictArity === 2) {
2755
+ ctx._sv = def.valueUnused ? void 0 : [first, second];
2756
+ return cur;
2713
2757
  }
2714
- } finally {
2715
- ctx._sync = inheritedSync;
2758
+ if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
2759
+ cur = scalarParsers[2](input, cur, ctx);
2760
+ if (cur < 0) return cur;
2761
+ ctx._sv = def.valueUnused ? void 0 : [first, second, ctx._sv];
2762
+ return cur;
2716
2763
  }
2717
- return {
2718
- ok: true,
2719
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2720
- value: values ?? void 0,
2721
- span: { start: pos, end: cur }
2722
- };
2723
- }
2724
- function parseAdjacent(input, pos, ctx) {
2725
2764
  const values = def.valueUnused ? void 0 : [];
2726
- let cur = pos;
2727
- for (let i = 0; i < parsers.length; i++) {
2728
- const adj = adjacency[i];
2729
- if (adj) {
2730
- if (!holdsAdjacency(input, cur, ctx, adj)) return adjacencyFail(cur, adj);
2731
- if (values !== void 0) values.push(null);
2732
- continue;
2733
- }
2734
- if (ctx.trivia && i > 0) {
2735
- let scanEnd;
2736
- const mTlog = cstTlLen(ctx);
2737
- const mLog = ctx._triviaLog?.length ?? 0;
2738
- const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2739
- if (needsDeferredTriviaCommit(ctx)) {
2740
- scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2741
- } else {
2742
- scanEnd = advanceTrivia(input, cur, ctx);
2743
- }
2744
- const scanTlog = cstTlLen(ctx);
2745
- const scanLog = ctx._triviaLog?.length ?? 0;
2746
- const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2747
- const result2 = parsers[i].parse(input, scanEnd, ctx);
2748
- if (!result2.ok) return result2;
2749
- if (result2.span.end > scanEnd) cur = result2.span.end;
2750
- else rollbackScannedTriviaAt(
2751
- ctx,
2752
- mTlog,
2753
- scanTlog,
2754
- mLog,
2755
- scanLog,
2756
- mRootLog,
2757
- scanRootLog
2758
- );
2759
- if (values !== void 0) values.push(result2.value);
2760
- continue;
2761
- }
2762
- const result = parsers[i].parse(input, cur, ctx);
2763
- if (!result.ok) return result;
2764
- if (values !== void 0) values.push(result.value);
2765
- cur = result.span.end;
2766
- }
2767
- return {
2768
- ok: true,
2769
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
2770
- value: values ?? void 0,
2771
- span: { start: pos, end: cur }
2772
- };
2773
- }
2765
+ for (let i = 0; i < scalarParsers.length; i++) {
2766
+ let termPos = cur;
2767
+ if (i > 0 && ctx.trivia) termPos = advanceTrivia(input, cur, ctx);
2768
+ const end = scalarParsers[i](input, termPos, ctx);
2769
+ if (end < 0) return end;
2770
+ if (values !== void 0) values.push(ctx._sv);
2771
+ if (end > termPos || termPos === cur) cur = end;
2772
+ }
2773
+ ctx._sv = values;
2774
+ return cur;
2775
+ };
2776
+ let followSentinels;
2774
2777
  return {
2775
2778
  _tag: "sequence",
2776
2779
  _meta: meta,
2777
2780
  _def: def,
2781
+ _parseScalar: hasAdjacency ? void 0 : parseScalar,
2778
2782
  parse(input, pos, ctx) {
2779
- if (ctx._tolerant) return parseTolerant(input, pos, ctx);
2780
- if (hasAdjacency) return parseAdjacent(input, pos, ctx);
2783
+ const tolerant = ctx._tolerant === true;
2784
+ if (tolerant) {
2785
+ followSentinels ??= parsers.map((_, i) => firstSetSentinel(
2786
+ parsers.slice(i + 1).reduce(
2787
+ (set, parser2) => union(set, firstSetOf(parser2)),
2788
+ { kind: "empty" }
2789
+ )
2790
+ ));
2791
+ }
2792
+ const inheritedSync = ctx._sync;
2793
+ const deferredTrivia = needsDeferredTriviaCommit(ctx);
2781
2794
  const values = def.valueUnused ? void 0 : [];
2782
2795
  let cur = pos;
2783
- for (let i = 0; i < parsers.length; i++) {
2784
- if (ctx.trivia && i > 0) {
2785
- let scanEnd;
2786
- const mTlog = cstTlLen(ctx);
2787
- const mLog = ctx._triviaLog?.length ?? 0;
2788
- const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2789
- if (needsDeferredTriviaCommit(ctx)) {
2790
- scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
2791
- } else {
2792
- scanEnd = advanceTrivia(input, cur, ctx);
2796
+ try {
2797
+ for (let i = 0; i < parsers.length; i++) {
2798
+ if (tolerant) ctx._sync = followSentinels[i] ?? inheritedSync;
2799
+ const assertion = adjacency?.[i];
2800
+ if (assertion) {
2801
+ if (!holdsAdjacency(input, cur, ctx, assertion)) return adjacencyFail(cur, assertion);
2802
+ if (values !== void 0) values.push(null);
2803
+ continue;
2793
2804
  }
2794
- const scanTlog = cstTlLen(ctx);
2795
- const scanLog = ctx._triviaLog?.length ?? 0;
2796
- const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2797
- const result2 = parsers[i].parse(input, scanEnd, ctx);
2798
- if (!result2.ok) return result2;
2799
- if (result2.span.end > scanEnd) {
2800
- cur = result2.span.end;
2801
- } else {
2805
+ let termPos = cur;
2806
+ const markTlog = deferredTrivia ? cstTlLen(ctx) : 0;
2807
+ const markLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
2808
+ const markRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
2809
+ if (ctx.trivia && i > 0) {
2810
+ termPos = deferredTrivia ? commitTriviaScan(scanTriviaCompact(input, cur, ctx)) : advanceTrivia(input, cur, ctx);
2811
+ }
2812
+ const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
2813
+ const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
2814
+ const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
2815
+ const result = parsers[i].parse(input, termPos, ctx);
2816
+ if (!result.ok) return result;
2817
+ if (values !== void 0) values.push(result.value);
2818
+ if (result.span.end > termPos || termPos === cur) cur = result.span.end;
2819
+ else if (deferredTrivia) {
2802
2820
  rollbackScannedTriviaAt(
2803
2821
  ctx,
2804
- mTlog,
2822
+ markTlog,
2805
2823
  scanTlog,
2806
- mLog,
2824
+ markLog,
2807
2825
  scanLog,
2808
- mRootLog,
2826
+ markRootLog,
2809
2827
  scanRootLog
2810
2828
  );
2811
2829
  }
2812
- if (values !== void 0) values.push(result2.value);
2813
- continue;
2814
2830
  }
2815
- const result = parsers[i].parse(input, cur, ctx);
2816
- if (!result.ok) return result;
2817
- if (values !== void 0) values.push(result.value);
2818
- cur = result.span.end;
2831
+ } finally {
2832
+ if (tolerant) ctx._sync = inheritedSync;
2819
2833
  }
2820
2834
  return {
2821
2835
  ok: true,
@@ -2950,7 +2964,8 @@ function choice(...args) {
2950
2964
  disjoint
2951
2965
  };
2952
2966
  const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
2953
- const autoNot = !disjoint && !hasGates && (strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix") ? computeAutoNot(parsers) : parsers.map(() => null);
2967
+ const ordered = strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix";
2968
+ const autoNot = !disjoint && !hasGates && ordered ? computeAutoNot(parsers) : parsers.map(() => null);
2954
2969
  let greedyLitMap = null;
2955
2970
  let sortedParsers = null;
2956
2971
  const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
@@ -2964,6 +2979,37 @@ function choice(...args) {
2964
2979
  } else if (strategy?.tag === "literalsLongestFirst") {
2965
2980
  sortedParsers = strategy.sortedIndices.map((i) => parsers[i]);
2966
2981
  }
2982
+ const scalarParsers = parsers.map(scalarOf);
2983
+ const scalarEligible = !hasGates && parsers.every((p) => p._parseScalar !== void 0) && (disjoint || ordered);
2984
+ const scalarExpected = parsers.flatMap(deriveExpected);
2985
+ const parseScalar = (input, pos, ctx) => {
2986
+ if (disjoint) {
2987
+ const code = pos < input.length ? input.codePointAt(pos) : -1;
2988
+ let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
2989
+ if (idx < 0 && code >= 0) {
2990
+ for (let i = 0; i < parsers.length; i++) {
2991
+ if (inFirstSet(code, parsers[i]._meta.firstSet)) {
2992
+ idx = i;
2993
+ break;
2994
+ }
2995
+ }
2996
+ }
2997
+ if (idx >= 0) {
2998
+ const gate2 = gates[idx];
2999
+ if (!gate2 || gate2(ctx.state)) return scalarParsers[idx](input, pos, ctx);
3000
+ ctx._fx = deriveExpected(parsers[idx]);
3001
+ return ~pos;
3002
+ }
3003
+ } else {
3004
+ for (let i = 0; i < scalarParsers.length; i++) {
3005
+ if (gates[i] && !gates[i](ctx.state)) continue;
3006
+ const end = scalarParsers[i](input, pos, ctx);
3007
+ if (end >= 0 && (!autoNot[i] || !autoNotFires(input, end, autoNot[i]))) return end;
3008
+ }
3009
+ }
3010
+ ctx._fx = scalarExpected;
3011
+ return ~pos;
3012
+ };
2967
3013
  return {
2968
3014
  _tag: "choice",
2969
3015
  _meta: meta,
@@ -2975,6 +3021,7 @@ function choice(...args) {
2975
3021
  strategy: strategy ?? { tag: "firstMatch" },
2976
3022
  autoNot
2977
3023
  },
3024
+ _parseScalar: scalarEligible ? parseScalar : void 0,
2978
3025
  parse(input, pos, ctx) {
2979
3026
  const expected = [];
2980
3027
  let expectedAt = pos;
@@ -3509,8 +3556,8 @@ function attempt(parser2) {
3509
3556
  }
3510
3557
 
3511
3558
  // src/combinators/repeat.ts
3512
- function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3513
- const mark = saveTriviaMark(ctx);
3559
+ function repItem(combinator, input, cur, ctx, guardable, mandatory, rollbackNeeded) {
3560
+ const mark = rollbackNeeded ? saveTriviaMark(ctx) : void 0;
3514
3561
  let pos = cur;
3515
3562
  if (ctx.trivia) {
3516
3563
  if (needsDeferredTriviaCommit(ctx)) {
@@ -3520,24 +3567,24 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3520
3567
  }
3521
3568
  }
3522
3569
  if (pos >= input.length && !mandatory) {
3523
- rollbackTrivia(ctx, mark);
3570
+ if (mark !== void 0) rollbackTrivia(ctx, mark);
3524
3571
  return "stop";
3525
3572
  }
3526
3573
  if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
3527
- rollbackTrivia(ctx, mark);
3574
+ if (mark !== void 0) rollbackTrivia(ctx, mark);
3528
3575
  return "stop";
3529
3576
  }
3530
3577
  const result = combinator.parse(input, pos, ctx);
3531
3578
  if (!result.ok) {
3532
- rollbackTrivia(ctx, mark);
3579
+ if (mark !== void 0) rollbackTrivia(ctx, mark);
3533
3580
  if (result.committed) return { fail: result, failPos: pos };
3534
3581
  return { fail: result, failPos: pos };
3535
3582
  }
3536
3583
  if (result.span.end === pos && !mandatory) {
3537
- rollbackTrivia(ctx, mark);
3584
+ if (mark !== void 0) rollbackTrivia(ctx, mark);
3538
3585
  return "stop";
3539
3586
  }
3540
- return { value: result.value, end: result.span.end };
3587
+ return result;
3541
3588
  }
3542
3589
  function resolveBounds(what, opts) {
3543
3590
  const min = opts.min ?? 0;
@@ -3550,6 +3597,21 @@ function resolveBounds(what, opts) {
3550
3597
  if (max < min) bad(`max (${max}) is less than min (${min}) \u2014 the combinator could never succeed`);
3551
3598
  return { min, max };
3552
3599
  }
3600
+ function repeatScalarTail(combinator, child, input, cur, ctx, guardable, values, remaining) {
3601
+ while (cur < input.length && remaining > 0) {
3602
+ let itemPos = cur;
3603
+ if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
3604
+ if (itemPos >= input.length) break;
3605
+ if (guardable && !startsFirstSet(combinator, input, itemPos)) break;
3606
+ const end = child(input, itemPos, ctx);
3607
+ if (end <= itemPos) break;
3608
+ if (values !== void 0) values.push(ctx._sv);
3609
+ cur = end;
3610
+ remaining--;
3611
+ }
3612
+ ctx._sv = values;
3613
+ return cur;
3614
+ }
3553
3615
  function many(combinator, opts = {}) {
3554
3616
  const { min, max } = resolveBounds("many()", opts);
3555
3617
  if (min >= 1) return atLeast(combinator, min, max);
@@ -3561,17 +3623,21 @@ function many(combinator, opts = {}) {
3561
3623
  const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
3562
3624
  let expected;
3563
3625
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
3626
+ const scalarChild = scalarOf(combinator);
3627
+ const parseScalar = (input, pos, ctx) => repeatScalarTail(combinator, scalarChild, input, pos, ctx, guardable, def.valueUnused ? void 0 : [], max);
3564
3628
  return {
3565
3629
  _tag: "many",
3566
3630
  _meta: meta,
3567
3631
  _def: def,
3632
+ _parseScalar: parseScalar,
3568
3633
  parse(input, pos, ctx) {
3569
3634
  const values = def.valueUnused ? void 0 : [];
3635
+ const rollbackNeeded = needsTriviaRollback(ctx);
3570
3636
  let cur = pos;
3571
3637
  let count = 0;
3572
3638
  while (cur < input.length) {
3573
3639
  if (count >= max) break;
3574
- const item = repItem(combinator, input, cur, ctx, guardable, false);
3640
+ const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
3575
3641
  if (item === "stop") break;
3576
3642
  if ("fail" in item) {
3577
3643
  if (!item.fail.ok && item.fail.committed) return item.fail;
@@ -3588,7 +3654,7 @@ function many(combinator, opts = {}) {
3588
3654
  }
3589
3655
  if (values !== void 0) values.push(item.value);
3590
3656
  count++;
3591
- cur = item.end;
3657
+ cur = item.span.end;
3592
3658
  }
3593
3659
  return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
3594
3660
  }
@@ -3606,30 +3672,47 @@ function atLeast(combinator, min, max) {
3606
3672
  const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
3607
3673
  let expected;
3608
3674
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
3675
+ const scalarChild = scalarOf(combinator);
3676
+ const parseScalar = (input, pos, ctx) => {
3677
+ let cur = scalarChild(input, pos, ctx);
3678
+ if (cur < 0) return cur;
3679
+ const values = def.valueUnused ? void 0 : [ctx._sv];
3680
+ for (let count = 1; count < min; count++) {
3681
+ let itemPos = cur;
3682
+ if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
3683
+ const end = scalarChild(input, itemPos, ctx);
3684
+ if (end < 0) return ~cur;
3685
+ cur = end;
3686
+ if (values !== void 0) values.push(ctx._sv);
3687
+ }
3688
+ return repeatScalarTail(combinator, scalarChild, input, cur, ctx, guardable, values, max - min);
3689
+ };
3609
3690
  return {
3610
3691
  _tag: "oneOrMore",
3611
3692
  _meta: meta,
3612
3693
  _def: def,
3694
+ _parseScalar: parseScalar,
3613
3695
  parse(input, pos, ctx) {
3614
3696
  const first = combinator.parse(input, pos, ctx);
3615
3697
  if (!first.ok) return first;
3616
3698
  const values = def.valueUnused ? void 0 : [first.value];
3699
+ const rollbackNeeded = needsTriviaRollback(ctx);
3617
3700
  let cur = first.span.end;
3618
3701
  let count = 1;
3619
3702
  while (count < min) {
3620
- const item = repItem(combinator, input, cur, ctx, guardable, true);
3703
+ const item = repItem(combinator, input, cur, ctx, guardable, true, rollbackNeeded);
3621
3704
  if (item === "stop" || "fail" in item) {
3622
3705
  if (item !== "stop" && !item.fail.ok && item.fail.committed) return item.fail;
3623
3706
  expected ??= deriveExpected(combinator);
3624
3707
  return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
3625
3708
  }
3626
3709
  if (values !== void 0) values.push(item.value);
3627
- cur = item.end;
3710
+ cur = item.span.end;
3628
3711
  count++;
3629
3712
  }
3630
3713
  while (cur < input.length) {
3631
3714
  if (count >= max) break;
3632
- const item = repItem(combinator, input, cur, ctx, guardable, false);
3715
+ const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
3633
3716
  if (item === "stop") break;
3634
3717
  if ("fail" in item) {
3635
3718
  if (!item.fail.ok && item.fail.committed) return item.fail;
@@ -3646,7 +3729,7 @@ function atLeast(combinator, min, max) {
3646
3729
  }
3647
3730
  if (values !== void 0) values.push(item.value);
3648
3731
  count++;
3649
- cur = item.end;
3732
+ cur = item.span.end;
3650
3733
  }
3651
3734
  return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
3652
3735
  }
@@ -3659,10 +3742,22 @@ function optional(combinator) {
3659
3742
  isTrivia: false
3660
3743
  };
3661
3744
  const firstSetSkippable = !matchesEmpty(combinator);
3745
+ const scalarChild = scalarOf(combinator);
3746
+ const parseScalar = (input, pos, ctx) => {
3747
+ if (firstSetSkippable && !startsFirstSet(combinator, input, pos)) {
3748
+ ctx._sv = null;
3749
+ return pos;
3750
+ }
3751
+ const end = scalarChild(input, pos, ctx);
3752
+ if (end >= 0) return end;
3753
+ ctx._sv = null;
3754
+ return pos;
3755
+ };
3662
3756
  return {
3663
3757
  _tag: "optional",
3664
3758
  _meta: meta,
3665
3759
  _def: { tag: "optional", parser: combinator },
3760
+ _parseScalar: parseScalar,
3666
3761
  parse(input, pos, ctx) {
3667
3762
  if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
3668
3763
  return { ok: true, value: null, span: { start: pos, end: pos } };
@@ -3699,6 +3794,43 @@ function sepBy(combinator, separatorArg, opts = {}) {
3699
3794
  expected ??= deriveExpected(combinator);
3700
3795
  return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: at, end: at } };
3701
3796
  };
3797
+ const scalarExpected = deriveExpected(combinator);
3798
+ const scalarChild = scalarOf(combinator);
3799
+ const scalarSeparator = scalarOf(separator);
3800
+ const parseScalar = (input, pos, ctx) => {
3801
+ let cur = scalarChild(input, pos, ctx);
3802
+ if (cur < 0) {
3803
+ if (min >= 1) {
3804
+ ctx._fx = scalarExpected.length > 0 ? scalarExpected : [combinator._tag];
3805
+ return ~pos;
3806
+ }
3807
+ ctx._sv = [];
3808
+ return pos;
3809
+ }
3810
+ const values = [ctx._sv];
3811
+ while (values.length < max && (cur < input.length || values.length < min)) {
3812
+ const beforeSeparator = cur;
3813
+ let separatorPos = cur;
3814
+ if (ctx.trivia) separatorPos = advanceTrivia(input, cur, ctx);
3815
+ const separatorEnd = scalarSeparator(input, separatorPos, ctx);
3816
+ if (separatorEnd < 0) break;
3817
+ let itemPos = separatorEnd;
3818
+ if (ctx.trivia) itemPos = advanceTrivia(input, itemPos, ctx);
3819
+ const itemEnd = scalarChild(input, itemPos, ctx);
3820
+ if (itemEnd < 0) {
3821
+ cur = trailing === "allow" ? separatorEnd : beforeSeparator;
3822
+ break;
3823
+ }
3824
+ values.push(ctx._sv);
3825
+ cur = itemEnd;
3826
+ }
3827
+ if (values.length < min) {
3828
+ ctx._fx = scalarExpected.length > 0 ? scalarExpected : [combinator._tag];
3829
+ return ~cur;
3830
+ }
3831
+ ctx._sv = values;
3832
+ return cur;
3833
+ };
3702
3834
  return {
3703
3835
  _tag: "sepBy",
3704
3836
  _meta: meta,
@@ -3714,6 +3846,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
3714
3846
  // this option surface already; parity is held by test/parity, not by hope.
3715
3847
  ...keepSeparators ? { keepSeparators: true } : {}
3716
3848
  },
3849
+ _parseScalar: keepSeparators ? void 0 : parseScalar,
3717
3850
  parse(input, pos, ctx) {
3718
3851
  const first = combinator.parse(input, pos, ctx);
3719
3852
  const values = [];
@@ -3827,8 +3960,20 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
3827
3960
  }
3828
3961
 
3829
3962
  // src/combinators/ref.ts
3963
+ function withRuleTrivia(trivia2, ctx, run3) {
3964
+ const savedLabels = ctx.triviaKindLabels;
3965
+ ctx.trivia = trivia2;
3966
+ ctx.triviaKindLabels = trivia2._meta.triviaKindLabels;
3967
+ try {
3968
+ return run3();
3969
+ } finally {
3970
+ ctx.trivia = void 0;
3971
+ ctx.triviaKindLabels = savedLabels;
3972
+ }
3973
+ }
3830
3974
  function ref() {
3831
3975
  let resolved = null;
3976
+ let resolvedScalar = null;
3832
3977
  let ownBoundary = false;
3833
3978
  const meta = {
3834
3979
  firstSet: any(),
@@ -3845,25 +3990,28 @@ function ref() {
3845
3990
  return resolved;
3846
3991
  }
3847
3992
  },
3993
+ _parseScalar(input, pos, ctx) {
3994
+ const scalar = resolvedScalar;
3995
+ if (!scalar) throw new Error("ref<T>() used before .define() was called");
3996
+ const gt = meta.grammarTrivia;
3997
+ if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
3998
+ return withRuleTrivia(gt, ctx, () => scalar(input, pos, ctx));
3999
+ }
4000
+ return scalar(input, pos, ctx);
4001
+ },
3848
4002
  parse(input, pos, ctx) {
3849
- if (!resolved) throw new Error("ref<T>() used before .define() was called");
4003
+ const parser2 = resolved;
4004
+ if (!parser2) throw new Error("ref<T>() used before .define() was called");
3850
4005
  const gt = meta.grammarTrivia;
3851
4006
  if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
3852
- const savedLabels = ctx.triviaKindLabels;
3853
- ctx.trivia = gt;
3854
- ctx.triviaKindLabels = gt._meta.triviaKindLabels;
3855
- try {
3856
- return resolved.parse(input, pos, ctx);
3857
- } finally {
3858
- ctx.trivia = void 0;
3859
- ctx.triviaKindLabels = savedLabels;
3860
- }
4007
+ return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
3861
4008
  }
3862
- return resolved.parse(input, pos, ctx);
4009
+ return parser2.parse(input, pos, ctx);
3863
4010
  },
3864
4011
  define(p) {
3865
4012
  if (resolved) throw new Error("ref<T>() already defined");
3866
4013
  resolved = p;
4014
+ resolvedScalar = scalarOf(p);
3867
4015
  ownBoundary = hasOwnTriviaBoundary(p);
3868
4016
  meta.firstSet = p._meta.firstSet;
3869
4017
  meta.canMatchNewline = p._meta.canMatchNewline;
@@ -4021,6 +4169,24 @@ function parser(opts, root) {
4021
4169
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
4022
4170
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
4023
4171
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
4172
+ const rootScalar = scalarOf(root);
4173
+ const scalarEligible = opts.trackLines !== true && opts.recover !== true && !opaqueRootCapture && !forceCaptureTrivia && captureKinds === void 0;
4174
+ const parseScalar = scalarEligible ? (input, pos, ctx) => {
4175
+ const savedTrivia = ctx.trivia;
4176
+ const savedLabels = ctx.triviaKindLabels;
4177
+ if (clearTrivia) {
4178
+ ctx.trivia = void 0;
4179
+ ctx.triviaKindLabels = void 0;
4180
+ } else if (scopeTrivia !== void 0) {
4181
+ ctx.trivia = scopeTrivia;
4182
+ ctx.triviaKindLabels = scopeLabels;
4183
+ }
4184
+ const end = rootScalar(input, pos, ctx);
4185
+ ctx.trivia = savedTrivia;
4186
+ ctx.triviaKindLabels = savedLabels;
4187
+ return end;
4188
+ } : void 0;
4189
+ let publicScalar;
4024
4190
  const grammar = {
4025
4191
  _tag: "grammar",
4026
4192
  _meta: {
@@ -4044,7 +4210,20 @@ function parser(opts, root) {
4044
4210
  constructionTrackLines: trackLinesPolicy,
4045
4211
  ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
4046
4212
  },
4213
+ _parseScalar: parseScalar,
4047
4214
  parse(input, pos, _ctx) {
4215
+ if (pos === void 0 && _ctx === void 0) {
4216
+ publicScalar ??= scalarRootOf(grammar) ?? null;
4217
+ if (publicScalar) {
4218
+ const ctx2 = createParseContext();
4219
+ const end = publicScalar(input, 0, ctx2);
4220
+ if (end < 0) {
4221
+ const at = ~end;
4222
+ return { ok: false, expected: ctx2._fx ?? [], span: { start: at, end: at } };
4223
+ }
4224
+ return { ok: true, value: ctx2._sv, span: { start: 0, end } };
4225
+ }
4226
+ }
4048
4227
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
4049
4228
  const trackLines = trackLinesOf(_ctx);
4050
4229
  const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
@@ -4082,6 +4261,9 @@ function parse(combinator, input, opts = {}) {
4082
4261
  _analyzed.add(combinator);
4083
4262
  markUnusedValues(combinator);
4084
4263
  }
4264
+ if (!opts.trackLines && !opts.recover && combinator._def.tag === "grammar" && combinator._meta.grammarScanSkip === void 0) {
4265
+ return combinator.parse(input);
4266
+ }
4085
4267
  const trackLines = opts.trackLines ?? combinator._meta.grammarTrackLines ?? false;
4086
4268
  const lineContext = trackLines ? createParseLineContext(input, 0) : void 0;
4087
4269
  const lineIndex = lineContext?.lineIndex;
@@ -4820,11 +5002,54 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
4820
5002
  }
4821
5003
 
4822
5004
  // src/combinators/map.ts
5005
+ var JSON_STRING_BODY = String.raw`(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*`;
4823
5006
  function transform(combinator, fn) {
5007
+ const observesSpan = fn.length > 1;
5008
+ const sequenceDef = combinator._def.tag === "sequence" ? combinator._def : void 0;
5009
+ const terms = sequenceDef?.parsers;
5010
+ const inner = terms?.[1];
5011
+ const fused = terms?.length === 3 && terms[0]._def.tag === "literal" && terms[0]._def.value === '"' && !terms[0]._def.caseInsensitive && inner._def.tag === "regex" && inner._def.source === JSON_STRING_BODY && inner._def.flags === "" && terms[2]._def.tag === "literal" && terms[2]._def.value === '"' && !terms[2]._def.caseInsensitive && inner._stickyRegex !== void 0;
5012
+ const child = scalarOf(combinator);
5013
+ const parseScalar = fused ? (() => {
5014
+ const body = inner._stickyRegex;
5015
+ const tuple = ['"', "", '"'];
5016
+ const expected = [JSON.stringify('"')];
5017
+ return (input, pos, ctx) => {
5018
+ if (ctx.trivia !== void 0) {
5019
+ const end2 = child(input, pos, ctx);
5020
+ if (end2 < 0) return end2;
5021
+ ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end: end2 }) : fn(ctx._sv);
5022
+ return end2;
5023
+ }
5024
+ if (input.charCodeAt(pos) !== 34) {
5025
+ ctx._fx = expected;
5026
+ return ~pos;
5027
+ }
5028
+ body.lastIndex = pos + 1;
5029
+ const match = body.exec(input);
5030
+ const close = pos + 1 + match[0].length;
5031
+ if (input.charCodeAt(close) !== 34) {
5032
+ ctx._fx = expected;
5033
+ return ~close;
5034
+ }
5035
+ tuple[1] = match[0];
5036
+ const end = close + 1;
5037
+ ctx._sv = observesSpan ? fn(tuple, { start: pos, end }) : fn(tuple);
5038
+ return end;
5039
+ };
5040
+ })() : /* @__PURE__ */ (() => {
5041
+ return (input, pos, ctx) => {
5042
+ const end = child(input, pos, ctx);
5043
+ if (end < 0) return end;
5044
+ ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end }) : fn(ctx._sv);
5045
+ return end;
5046
+ };
5047
+ })();
4824
5048
  return {
4825
5049
  _tag: "transform",
4826
5050
  _meta: combinator._meta,
4827
5051
  _def: { tag: "transform", parser: combinator, fn },
5052
+ _parseScalar: parseScalar,
4828
5053
  parse(input, pos, ctx) {
4829
5054
  const result = combinator.parse(input, pos, ctx);
4830
5055
  if (!result.ok) return result;
@@ -4839,9 +5064,11 @@ function trivia(combinator) {
4839
5064
  _meta: {
4840
5065
  ...combinator._meta,
4841
5066
  isTrivia: true,
5067
+ triviaScanner: fastTriviaScanner(combinator),
4842
5068
  ...kindLabels ? { triviaKindLabels: kindLabels } : {}
4843
5069
  },
4844
5070
  _def: { tag: "trivia", parser: combinator },
5071
+ _parseScalar: scalarOf(combinator),
4845
5072
  parse: combinator.parse.bind(combinator)
4846
5073
  };
4847
5074
  }
@@ -9772,6 +9999,9 @@ if(ctx._rootTriviaLog!==undefined&&ctx._rootTriviaLog.length!==rt)ctx._rootTrivi
9772
9999
  function q(s) {
9773
10000
  return JSON.stringify(s);
9774
10001
  }
10002
+ function isAsciiOnlyClass(cls) {
10003
+ return cls !== null && cls !== void 0 && cls.hi.length === 0;
10004
+ }
9775
10005
  var NO_SINKS = { fd: false, er: false };
9776
10006
  function sinkSlots(t, s) {
9777
10007
  return `${s.fd ? `,${t}fd=0` : ""}${s.er ? `,${t}er=0` : ""}`;
@@ -10318,12 +10548,13 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
10318
10548
  return `${head}EC.e=pos;return ''}`;
10319
10549
  case OP_GATE: {
10320
10550
  const child = link(code[ip + 2]);
10321
- const ci = classes.push([t.cc[code[ip + 1]]]) - 1;
10551
+ const resolved = t.cc[code[ip + 1]];
10552
+ const ci = classes.push([resolved]) - 1;
10322
10553
  classPlan.push([code[ip + 1]]);
10323
10554
  const cls = hoist("cl", `CLS[${ci}][0]`);
10324
10555
  const xf = fxRef(code[ip + 3]);
10325
10556
  return `${head}
10326
- if(!classHas(${cls},lead(input,pos))){ctx._fe=pos;ctx._fx=${xf};return FAIL}
10557
+ if(${staticBuild && isAsciiOnlyClass(resolved) ? `${cls}.ascii[input.charCodeAt(pos)]!==1` : `!classHas(${cls},lead(input,pos))`}){ctx._fe=pos;ctx._fx=${xf};return FAIL}
10327
10558
  return ${child}(input,pos,ctx)
10328
10559
  }`;
10329
10560
  }
@@ -10666,10 +10897,11 @@ return v
10666
10897
  const asc = hoist("as", `DISP[${di}].ascii`);
10667
10898
  const hiArr = table.hi;
10668
10899
  const armSwitch = arms.map((a, i) => `case ${i}:v=${a}(input,pos,ctx);break`).join("\n");
10900
+ const directAscii = staticBuild && table.hi.length === 0;
10669
10901
  return `${head}
10670
- const c=lead(input,pos)
10902
+ const c=${directAscii ? "input.charCodeAt(pos)" : "lead(input,pos)"}
10671
10903
  let arm=-1
10672
- if(c>=0&&c<128){const a=${asc}[c];if(a!==0)arm=a-1}
10904
+ if(${directAscii ? "c<128" : "c>=0&&c<128"}){const a=${asc}[c];if(a!==0)arm=a-1}
10673
10905
  ${hiArr.length === 0 ? "" : `else if(c>=128){const h=${hoist("hi", `DISP[${di}].hi`)}
10674
10906
  for(let i=0;i<h.length;i+=3){if(c>=h[i]&&c<=h[i+1]){arm=h[i+2];break}}}`}
10675
10907
  if(arm>=0){
@@ -10691,7 +10923,9 @@ return FAIL
10691
10923
  const di = code[ip + 1];
10692
10924
  const expected = Array.from({ length: n }, (_, i) => fxRef(code[base + n + i]));
10693
10925
  const gates = Array.from({ length: n }, (_, i) => table.armCls[i] ?? null);
10694
- const gateRefs = Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
10926
+ const maskable = n <= 32;
10927
+ const directAsciiMask = staticBuild && maskable && gates.every(isAsciiOnlyClass);
10928
+ const gateRefs = directAsciiMask ? [] : Array.from({ length: n }, (_, i) => hoist("g", `DISP[${di}].armCls[${i}]`));
10695
10929
  const tokenCandidate = tokenChoiceCandidates.get(ip);
10696
10930
  const pretests = Array.from({ length: n }, (_, i) => {
10697
10931
  if (tokenCandidate?.arm === i) {
@@ -10711,7 +10945,6 @@ return FAIL
10711
10945
  const sequence6 = largeChoiceScalarSequences.get(code[base + i]);
10712
10946
  return sequence6 === void 0 ? void 0 : { sequence: scalarSequenceRef(sequence6) };
10713
10947
  });
10714
- const maskable = n <= 32;
10715
10948
  const maskName = maskable ? hoist("mk", `MASK[${masks.push(maskForClassRow(gates)) - 1}]`) : "";
10716
10949
  if (maskable) maskPlan.push(~di);
10717
10950
  const p = tmp();
@@ -10773,16 +11006,16 @@ ${merge2}
10773
11006
  ctx._fe=pos;ctx._fx=acc??${choiceFx}
10774
11007
  return FAIL`;
10775
11008
  return `${head}
10776
- const c=lead(input,pos)
11009
+ const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
10777
11010
  ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
10778
11011
  ${deepAt.map((at, i) => `let ${at},${deepFx[i]}`).join("\n")}
10779
11012
  ${maskable ? `if(c<128){
10780
- const bits=${maskName}[c<0?128:c]
11013
+ const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
10781
11014
  if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10782
11015
  ${lazyArms(true)}
10783
- }else{
11016
+ }${directAsciiMask ? "" : `else{
10784
11017
  ${lazyArms(false)}
10785
- }
11018
+ }`}
10786
11019
  ` : lazyArms(false)}
10787
11020
  ${finish}
10788
11021
  }`;
@@ -10833,7 +11066,7 @@ if(ctx._fc===true){${startFailureExact ? `if(best===pos){acc=${catchName}(${i},0
10833
11066
  ${rollbackFor(i)}
10834
11067
  }${routeMiss}${sequenceMiss}`;
10835
11068
  }).join("\n") : "";
10836
- const generalArms = arms.map((arm, i) => {
11069
+ const generalArms = directAsciiMask ? "" : arms.map((arm, i) => {
10837
11070
  const pretest = pretests[i];
10838
11071
  const decision = pretest?.token === void 0 && pretest?.sequence === void 0 ? "" : tmp();
10839
11072
  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("||")})`;
@@ -10863,12 +11096,12 @@ ${rollbackFor(i)}
10863
11096
  }${miss}`;
10864
11097
  }).join("\n");
10865
11098
  return `${head}
10866
- const c=lead(input,pos)
11099
+ const c=${directAsciiMask ? "input.charCodeAt(pos)" : "lead(input,pos)"}
10867
11100
  ${hasRollback ? emitMark(p, L.buf, L.raw, sinks) : ""}
10868
11101
  let acc
10869
11102
  let best=pos
10870
11103
  ${maskable ? `if(c<128){
10871
- const bits=${maskName}[c<0?128:c]
11104
+ const bits=${maskName}[${directAsciiMask ? "c" : "c<0?128:c"}]
10872
11105
  if(bits===0){ctx._fe=pos;ctx._fx=${choiceFx};return FAIL}
10873
11106
  ${startFailureExact ? "" : "let prev=0"}
10874
11107
  ${maskArms}
@@ -10963,14 +11196,18 @@ return [key,v]
10963
11196
  const itemFx = reportItem ? fxRef(code[ip + 6]) : "EMPTY_FX";
10964
11197
  const collect = op === OP_REP;
10965
11198
  let itemCls;
11199
+ let itemAscii = false;
10966
11200
  if (!REC2) {
10967
11201
  const itemClassIndex = sepIp < 0 ? code[ip + 7] : -1;
10968
11202
  if (itemClassIndex >= 0) {
10969
- const ci = classes.push([t.cc[itemClassIndex]]) - 1;
11203
+ const resolved = t.cc[itemClassIndex];
11204
+ const ci = classes.push([resolved]) - 1;
10970
11205
  classPlan.push([itemClassIndex]);
10971
11206
  itemCls = hoist("ri", `CLS[${ci}][0]`);
11207
+ itemAscii = staticBuild && isAsciiOnlyClass(resolved);
10972
11208
  }
10973
11209
  }
11210
+ const itemMiss = (at) => itemAscii ? `${itemCls}.ascii[input.charCodeAt(${at})]!==1` : `!classHas(${itemCls},lead(input,${at}))`;
10974
11211
  const skipBeforeFirst = sepIp < 0 && min === 0;
10975
11212
  const p = tmp();
10976
11213
  const via = sep !== void 0 ? "false" : min === 0 ? skipBeforeFirst ? "true" : "count>0" : `count>=${min}&&count>0`;
@@ -11030,7 +11267,7 @@ let count=0
11030
11267
  for(;;){
11031
11268
  ${max >= 0 ? `if(count>=${max})break
11032
11269
  ` : ""}${sep !== void 0 ? `if(count>0&&count>=${min}&&cur>=input.length)break
11033
- ` : ""}${itemCls !== void 0 && sep === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}&&!classHas(${itemCls},lead(input,cur)))break
11270
+ ` : ""}${itemCls !== void 0 && sep === void 0 ? `if(count>=${min}&&${p}gate&&${hasTrivia === "false" ? "true" : hasTrivia === "true" ? "false" : "!hasTrivia"}&&${itemMiss("cur")})break
11034
11271
  ` : ""}let ${p}raw=0,${p}tl=0,${p}lv=0,${p}lg=0,${p}rt=0${sinks.fd ? `,${p}fd=0` : ""}${sinks.er ? `,${p}er=0` : ""}
11035
11272
  ${markBody}
11036
11273
  let itemStart=cur
@@ -11055,7 +11292,7 @@ itemStart=${hasTrivia === "false" ? "EC.e" : hasTrivia === "true" ? `${skip}(inp
11055
11292
  ${rb}
11056
11293
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
11057
11294
  }
11058
- ${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&!classHas(${itemCls},lead(input,itemStart))){
11295
+ ${itemCls === void 0 ? "" : `if(count>=${min}&&${p}gate&&${itemMiss("itemStart")}){
11059
11296
  ${rb}
11060
11297
  ${trailingAllowed ? "if(sepEnd>=0)cur=sepEnd\n" : ""}break
11061
11298
  }
@@ -17106,7 +17343,7 @@ function compileRuleMap(ruleMap, opts = {}) {
17106
17343
  }
17107
17344
 
17108
17345
  // src/version.ts
17109
- var PARSEMAN_VERSION = "0.50.1";
17346
+ var PARSEMAN_VERSION = "0.50.3";
17110
17347
 
17111
17348
  // src/compiler/compile-linkable-table.ts
17112
17349
  function isLocal(rule) {