parseman 0.58.2 → 0.58.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 (56) hide show
  1. package/dist/analysis/diagnostics.js +203 -37
  2. package/dist/analysis/diagnostics.js.map +3 -3
  3. package/dist/cli/index.js +203 -37
  4. package/dist/cli/index.js.map +3 -3
  5. package/dist/combinators/first-set.d.ts.map +1 -1
  6. package/dist/combinators/regex.d.ts.map +1 -1
  7. package/dist/compiler/token-capability.js +28 -4
  8. package/dist/compiler/token-capability.js.map +2 -2
  9. package/dist/compiler/token-scanner.d.ts.map +1 -1
  10. package/dist/index.js +207 -41
  11. package/dist/index.js.map +3 -3
  12. package/dist/language-service/index.js +10 -3
  13. package/dist/language-service/index.js.map +2 -2
  14. package/dist/lead-ranges.d.ts +26 -0
  15. package/dist/lead-ranges.d.ts.map +1 -0
  16. package/dist/plugin/index.js +207 -41
  17. package/dist/plugin/index.js.map +3 -3
  18. package/dist/recovery/scan.d.ts.map +1 -1
  19. package/dist/regex/classes.d.ts +5 -3
  20. package/dist/regex/classes.d.ts.map +1 -1
  21. package/dist/regex/first-set.d.ts +7 -1
  22. package/dist/regex/first-set.d.ts.map +1 -1
  23. package/dist/run/index.js +10 -3
  24. package/dist/run/index.js.map +2 -2
  25. package/dist/table/assemble.d.ts.map +1 -1
  26. package/dist/table/compile-rule-map.d.ts.map +1 -1
  27. package/dist/table/emit-assembly.d.ts +8 -1
  28. package/dist/table/emit-assembly.d.ts.map +1 -1
  29. package/dist/table/encode-baseline.d.ts.map +1 -1
  30. package/dist/table/index.js +206 -40
  31. package/dist/table/index.js.map +3 -3
  32. package/dist/table/program.d.ts.map +1 -1
  33. package/dist/table/scan-shapes.d.ts +1 -1
  34. package/dist/table/scan-shapes.d.ts.map +1 -1
  35. package/dist/table/site-labels.d.ts.map +1 -1
  36. package/dist/table/trivia-gap.d.ts +11 -1
  37. package/dist/table/trivia-gap.d.ts.map +1 -1
  38. package/dist/version.d.ts +1 -1
  39. package/package.json +1 -1
  40. package/src/combinators/choice.ts +4 -0
  41. package/src/combinators/first-set.ts +13 -4
  42. package/src/combinators/regex.ts +28 -9
  43. package/src/compiler/token-scanner.ts +4 -1
  44. package/src/lead-ranges.ts +53 -0
  45. package/src/recovery/scan.ts +2 -3
  46. package/src/regex/classes.ts +22 -7
  47. package/src/regex/first-set.ts +67 -12
  48. package/src/table/assemble.ts +42 -3
  49. package/src/table/compile-rule-map.ts +5 -3
  50. package/src/table/emit-assembly.ts +42 -8
  51. package/src/table/encode-baseline.ts +2 -1
  52. package/src/table/program.ts +2 -1
  53. package/src/table/scan-shapes.ts +5 -2
  54. package/src/table/site-labels.ts +2 -1
  55. package/src/table/trivia-gap.ts +19 -0
  56. package/src/version.ts +1 -1
package/dist/index.js CHANGED
@@ -1,3 +1,32 @@
1
+ // src/lead-ranges.ts
2
+ function rangesHaveLead(ranges, code) {
3
+ for (const r of ranges) if (code >= r.lo && code <= r.hi) return true;
4
+ if (code <= 65535) return false;
5
+ const high = 55296 + (code - 65536 >> 10);
6
+ for (const r of ranges) if (high >= r.lo && high <= r.hi) return true;
7
+ return false;
8
+ }
9
+ function leadRanges(ranges) {
10
+ let out;
11
+ for (const r of ranges) {
12
+ const lo = Math.max(r.lo, 55296), hi = Math.min(r.hi, 56319);
13
+ if (lo <= hi) (out ??= [...ranges]).push({ lo: 65536 + (lo - 55296 << 10), hi: 65536 + (hi - 55296 << 10) + 1023 });
14
+ }
15
+ return out ?? ranges;
16
+ }
17
+ function implicitLeadsDropped(ranges) {
18
+ const implied = leadRanges(ranges.filter((r) => r.lo <= 65535)).filter((r) => r.lo > 65535);
19
+ const out = [];
20
+ for (const r of ranges) {
21
+ let pieces = [{ lo: r.lo, hi: r.hi }];
22
+ if (r.hi > 65535) for (const c of implied) {
23
+ pieces = pieces.flatMap((q2) => q2.hi < c.lo || q2.lo > c.hi ? [q2] : [...q2.lo < c.lo ? [{ lo: q2.lo, hi: c.lo - 1 }] : [], ...q2.hi > c.hi ? [{ lo: c.hi + 1, hi: q2.hi }] : []]);
24
+ }
25
+ out.push(...pieces);
26
+ }
27
+ return out;
28
+ }
29
+
1
30
  // src/combinators/first-set.ts
2
31
  function classifyFinalChoice(arms, resolve, activeTrivia) {
3
32
  const firstSets = [];
@@ -59,8 +88,9 @@ function union(a, b) {
59
88
  function intersects(a, b) {
60
89
  if (a.kind === "any" || b.kind === "any") return true;
61
90
  if (a.kind === "empty" || b.kind === "empty") return false;
62
- for (const ra of a.ranges) {
63
- for (const rb of b.ranges) {
91
+ const bs = leadRanges(b.ranges);
92
+ for (const ra of leadRanges(a.ranges)) {
93
+ for (const rb of bs) {
64
94
  if (ra.lo <= rb.hi && rb.lo <= ra.hi) return true;
65
95
  }
66
96
  }
@@ -76,6 +106,9 @@ function startsFirstSet(combinator, input, pos) {
76
106
  const code = input.codePointAt(pos);
77
107
  if (code === void 0) return false;
78
108
  for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
109
+ if (code <= 65535) return false;
110
+ const high = 55296 + (code - 65536 >> 10);
111
+ for (const r of fs.ranges) if (high >= r.lo && high <= r.hi) return true;
79
112
  return false;
80
113
  }
81
114
  function fromRange(lo, hi) {
@@ -176,12 +209,13 @@ function narrowBy(acc, constraint) {
176
209
  if (acc.kind === "any") return constraint;
177
210
  if (acc.kind === "empty" || constraint.kind === "empty") return { kind: "empty" };
178
211
  const ranges = [];
179
- for (const a of acc.ranges) for (const b of constraint.ranges) {
212
+ const bs = leadRanges(constraint.ranges);
213
+ for (const a of leadRanges(acc.ranges)) for (const b of bs) {
180
214
  const lo = Math.max(a.lo, b.lo);
181
215
  const hi = Math.min(a.hi, b.hi);
182
216
  if (lo <= hi) ranges.push({ lo, hi });
183
217
  }
184
- return ranges.length === 0 ? { kind: "empty" } : { kind: "ranges", ranges };
218
+ return ranges.length === 0 ? { kind: "empty" } : { kind: "ranges", ranges: implicitLeadsDropped(ranges) };
185
219
  }
186
220
  function applyAssertion(fs, assertion) {
187
221
  return assertion === null ? fs : fs.kind === "empty" ? assertion : narrowBy(fs, assertion);
@@ -736,11 +770,17 @@ function shorthandRanges(ch2) {
736
770
  if (ch2 === "s") return SPACE_RANGES;
737
771
  return [[48, 57], [65, 90], [97, 122], [95, 95]];
738
772
  }
739
- function readUnicodeEscape(body, i) {
773
+ function readUnicodeEscape(body, i, unicode = false) {
740
774
  if (body[i] !== "\\" || body[i + 1] !== "u") return null;
741
775
  const hex = body.slice(i + 2, i + 6);
742
776
  if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
743
- return { cp: Number.parseInt(hex, 16), next: i + 6 };
777
+ const cp = Number.parseInt(hex, 16);
778
+ if (unicode && cp >= 55296 && cp <= 56319 && body[i + 6] === "\\" && body[i + 7] === "u") {
779
+ const lowHex = body.slice(i + 8, i + 12);
780
+ const low = /^[0-9a-fA-F]{4}$/.test(lowHex) ? Number.parseInt(lowHex, 16) : -1;
781
+ if (low >= 56320 && low <= 57343) return { cp: 65536 + (cp - 55296 << 10) + (low - 56320), next: i + 12 };
782
+ }
783
+ return { cp, next: i + 6 };
744
784
  }
745
785
  var META = new Set("()[]{}*+?|^$.".split(""));
746
786
  function literalCodePoints(frag) {
@@ -752,6 +792,7 @@ function literalCodePoints(frag) {
752
792
  const e = frag[i + 1];
753
793
  if (e === void 0) return null;
754
794
  if (!(e in CLASS_ESCAPES) && /\w/.test(e)) return null;
795
+ if (e === "0" && frag[i + 2] !== void 0 && frag[i + 2] >= "0" && frag[i + 2] <= "9") return null;
755
796
  out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
756
797
  i += 2;
757
798
  continue;
@@ -792,14 +833,14 @@ function parseClassOperand(body) {
792
833
  if (cps && cps.length === 1) return { ranges: [[cps[0], cps[0]]], negated: false };
793
834
  return null;
794
835
  }
795
- function parseClassRanges(body) {
836
+ function parseClassRanges(body, unicode = false) {
796
837
  const ranges = [];
797
838
  let i = 0;
798
839
  const readAtom = () => {
799
840
  const ch2 = body[i];
800
841
  if (ch2 === void 0) return null;
801
842
  if (ch2 === "\\") {
802
- const uni = readUnicodeEscape(body, i);
843
+ const uni = readUnicodeEscape(body, i, unicode);
803
844
  if (uni) {
804
845
  i = uni.next;
805
846
  return { cp: uni.cp };
@@ -807,13 +848,15 @@ function parseClassRanges(body) {
807
848
  const e = body[i + 1];
808
849
  if (e === void 0) return null;
809
850
  i += 2;
851
+ if (e === "0" && body[i] !== void 0 && body[i] >= "0" && body[i] <= "9" || e >= "1" && e <= "9") return null;
810
852
  if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
811
853
  if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
812
854
  if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
813
855
  return { cp: e.codePointAt(0) };
814
856
  }
815
- i += ch2.length;
816
- return { cp: ch2.codePointAt(0) };
857
+ const cp = unicode ? body.codePointAt(i) : body.charCodeAt(i);
858
+ i += cp > 65535 ? 2 : 1;
859
+ return { cp };
817
860
  };
818
861
  while (i < body.length) {
819
862
  const lo = readAtom();
@@ -849,7 +892,7 @@ function rangesHaveNewline(ranges) {
849
892
  return ranges.some(([lo, hi]) => lo <= 10 && 10 <= hi);
850
893
  }
851
894
  var BAIL = /* @__PURE__ */ Symbol("regex-bail");
852
- function parseRegex(src) {
895
+ function parseRegex(src, unicode = false, sets = false) {
853
896
  let i = 0;
854
897
  const parseAlt = () => {
855
898
  const arms = [parseSeq()];
@@ -919,9 +962,11 @@ function parseRegex(src) {
919
962
  i++;
920
963
  return charNode(fromRange(123, 123), false);
921
964
  // a `{` with nothing to quantify is a literal brace
922
- default:
923
- i += ch2.length;
924
- return charNode(fromRange(ch2.codePointAt(0), ch2.codePointAt(0)), ch2 === "\n");
965
+ default: {
966
+ const cp = unicode ? src.codePointAt(i) : src.charCodeAt(i);
967
+ i += cp > 65535 ? 2 : 1;
968
+ return charNode(fromRange(cp, cp), ch2 === "\n");
969
+ }
925
970
  }
926
971
  };
927
972
  const parseGroup = () => {
@@ -954,6 +999,32 @@ function parseRegex(src) {
954
999
  let k = i + 1;
955
1000
  const negated = src[k] === "^";
956
1001
  if (negated) k++;
1002
+ if (sets) {
1003
+ let depth = 1;
1004
+ let nested = false;
1005
+ while (k < src.length && depth > 0) {
1006
+ const c = src[k];
1007
+ if (c === "\\") {
1008
+ if (src[k + 1] === "q") nested = true;
1009
+ k += 2;
1010
+ continue;
1011
+ }
1012
+ if (c === "[") {
1013
+ depth++;
1014
+ nested = true;
1015
+ } else if (c === "]") {
1016
+ depth--;
1017
+ if (depth === 0) break;
1018
+ } else if ((c === "-" || c === "&") && src[k + 1] === c) nested = true;
1019
+ k++;
1020
+ }
1021
+ if (src[k] !== "]") throw BAIL;
1022
+ if (nested) {
1023
+ i = k + 1;
1024
+ return charNode(any(), true);
1025
+ }
1026
+ k = i + 1 + (negated ? 1 : 0);
1027
+ }
957
1028
  let body = "";
958
1029
  while (k < src.length && src[k] !== "]") {
959
1030
  if (src[k] === "\\") {
@@ -966,7 +1037,7 @@ function parseRegex(src) {
966
1037
  }
967
1038
  if (src[k] !== "]") throw BAIL;
968
1039
  i = k + 1;
969
- const ranges = parseClassRanges(body);
1040
+ const ranges = parseClassRanges(body, unicode);
970
1041
  if (negated) return charNode(any(), !ranges || !rangesHaveNewline(ranges));
971
1042
  if (!ranges) return charNode(any(), true);
972
1043
  return charNode(rangesToSet(ranges), rangesHaveNewline(ranges));
@@ -974,9 +1045,20 @@ function parseRegex(src) {
974
1045
  const parseEscape = () => {
975
1046
  const e = src[i + 1];
976
1047
  if (e === void 0) throw BAIL;
977
- if (e === "u" && /^[0-9a-fA-F]{4}$/.test(src.slice(i + 2, i + 6))) {
978
- const cp = Number.parseInt(src.slice(i + 2, i + 6), 16);
979
- i += 6;
1048
+ const uni = readUnicodeEscape(src, i, unicode);
1049
+ if (uni !== null) {
1050
+ i = uni.next;
1051
+ return charNode(fromRange(uni.cp, uni.cp), uni.cp === 10);
1052
+ }
1053
+ if (e === "u" && src[i + 2] === "{") {
1054
+ const close = src.indexOf("}", i + 3);
1055
+ const hex = close < 0 ? "" : src.slice(i + 3, close);
1056
+ if (!unicode || !/^[0-9a-fA-F]{1,6}$/.test(hex)) {
1057
+ i += 2;
1058
+ return ANY;
1059
+ }
1060
+ const cp = Number.parseInt(hex, 16);
1061
+ i = close + 1;
980
1062
  return charNode(fromRange(cp, cp), cp === 10);
981
1063
  }
982
1064
  if (e === "x" && /^[0-9a-fA-F]{2}$/.test(src.slice(i + 2, i + 4))) {
@@ -984,6 +1066,16 @@ function parseRegex(src) {
984
1066
  i += 4;
985
1067
  return charNode(fromRange(cp, cp), cp === 10);
986
1068
  }
1069
+ if (e === "c") {
1070
+ const x = src[i + 2];
1071
+ if (x !== void 0 && /^[A-Za-z]$/.test(x)) {
1072
+ const cp = x.charCodeAt(0) % 32;
1073
+ i += 3;
1074
+ return charNode(fromRange(cp, cp), cp === 10);
1075
+ }
1076
+ i += 2;
1077
+ return ANY;
1078
+ }
987
1079
  i += 2;
988
1080
  switch (e) {
989
1081
  case "d":
@@ -1011,8 +1103,16 @@ function parseRegex(src) {
1011
1103
  return charNode(fromRange(12, 12), false);
1012
1104
  case "v":
1013
1105
  return charNode(fromRange(11, 11), false);
1106
+ // `\0` then a digit is a legacy octal escape (`\012` is a newline), not NUL.
1014
1107
  case "0":
1015
- return charNode(fromRange(0, 0), false);
1108
+ return src[i] !== void 0 && src[i] >= "0" && src[i] <= "9" ? ANY : charNode(fromRange(0, 0), false);
1109
+ // A property escape (`\p{…}`/`\P{…}`) matches one character of a class this
1110
+ // analyzer does not enumerate; `\k<name>` is a backreference, which may match empty.
1111
+ case "p":
1112
+ case "P":
1113
+ return charNode(any(), true);
1114
+ case "k":
1115
+ return ANY;
1016
1116
  default:
1017
1117
  if (e >= "1" && e <= "9") return ANY;
1018
1118
  return charNode(fromRange(e.codePointAt(0), e.codePointAt(0)), e === "\n");
@@ -1086,10 +1186,10 @@ function regexCanMatchEmpty(source) {
1086
1186
  return true;
1087
1187
  }
1088
1188
  }
1089
- function firstSetFromRegex(source) {
1189
+ function firstSetFromRegex(source, flags = "") {
1090
1190
  let ast;
1091
1191
  try {
1092
- ast = parseRegex(source);
1192
+ ast = parseRegex(source, flags.includes("u") || flags.includes("v"), flags.includes("v"));
1093
1193
  } catch {
1094
1194
  return { firstSet: any(), canMatchNewline: true };
1095
1195
  }
@@ -1138,8 +1238,18 @@ function shortScanner(source, flags) {
1138
1238
  return minOne && end === pos ? null : end;
1139
1239
  };
1140
1240
  }
1241
+ function coversNonAscii(ranges) {
1242
+ let next = 128;
1243
+ for (const r of [...ranges].sort((a, b) => a.lo - b.lo)) {
1244
+ if (r.lo > next) return false;
1245
+ if (r.hi >= next) next = r.hi + 1;
1246
+ if (next > 65535) return true;
1247
+ }
1248
+ return false;
1249
+ }
1141
1250
  function asciiCaseFold(fs) {
1142
1251
  if (fs.kind !== "ranges") return fs;
1252
+ if (fs.ranges.some((r) => r.hi >= 128) && !coversNonAscii(fs.ranges)) return any();
1143
1253
  const ranges = fs.ranges.map((r) => ({ lo: r.lo, hi: r.hi }));
1144
1254
  const add = (lo, hi) => {
1145
1255
  if (lo <= hi) ranges.push({ lo, hi });
@@ -1164,7 +1274,7 @@ function regex(pattern, flags = "") {
1164
1274
  const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
1165
1275
  const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
1166
1276
  const scan = shortScanner(source, resolvedFlags);
1167
- const raw = firstSetFromRegex(source);
1277
+ const raw = firstSetFromRegex(source, resolvedFlags);
1168
1278
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
1169
1279
  const canMatchNewline = raw.canMatchNewline;
1170
1280
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
@@ -2668,9 +2778,7 @@ function firstSetSentinel(fs) {
2668
2778
  parse(input, pos) {
2669
2779
  const code = pos < input.length ? input.codePointAt(pos) : void 0;
2670
2780
  if (code !== void 0) {
2671
- for (const r of ranges) {
2672
- if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
2673
- }
2781
+ if (rangesHaveLead(ranges, code)) return { ok: true, value: null, span: { start: pos, end: pos } };
2674
2782
  }
2675
2783
  return { ok: false, expected: [], span: { start: pos, end: pos } };
2676
2784
  }
@@ -3346,6 +3454,9 @@ function inFirstSet(code, fs) {
3346
3454
  if (fs.kind === "any") return true;
3347
3455
  if (fs.kind === "empty") return false;
3348
3456
  for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
3457
+ if (code <= 65535) return false;
3458
+ const high = 55296 + (code - 65536 >> 10);
3459
+ for (const r of fs.ranges) if (high >= r.lo && high <= r.hi) return true;
3349
3460
  return false;
3350
3461
  }
3351
3462
  function areDisjoint(sets) {
@@ -6127,7 +6238,7 @@ function decodeClassSpec(spec) {
6127
6238
  function resolveClass(spec) {
6128
6239
  const ascii = new Uint8Array(128);
6129
6240
  const hi = [];
6130
- for (const { lo, hi: up } of decodeClassSpec(spec)) {
6241
+ for (const { lo, hi: up } of leadRanges(decodeClassSpec(spec))) {
6131
6242
  if (lo < 128) for (let c = lo; c <= Math.min(up, 127); c++) ascii[c] = 1;
6132
6243
  if (up >= 128) hi.push(Math.max(lo, 128), up);
6133
6244
  }
@@ -9227,6 +9338,7 @@ function parseSeqParts(source) {
9227
9338
  cp2 = uni.cp;
9228
9339
  i = uni.next;
9229
9340
  } else if (e === void 0) return null;
9341
+ else if (e >= "0" && e <= "9" && (e !== "0" || source[i + 2] !== void 0 && source[i + 2] >= "0" && source[i + 2] <= "9")) return null;
9230
9342
  else if (e in CLASS_ESCAPES) {
9231
9343
  cp2 = CLASS_ESCAPES[e];
9232
9344
  i += 2;
@@ -9776,7 +9888,7 @@ function parseScanShapeCore(source) {
9776
9888
  return null;
9777
9889
  }
9778
9890
  function scanShapeFromRegex(source, flags) {
9779
- if (/[msu]/.test(flags)) return null;
9891
+ if (/[msuv]/.test(flags)) return null;
9780
9892
  if (/i/.test(flags)) return caseFoldShape(source);
9781
9893
  return parseScanShape(source);
9782
9894
  }
@@ -10381,7 +10493,7 @@ function triviaLeadRanges(tri, trivia2) {
10381
10493
  const fs = trivia2[tri]?._meta.firstSet;
10382
10494
  if (fs === void 0) return void 0;
10383
10495
  if (fs.kind === "empty") return [];
10384
- return fs.kind === "ranges" && fs.ranges !== void 0 ? fs.ranges : void 0;
10496
+ return fs.kind === "ranges" && fs.ranges !== void 0 ? leadRanges(fs.ranges) : void 0;
10385
10497
  }
10386
10498
 
10387
10499
  // src/table/scalar-terminal.ts
@@ -10911,7 +11023,7 @@ if(ctx._errors!==undefined&&ctx._errors.length!==${t}er)ctx._errors.length=${t}e
10911
11023
  if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,undefined,undefined,${t}lg,${t}rt)`;
10912
11024
  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)}`;
10913
11025
  }
10914
- function emitTerm(callee, dst, t, l, skip) {
11026
+ function emitTerm(callee, dst, t, l, skip, miss) {
10915
11027
  const fast = `const ${t}v=${callee}(input,cur,ctx)
10916
11028
  if(${t}v===FAIL)return FAIL
10917
11029
  ${dst}=${t}v
@@ -10929,7 +11041,12 @@ if(${t}v===FAIL)return FAIL
10929
11041
  ${dst}=${t}v
10930
11042
  if(EC.e>${t}s)cur=EC.e
10931
11043
  else{rollbackScannedTriviaAt(ctx,${t}tl,${t}stl,${t}lg,${t}slg,${t}rt,${t}srt)}`;
10932
- if (l.tri !== TRI_UNKNOWN) return scanned;
11044
+ if (l.tri !== TRI_UNKNOWN) return miss === void 0 ? scanned : `const ${t}c=input.charCodeAt(cur)
11045
+ if(${miss(`${t}c`)}){
11046
+ ${fast}
11047
+ }else{
11048
+ ${scanned}
11049
+ }`;
10933
11050
  return `if(ctx.trivia===undefined){
10934
11051
  ${fast}
10935
11052
  }else{
@@ -10985,7 +11102,7 @@ function rebuildPools(cc, fx, disp, plan) {
10985
11102
  })
10986
11103
  };
10987
11104
  }
10988
- function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select) {
11105
+ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select, scanSinkNeutral = false) {
10989
11106
  const { code, k, fx, disp, dsp, triviaLabelled } = t;
10990
11107
  const swapLegal = !cfg.trackLines;
10991
11108
  const hostCst = cfg.hostCst;
@@ -11061,7 +11178,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, se
11061
11178
  const op = code[ip];
11062
11179
  sinkBits.set(
11063
11180
  ip,
11064
- op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC2 && (op === OP_REP || op === OP_REPV) ? 2 : 0)
11181
+ op === OP_SCAN || !scanSinkNeutral && op === OP_LEX_PROGRAM && t.lexPrograms[code[ip + 1]].scan !== void 0 ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC2 && (op === OP_REP || op === OP_REPV) ? 2 : 0)
11065
11182
  );
11066
11183
  }
11067
11184
  const sinkKids = [];
@@ -11234,6 +11351,12 @@ return 1
11234
11351
  return `if(${gateMissTest(child)}){${miss}}
11235
11352
  `;
11236
11353
  }
11354
+ function triviaMiss(ki) {
11355
+ const leads = triviaLeadRanges(ki, t.trivia);
11356
+ if (leads === void 0 || leads.length > 16) return void 0;
11357
+ if (leads.length === 0) return (c) => `${c}<55296`;
11358
+ return (c) => `${c}<55296&&!(${leads.map((r) => r.lo === r.hi ? `${c}===${r.lo}` : `(${c}>=${r.lo}&&${c}<=${r.hi})`).join("||")})`;
11359
+ }
11237
11360
  function skipFor(l) {
11238
11361
  if (l.tri < 0) return "_skipTrivia";
11239
11362
  const ki = l.tri;
@@ -11244,8 +11367,13 @@ return 1
11244
11367
  const nm = `_sk${skipPool.size}`;
11245
11368
  skipPool.set(key, nm);
11246
11369
  if (!hasScan) {
11247
- skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return skipDeferredTrivia(input,cur,ctx)}` : `function ${nm}(input,cur,ctx){
11248
- if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
11370
+ const miss = triviaMiss(ki);
11371
+ const pre = miss === void 0 ? "" : `const c=input.charCodeAt(cur)
11372
+ if(${miss("c")})return cur
11373
+ `;
11374
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){${pre === "" ? "" : `
11375
+ ${pre}`}return skipDeferredTrivia(input,cur,ctx)}` : `function ${nm}(input,cur,ctx){
11376
+ ${pre}if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
11249
11377
  return advanceTrivia(input,cur,ctx)}`);
11250
11378
  return nm;
11251
11379
  }
@@ -11829,7 +11957,7 @@ return v
11829
11957
  );
11830
11958
  } else {
11831
11959
  const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
11832
- parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L)));
11960
+ parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L), L.tri >= 0 ? triviaMiss(L.tri) : void 0));
11833
11961
  }
11834
11962
  names.push(vn);
11835
11963
  }
@@ -13008,6 +13136,15 @@ function skipDeferredTrivia(input, cur, ctx) {
13008
13136
  if (plain) remember(cur, scan, ctx, input, triviaP);
13009
13137
  return scan;
13010
13138
  }
13139
+ function triviaLeadTable(triviaP) {
13140
+ const fs = triviaP._meta.firstSet;
13141
+ if (fs.kind === "any") return null;
13142
+ const table = new Uint8Array(128);
13143
+ if (fs.kind === "ranges") {
13144
+ for (const r of fs.ranges) for (let c = Math.max(0, r.lo); c <= Math.min(127, r.hi); c++) table[c] = 1;
13145
+ }
13146
+ return table;
13147
+ }
13011
13148
  function clearRunEnd(input, cur, ctx, triviaP, plain) {
13012
13149
  const rootKinds = ctx._rootTriviaKindIndex;
13013
13150
  const spec = triviaP?._meta.labeledTriviaSpec;
@@ -13681,7 +13818,23 @@ function assemble(t, prog, cfg) {
13681
13818
  }
13682
13819
  return out;
13683
13820
  }
13821
+ const LEAD_TABLES = trivia2.map((tp) => tp === void 0 ? null : triviaLeadTable(tp));
13822
+ let LEAD_OF;
13823
+ let LEAD_TABLE = null;
13824
+ function cannotStartTrivia(input, cur, triviaP) {
13825
+ if (triviaP !== LEAD_OF) {
13826
+ LEAD_OF = triviaP;
13827
+ const slot = trivia2.indexOf(triviaP);
13828
+ LEAD_TABLE = slot >= 0 ? LEAD_TABLES[slot] : triviaLeadTable(triviaP);
13829
+ }
13830
+ const table = LEAD_TABLE;
13831
+ if (table === null) return false;
13832
+ const c = input.charCodeAt(cur);
13833
+ return c < 128 && table[c] === 0;
13834
+ }
13684
13835
  function skipTrivia(input, cur, ctx) {
13836
+ const t2 = ctx.trivia;
13837
+ if (t2 !== void 0 && cannotStartTrivia(input, cur, t2)) return cur;
13685
13838
  const s = SCAN;
13686
13839
  if (s !== null && ctx._triviaLog === void 0 && !(ctx.captureTrivia === true && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0))) {
13687
13840
  return s(input, cur);
@@ -13696,7 +13849,8 @@ function assemble(t, prog, cfg) {
13696
13849
  const frames = [];
13697
13850
  let depth = 0;
13698
13851
  function nextTerm(child, input, cur, ctx) {
13699
- if (ctx.trivia === void 0) {
13852
+ const t2 = ctx.trivia;
13853
+ if (t2 === void 0 || cannotStartTrivia(input, cur, t2)) {
13700
13854
  const v2 = child(input, cur, ctx);
13701
13855
  if (v2 === FAIL) return -1;
13702
13856
  TERMV = v2;
@@ -13725,7 +13879,8 @@ function assemble(t, prog, cfg) {
13725
13879
  return cur;
13726
13880
  }
13727
13881
  function nextTermBuffered(child, input, cur, ctx) {
13728
- if (ctx.trivia === void 0) {
13882
+ const t2 = ctx.trivia;
13883
+ if (t2 === void 0 || cannotStartTrivia(input, cur, t2)) {
13729
13884
  const v2 = child(input, cur, ctx);
13730
13885
  if (v2 === FAIL) return -1;
13731
13886
  TERMV = v2;
@@ -14527,6 +14682,7 @@ function assemble(t, prog, cfg) {
14527
14682
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
14528
14683
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
14529
14684
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? triviaScan[ki] : null;
14685
+ const scopeLead = ki < 0 ? null : LEAD_TABLES[ki];
14530
14686
  const child = link(code[ip + 2]);
14531
14687
  const scopePiece = code[ip] === OP_SCOPE_CAP ? (input, pos, ctx) => {
14532
14688
  const saved = ctx.trivia;
@@ -14534,6 +14690,9 @@ function assemble(t, prog, cfg) {
14534
14690
  const savedScan = SCAN;
14535
14691
  const savedCap = ctx.captureTrivia;
14536
14692
  SCAN = scanFor;
14693
+ const savedLeadOf = LEAD_OF, savedLead = LEAD_TABLE;
14694
+ LEAD_OF = scopeTrivia;
14695
+ LEAD_TABLE = scopeLead;
14537
14696
  ctx.trivia = scopeTrivia;
14538
14697
  ctx.triviaKindLabels = scopeLabels;
14539
14698
  ctx.captureTrivia = true;
@@ -14542,18 +14701,25 @@ function assemble(t, prog, cfg) {
14542
14701
  ctx.trivia = saved;
14543
14702
  ctx.triviaKindLabels = savedLabels;
14544
14703
  SCAN = savedScan;
14704
+ LEAD_OF = savedLeadOf;
14705
+ LEAD_TABLE = savedLead;
14545
14706
  return v;
14546
14707
  } : (input, pos, ctx) => {
14547
14708
  const saved = ctx.trivia;
14548
14709
  const savedLabels = ctx.triviaKindLabels;
14549
14710
  const savedScan = SCAN;
14550
14711
  SCAN = scanFor;
14712
+ const savedLeadOf = LEAD_OF, savedLead = LEAD_TABLE;
14713
+ LEAD_OF = scopeTrivia;
14714
+ LEAD_TABLE = scopeLead;
14551
14715
  ctx.trivia = scopeTrivia;
14552
14716
  ctx.triviaKindLabels = scopeLabels;
14553
14717
  const v = child(input, pos, ctx);
14554
14718
  ctx.trivia = saved;
14555
14719
  ctx.triviaKindLabels = savedLabels;
14556
14720
  SCAN = savedScan;
14721
+ LEAD_OF = savedLeadOf;
14722
+ LEAD_TABLE = savedLead;
14557
14723
  return v;
14558
14724
  };
14559
14725
  return scopeRootPolicy(scopePiece, code[ip] === OP_SCOPE_PLAIN ? 0 : code[ip + 3]);
@@ -18589,8 +18755,8 @@ function compileRuleMap(ruleMap, opts = {}) {
18589
18755
  const roots = assemblyExtraIps(artifact);
18590
18756
  let siteBytes, fixed;
18591
18757
  try {
18592
- siteBytes = emitAssemblySource(table, artifact, cfg, roots, true).siteBytes;
18593
- fixed = emitAssemblySource(table, artifact, cfg, roots, true, /* @__PURE__ */ new Set()).source.length;
18758
+ siteBytes = emitAssemblySource(table, artifact, cfg, roots, true, void 0, true).siteBytes;
18759
+ fixed = emitAssemblySource(table, artifact, cfg, roots, true, /* @__PURE__ */ new Set(), true).source.length;
18594
18760
  } catch (e) {
18595
18761
  if (e instanceof Unemittable) return { ...none, refusal: e.construct };
18596
18762
  throw e;
@@ -18606,7 +18772,7 @@ function compileRuleMap(ruleMap, opts = {}) {
18606
18772
  refusal: `a site within its ${Math.floor(ceiling)} B selection ceiling (the prelude alone is ${fixed} B)`
18607
18773
  };
18608
18774
  }
18609
- const bytes2 = emitAssemblySource(table, artifact, cfg, roots, true, sites).source.length;
18775
+ const bytes2 = emitAssemblySource(table, artifact, cfg, roots, true, sites, true).source.length;
18610
18776
  if (bytes2 <= ceiling) return { sites, bytes: Math.ceil(bytes2 * SUPERCOMPILE_GROWTH) };
18611
18777
  target *= Math.min(ceiling / bytes2, 0.99);
18612
18778
  }
@@ -19248,7 +19414,7 @@ function fieldOptionsSrc(def) {
19248
19414
  }
19249
19415
 
19250
19416
  // src/version.ts
19251
- var PARSEMAN_VERSION = "0.58.2";
19417
+ var PARSEMAN_VERSION = "0.58.3";
19252
19418
 
19253
19419
  // src/compiler/compile-linkable-table.ts
19254
19420
  function isLocal(rule) {