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
@@ -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);
@@ -806,11 +840,17 @@ function shorthandRanges(ch2) {
806
840
  if (ch2 === "s") return SPACE_RANGES;
807
841
  return [[48, 57], [65, 90], [97, 122], [95, 95]];
808
842
  }
809
- function readUnicodeEscape(body, i) {
843
+ function readUnicodeEscape(body, i, unicode = false) {
810
844
  if (body[i] !== "\\" || body[i + 1] !== "u") return null;
811
845
  const hex = body.slice(i + 2, i + 6);
812
846
  if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
813
- return { cp: Number.parseInt(hex, 16), next: i + 6 };
847
+ const cp = Number.parseInt(hex, 16);
848
+ if (unicode && cp >= 55296 && cp <= 56319 && body[i + 6] === "\\" && body[i + 7] === "u") {
849
+ const lowHex = body.slice(i + 8, i + 12);
850
+ const low = /^[0-9a-fA-F]{4}$/.test(lowHex) ? Number.parseInt(lowHex, 16) : -1;
851
+ if (low >= 56320 && low <= 57343) return { cp: 65536 + (cp - 55296 << 10) + (low - 56320), next: i + 12 };
852
+ }
853
+ return { cp, next: i + 6 };
814
854
  }
815
855
  var META = new Set("()[]{}*+?|^$.".split(""));
816
856
  function literalCodePoints(frag) {
@@ -822,6 +862,7 @@ function literalCodePoints(frag) {
822
862
  const e = frag[i + 1];
823
863
  if (e === void 0) return null;
824
864
  if (!(e in CLASS_ESCAPES) && /\w/.test(e)) return null;
865
+ if (e === "0" && frag[i + 2] !== void 0 && frag[i + 2] >= "0" && frag[i + 2] <= "9") return null;
825
866
  out.push(e in CLASS_ESCAPES ? CLASS_ESCAPES[e] : e.codePointAt(0));
826
867
  i += 2;
827
868
  continue;
@@ -862,14 +903,14 @@ function parseClassOperand(body) {
862
903
  if (cps && cps.length === 1) return { ranges: [[cps[0], cps[0]]], negated: false };
863
904
  return null;
864
905
  }
865
- function parseClassRanges(body) {
906
+ function parseClassRanges(body, unicode = false) {
866
907
  const ranges = [];
867
908
  let i = 0;
868
909
  const readAtom = () => {
869
910
  const ch2 = body[i];
870
911
  if (ch2 === void 0) return null;
871
912
  if (ch2 === "\\") {
872
- const uni = readUnicodeEscape(body, i);
913
+ const uni = readUnicodeEscape(body, i, unicode);
873
914
  if (uni) {
874
915
  i = uni.next;
875
916
  return { cp: uni.cp };
@@ -877,13 +918,15 @@ function parseClassRanges(body) {
877
918
  const e = body[i + 1];
878
919
  if (e === void 0) return null;
879
920
  i += 2;
921
+ if (e === "0" && body[i] !== void 0 && body[i] >= "0" && body[i] <= "9" || e >= "1" && e <= "9") return null;
880
922
  if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
881
923
  if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
882
924
  if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
883
925
  return { cp: e.codePointAt(0) };
884
926
  }
885
- i += ch2.length;
886
- return { cp: ch2.codePointAt(0) };
927
+ const cp = unicode ? body.codePointAt(i) : body.charCodeAt(i);
928
+ i += cp > 65535 ? 2 : 1;
929
+ return { cp };
887
930
  };
888
931
  while (i < body.length) {
889
932
  const lo = readAtom();
@@ -1586,9 +1629,7 @@ function firstSetSentinel(fs) {
1586
1629
  parse(input, pos) {
1587
1630
  const code = pos < input.length ? input.codePointAt(pos) : void 0;
1588
1631
  if (code !== void 0) {
1589
- for (const r of ranges) {
1590
- if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
1591
- }
1632
+ if (rangesHaveLead(ranges, code)) return { ok: true, value: null, span: { start: pos, end: pos } };
1592
1633
  }
1593
1634
  return { ok: false, expected: [], span: { start: pos, end: pos } };
1594
1635
  }
@@ -2673,6 +2714,9 @@ function inFirstSet(code, fs) {
2673
2714
  if (fs.kind === "any") return true;
2674
2715
  if (fs.kind === "empty") return false;
2675
2716
  for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
2717
+ if (code <= 65535) return false;
2718
+ const high = 55296 + (code - 65536 >> 10);
2719
+ for (const r of fs.ranges) if (high >= r.lo && high <= r.hi) return true;
2676
2720
  return false;
2677
2721
  }
2678
2722
  function areDisjoint(sets) {
@@ -3016,7 +3060,7 @@ function rangesHaveNewline(ranges) {
3016
3060
  return ranges.some(([lo, hi]) => lo <= 10 && 10 <= hi);
3017
3061
  }
3018
3062
  var BAIL = /* @__PURE__ */ Symbol("regex-bail");
3019
- function parseRegex(src) {
3063
+ function parseRegex(src, unicode = false, sets = false) {
3020
3064
  let i = 0;
3021
3065
  const parseAlt = () => {
3022
3066
  const arms = [parseSeq()];
@@ -3086,9 +3130,11 @@ function parseRegex(src) {
3086
3130
  i++;
3087
3131
  return charNode(fromRange(123, 123), false);
3088
3132
  // a `{` with nothing to quantify is a literal brace
3089
- default:
3090
- i += ch2.length;
3091
- return charNode(fromRange(ch2.codePointAt(0), ch2.codePointAt(0)), ch2 === "\n");
3133
+ default: {
3134
+ const cp = unicode ? src.codePointAt(i) : src.charCodeAt(i);
3135
+ i += cp > 65535 ? 2 : 1;
3136
+ return charNode(fromRange(cp, cp), ch2 === "\n");
3137
+ }
3092
3138
  }
3093
3139
  };
3094
3140
  const parseGroup = () => {
@@ -3121,6 +3167,32 @@ function parseRegex(src) {
3121
3167
  let k = i + 1;
3122
3168
  const negated = src[k] === "^";
3123
3169
  if (negated) k++;
3170
+ if (sets) {
3171
+ let depth = 1;
3172
+ let nested = false;
3173
+ while (k < src.length && depth > 0) {
3174
+ const c = src[k];
3175
+ if (c === "\\") {
3176
+ if (src[k + 1] === "q") nested = true;
3177
+ k += 2;
3178
+ continue;
3179
+ }
3180
+ if (c === "[") {
3181
+ depth++;
3182
+ nested = true;
3183
+ } else if (c === "]") {
3184
+ depth--;
3185
+ if (depth === 0) break;
3186
+ } else if ((c === "-" || c === "&") && src[k + 1] === c) nested = true;
3187
+ k++;
3188
+ }
3189
+ if (src[k] !== "]") throw BAIL;
3190
+ if (nested) {
3191
+ i = k + 1;
3192
+ return charNode(any(), true);
3193
+ }
3194
+ k = i + 1 + (negated ? 1 : 0);
3195
+ }
3124
3196
  let body = "";
3125
3197
  while (k < src.length && src[k] !== "]") {
3126
3198
  if (src[k] === "\\") {
@@ -3133,7 +3205,7 @@ function parseRegex(src) {
3133
3205
  }
3134
3206
  if (src[k] !== "]") throw BAIL;
3135
3207
  i = k + 1;
3136
- const ranges = parseClassRanges(body);
3208
+ const ranges = parseClassRanges(body, unicode);
3137
3209
  if (negated) return charNode(any(), !ranges || !rangesHaveNewline(ranges));
3138
3210
  if (!ranges) return charNode(any(), true);
3139
3211
  return charNode(rangesToSet(ranges), rangesHaveNewline(ranges));
@@ -3141,9 +3213,20 @@ function parseRegex(src) {
3141
3213
  const parseEscape = () => {
3142
3214
  const e = src[i + 1];
3143
3215
  if (e === void 0) throw BAIL;
3144
- if (e === "u" && /^[0-9a-fA-F]{4}$/.test(src.slice(i + 2, i + 6))) {
3145
- const cp = Number.parseInt(src.slice(i + 2, i + 6), 16);
3146
- i += 6;
3216
+ const uni = readUnicodeEscape(src, i, unicode);
3217
+ if (uni !== null) {
3218
+ i = uni.next;
3219
+ return charNode(fromRange(uni.cp, uni.cp), uni.cp === 10);
3220
+ }
3221
+ if (e === "u" && src[i + 2] === "{") {
3222
+ const close = src.indexOf("}", i + 3);
3223
+ const hex = close < 0 ? "" : src.slice(i + 3, close);
3224
+ if (!unicode || !/^[0-9a-fA-F]{1,6}$/.test(hex)) {
3225
+ i += 2;
3226
+ return ANY;
3227
+ }
3228
+ const cp = Number.parseInt(hex, 16);
3229
+ i = close + 1;
3147
3230
  return charNode(fromRange(cp, cp), cp === 10);
3148
3231
  }
3149
3232
  if (e === "x" && /^[0-9a-fA-F]{2}$/.test(src.slice(i + 2, i + 4))) {
@@ -3151,6 +3234,16 @@ function parseRegex(src) {
3151
3234
  i += 4;
3152
3235
  return charNode(fromRange(cp, cp), cp === 10);
3153
3236
  }
3237
+ if (e === "c") {
3238
+ const x = src[i + 2];
3239
+ if (x !== void 0 && /^[A-Za-z]$/.test(x)) {
3240
+ const cp = x.charCodeAt(0) % 32;
3241
+ i += 3;
3242
+ return charNode(fromRange(cp, cp), cp === 10);
3243
+ }
3244
+ i += 2;
3245
+ return ANY;
3246
+ }
3154
3247
  i += 2;
3155
3248
  switch (e) {
3156
3249
  case "d":
@@ -3178,8 +3271,16 @@ function parseRegex(src) {
3178
3271
  return charNode(fromRange(12, 12), false);
3179
3272
  case "v":
3180
3273
  return charNode(fromRange(11, 11), false);
3274
+ // `\0` then a digit is a legacy octal escape (`\012` is a newline), not NUL.
3181
3275
  case "0":
3182
- return charNode(fromRange(0, 0), false);
3276
+ return src[i] !== void 0 && src[i] >= "0" && src[i] <= "9" ? ANY : charNode(fromRange(0, 0), false);
3277
+ // A property escape (`\p{…}`/`\P{…}`) matches one character of a class this
3278
+ // analyzer does not enumerate; `\k<name>` is a backreference, which may match empty.
3279
+ case "p":
3280
+ case "P":
3281
+ return charNode(any(), true);
3282
+ case "k":
3283
+ return ANY;
3183
3284
  default:
3184
3285
  if (e >= "1" && e <= "9") return ANY;
3185
3286
  return charNode(fromRange(e.codePointAt(0), e.codePointAt(0)), e === "\n");
@@ -3253,10 +3354,10 @@ function regexCanMatchEmpty(source) {
3253
3354
  return true;
3254
3355
  }
3255
3356
  }
3256
- function firstSetFromRegex(source) {
3357
+ function firstSetFromRegex(source, flags = "") {
3257
3358
  let ast;
3258
3359
  try {
3259
- ast = parseRegex(source);
3360
+ ast = parseRegex(source, flags.includes("u") || flags.includes("v"), flags.includes("v"));
3260
3361
  } catch {
3261
3362
  return { firstSet: any(), canMatchNewline: true };
3262
3363
  }
@@ -3305,8 +3406,18 @@ function shortScanner(source, flags) {
3305
3406
  return minOne && end === pos ? null : end;
3306
3407
  };
3307
3408
  }
3409
+ function coversNonAscii(ranges) {
3410
+ let next = 128;
3411
+ for (const r of [...ranges].sort((a, b) => a.lo - b.lo)) {
3412
+ if (r.lo > next) return false;
3413
+ if (r.hi >= next) next = r.hi + 1;
3414
+ if (next > 65535) return true;
3415
+ }
3416
+ return false;
3417
+ }
3308
3418
  function asciiCaseFold(fs) {
3309
3419
  if (fs.kind !== "ranges") return fs;
3420
+ if (fs.ranges.some((r) => r.hi >= 128) && !coversNonAscii(fs.ranges)) return any();
3310
3421
  const ranges = fs.ranges.map((r) => ({ lo: r.lo, hi: r.hi }));
3311
3422
  const add = (lo, hi) => {
3312
3423
  if (lo <= hi) ranges.push({ lo, hi });
@@ -3331,7 +3442,7 @@ function regex(pattern, flags = "") {
3331
3442
  const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
3332
3443
  const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
3333
3444
  const scan = shortScanner(source, resolvedFlags);
3334
- const raw = firstSetFromRegex(source);
3445
+ const raw = firstSetFromRegex(source, resolvedFlags);
3335
3446
  const firstSet2 = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
3336
3447
  const canMatchNewline = raw.canMatchNewline;
3337
3448
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
@@ -4113,7 +4224,7 @@ function decodeClassSpec(spec) {
4113
4224
  function resolveClass(spec) {
4114
4225
  const ascii = new Uint8Array(128);
4115
4226
  const hi = [];
4116
- for (const { lo, hi: up } of decodeClassSpec(spec)) {
4227
+ for (const { lo, hi: up } of leadRanges(decodeClassSpec(spec))) {
4117
4228
  if (lo < 128) for (let c = lo; c <= Math.min(up, 127); c++) ascii[c] = 1;
4118
4229
  if (up >= 128) hi.push(Math.max(lo, 128), up);
4119
4230
  }
@@ -5386,6 +5497,15 @@ function skipDeferredTrivia(input, cur, ctx) {
5386
5497
  if (plain) remember(cur, scan, ctx, input, triviaP);
5387
5498
  return scan;
5388
5499
  }
5500
+ function triviaLeadTable(triviaP) {
5501
+ const fs = triviaP._meta.firstSet;
5502
+ if (fs.kind === "any") return null;
5503
+ const table = new Uint8Array(128);
5504
+ if (fs.kind === "ranges") {
5505
+ for (const r of fs.ranges) for (let c = Math.max(0, r.lo); c <= Math.min(127, r.hi); c++) table[c] = 1;
5506
+ }
5507
+ return table;
5508
+ }
5389
5509
  function clearRunEnd(input, cur, ctx, triviaP, plain) {
5390
5510
  const rootKinds = ctx._rootTriviaKindIndex;
5391
5511
  const spec = triviaP?._meta.labeledTriviaSpec;
@@ -5737,6 +5857,7 @@ function parseSeqParts(source) {
5737
5857
  cp2 = uni.cp;
5738
5858
  i = uni.next;
5739
5859
  } else if (e === void 0) return null;
5860
+ else if (e >= "0" && e <= "9" && (e !== "0" || source[i + 2] !== void 0 && source[i + 2] >= "0" && source[i + 2] <= "9")) return null;
5740
5861
  else if (e in CLASS_ESCAPES) {
5741
5862
  cp2 = CLASS_ESCAPES[e];
5742
5863
  i += 2;
@@ -6286,7 +6407,7 @@ function parseScanShapeCore(source) {
6286
6407
  return null;
6287
6408
  }
6288
6409
  function scanShapeFromRegex(source, flags) {
6289
- if (/[msu]/.test(flags)) return null;
6410
+ if (/[msuv]/.test(flags)) return null;
6290
6411
  if (/i/.test(flags)) return caseFoldShape(source);
6291
6412
  return parseScanShape(source);
6292
6413
  }
@@ -6891,7 +7012,7 @@ function triviaLeadRanges(tri, trivia2) {
6891
7012
  const fs = trivia2[tri]?._meta.firstSet;
6892
7013
  if (fs === void 0) return void 0;
6893
7014
  if (fs.kind === "empty") return [];
6894
- return fs.kind === "ranges" && fs.ranges !== void 0 ? fs.ranges : void 0;
7015
+ return fs.kind === "ranges" && fs.ranges !== void 0 ? leadRanges(fs.ranges) : void 0;
6895
7016
  }
6896
7017
 
6897
7018
  // src/table/scalar-terminal.ts
@@ -7421,7 +7542,7 @@ if(ctx._errors!==undefined&&ctx._errors.length!==${t}er)ctx._errors.length=${t}e
7421
7542
  if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,undefined,undefined,${t}lg,${t}rt)`;
7422
7543
  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)}`;
7423
7544
  }
7424
- function emitTerm(callee, dst, t, l, skip) {
7545
+ function emitTerm(callee, dst, t, l, skip, miss) {
7425
7546
  const fast = `const ${t}v=${callee}(input,cur,ctx)
7426
7547
  if(${t}v===FAIL)return FAIL
7427
7548
  ${dst}=${t}v
@@ -7439,7 +7560,12 @@ if(${t}v===FAIL)return FAIL
7439
7560
  ${dst}=${t}v
7440
7561
  if(EC.e>${t}s)cur=EC.e
7441
7562
  else{rollbackScannedTriviaAt(ctx,${t}tl,${t}stl,${t}lg,${t}slg,${t}rt,${t}srt)}`;
7442
- if (l.tri !== TRI_UNKNOWN) return scanned;
7563
+ if (l.tri !== TRI_UNKNOWN) return miss === void 0 ? scanned : `const ${t}c=input.charCodeAt(cur)
7564
+ if(${miss(`${t}c`)}){
7565
+ ${fast}
7566
+ }else{
7567
+ ${scanned}
7568
+ }`;
7443
7569
  return `if(ctx.trivia===undefined){
7444
7570
  ${fast}
7445
7571
  }else{
@@ -7495,7 +7621,7 @@ function rebuildPools(cc, fx, disp, plan) {
7495
7621
  })
7496
7622
  };
7497
7623
  }
7498
- function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select) {
7624
+ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, select, scanSinkNeutral = false) {
7499
7625
  const { code, k, fx, disp, dsp, triviaLabelled } = t;
7500
7626
  const swapLegal = !cfg.trackLines;
7501
7627
  const hostCst = cfg.hostCst;
@@ -7571,7 +7697,7 @@ function emitAssemblySource(t, prog, cfg, extraIps = [], staticBuild = false, se
7571
7697
  const op = code[ip];
7572
7698
  sinkBits.set(
7573
7699
  ip,
7574
- op === OP_SCAN ? 3 : (op === OP_FIELD ? 1 : 0) | (op === OP_EXPECT || REC && (op === OP_REP || op === OP_REPV) ? 2 : 0)
7700
+ 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 || REC && (op === OP_REP || op === OP_REPV) ? 2 : 0)
7575
7701
  );
7576
7702
  }
7577
7703
  const sinkKids = [];
@@ -7744,6 +7870,12 @@ return 1
7744
7870
  return `if(${gateMissTest(child)}){${miss}}
7745
7871
  `;
7746
7872
  }
7873
+ function triviaMiss(ki) {
7874
+ const leads = triviaLeadRanges(ki, t.trivia);
7875
+ if (leads === void 0 || leads.length > 16) return void 0;
7876
+ if (leads.length === 0) return (c) => `${c}<55296`;
7877
+ return (c) => `${c}<55296&&!(${leads.map((r) => r.lo === r.hi ? `${c}===${r.lo}` : `(${c}>=${r.lo}&&${c}<=${r.hi})`).join("||")})`;
7878
+ }
7747
7879
  function skipFor(l) {
7748
7880
  if (l.tri < 0) return "_skipTrivia";
7749
7881
  const ki = l.tri;
@@ -7754,8 +7886,13 @@ return 1
7754
7886
  const nm = `_sk${skipPool.size}`;
7755
7887
  skipPool.set(key, nm);
7756
7888
  if (!hasScan) {
7757
- skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){return skipDeferredTrivia(input,cur,ctx)}` : `function ${nm}(input,cur,ctx){
7758
- if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
7889
+ const miss = triviaMiss(ki);
7890
+ const pre = miss === void 0 ? "" : `const c=input.charCodeAt(cur)
7891
+ if(${miss("c")})return cur
7892
+ `;
7893
+ skipDefs.push(l.buf ? `function ${nm}(input,cur,ctx){${pre === "" ? "" : `
7894
+ ${pre}`}return skipDeferredTrivia(input,cur,ctx)}` : `function ${nm}(input,cur,ctx){
7895
+ ${pre}if(needsDeferredTriviaCommit(ctx))return skipDeferredTrivia(input,cur,ctx)
7759
7896
  return advanceTrivia(input,cur,ctx)}`);
7760
7897
  return nm;
7761
7898
  }
@@ -8339,7 +8476,7 @@ return v
8339
8476
  );
8340
8477
  } else {
8341
8478
  const callee = leadingTriviaFieldAt(code, k, childIp) ? `(LEAD.at=cur,${kids[i]})` : kids[i];
8342
- parts.push(holdsGap(code, k, base, n, i, nullable2) ? emitHoldTerm(callee, vn, tmp(), L, skipFor(L)) : emitTerm(callee, vn, tmp(), L, skipFor(L)));
8479
+ 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));
8343
8480
  }
8344
8481
  names.push(vn);
8345
8482
  }
@@ -9708,7 +9845,23 @@ function assemble(t, prog, cfg) {
9708
9845
  }
9709
9846
  return out;
9710
9847
  }
9848
+ const LEAD_TABLES = trivia2.map((tp) => tp === void 0 ? null : triviaLeadTable(tp));
9849
+ let LEAD_OF;
9850
+ let LEAD_TABLE = null;
9851
+ function cannotStartTrivia(input, cur, triviaP) {
9852
+ if (triviaP !== LEAD_OF) {
9853
+ LEAD_OF = triviaP;
9854
+ const slot = trivia2.indexOf(triviaP);
9855
+ LEAD_TABLE = slot >= 0 ? LEAD_TABLES[slot] : triviaLeadTable(triviaP);
9856
+ }
9857
+ const table = LEAD_TABLE;
9858
+ if (table === null) return false;
9859
+ const c = input.charCodeAt(cur);
9860
+ return c < 128 && table[c] === 0;
9861
+ }
9711
9862
  function skipTrivia(input, cur, ctx) {
9863
+ const t2 = ctx.trivia;
9864
+ if (t2 !== void 0 && cannotStartTrivia(input, cur, t2)) return cur;
9712
9865
  const s = SCAN;
9713
9866
  if (s !== null && ctx._triviaLog === void 0 && !(ctx.captureTrivia === true && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0))) {
9714
9867
  return s(input, cur);
@@ -9723,7 +9876,8 @@ function assemble(t, prog, cfg) {
9723
9876
  const frames = [];
9724
9877
  let depth = 0;
9725
9878
  function nextTerm(child, input, cur, ctx) {
9726
- if (ctx.trivia === void 0) {
9879
+ const t2 = ctx.trivia;
9880
+ if (t2 === void 0 || cannotStartTrivia(input, cur, t2)) {
9727
9881
  const v2 = child(input, cur, ctx);
9728
9882
  if (v2 === FAIL) return -1;
9729
9883
  TERMV = v2;
@@ -9752,7 +9906,8 @@ function assemble(t, prog, cfg) {
9752
9906
  return cur;
9753
9907
  }
9754
9908
  function nextTermBuffered(child, input, cur, ctx) {
9755
- if (ctx.trivia === void 0) {
9909
+ const t2 = ctx.trivia;
9910
+ if (t2 === void 0 || cannotStartTrivia(input, cur, t2)) {
9756
9911
  const v2 = child(input, cur, ctx);
9757
9912
  if (v2 === FAIL) return -1;
9758
9913
  TERMV = v2;
@@ -10554,6 +10709,7 @@ function assemble(t, prog, cfg) {
10554
10709
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
10555
10710
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
10556
10711
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? triviaScan[ki] : null;
10712
+ const scopeLead = ki < 0 ? null : LEAD_TABLES[ki];
10557
10713
  const child = link(code[ip + 2]);
10558
10714
  const scopePiece = code[ip] === OP_SCOPE_CAP ? (input, pos, ctx) => {
10559
10715
  const saved = ctx.trivia;
@@ -10561,6 +10717,9 @@ function assemble(t, prog, cfg) {
10561
10717
  const savedScan = SCAN;
10562
10718
  const savedCap = ctx.captureTrivia;
10563
10719
  SCAN = scanFor;
10720
+ const savedLeadOf = LEAD_OF, savedLead = LEAD_TABLE;
10721
+ LEAD_OF = scopeTrivia;
10722
+ LEAD_TABLE = scopeLead;
10564
10723
  ctx.trivia = scopeTrivia;
10565
10724
  ctx.triviaKindLabels = scopeLabels;
10566
10725
  ctx.captureTrivia = true;
@@ -10569,18 +10728,25 @@ function assemble(t, prog, cfg) {
10569
10728
  ctx.trivia = saved;
10570
10729
  ctx.triviaKindLabels = savedLabels;
10571
10730
  SCAN = savedScan;
10731
+ LEAD_OF = savedLeadOf;
10732
+ LEAD_TABLE = savedLead;
10572
10733
  return v;
10573
10734
  } : (input, pos, ctx) => {
10574
10735
  const saved = ctx.trivia;
10575
10736
  const savedLabels = ctx.triviaKindLabels;
10576
10737
  const savedScan = SCAN;
10577
10738
  SCAN = scanFor;
10739
+ const savedLeadOf = LEAD_OF, savedLead = LEAD_TABLE;
10740
+ LEAD_OF = scopeTrivia;
10741
+ LEAD_TABLE = scopeLead;
10578
10742
  ctx.trivia = scopeTrivia;
10579
10743
  ctx.triviaKindLabels = scopeLabels;
10580
10744
  const v = child(input, pos, ctx);
10581
10745
  ctx.trivia = saved;
10582
10746
  ctx.triviaKindLabels = savedLabels;
10583
10747
  SCAN = savedScan;
10748
+ LEAD_OF = savedLeadOf;
10749
+ LEAD_TABLE = savedLead;
10584
10750
  return v;
10585
10751
  };
10586
10752
  return scopeRootPolicy(scopePiece, code[ip] === OP_SCOPE_PLAIN ? 0 : code[ip + 3]);
@@ -17282,8 +17448,8 @@ function compileRuleMap(ruleMap, opts = {}) {
17282
17448
  const roots = assemblyExtraIps(artifact);
17283
17449
  let siteBytes, fixed;
17284
17450
  try {
17285
- siteBytes = emitAssemblySource(table, artifact, cfg, roots, true).siteBytes;
17286
- fixed = emitAssemblySource(table, artifact, cfg, roots, true, /* @__PURE__ */ new Set()).source.length;
17451
+ siteBytes = emitAssemblySource(table, artifact, cfg, roots, true, void 0, true).siteBytes;
17452
+ fixed = emitAssemblySource(table, artifact, cfg, roots, true, /* @__PURE__ */ new Set(), true).source.length;
17287
17453
  } catch (e) {
17288
17454
  if (e instanceof Unemittable) return { ...none, refusal: e.construct };
17289
17455
  throw e;
@@ -17299,7 +17465,7 @@ function compileRuleMap(ruleMap, opts = {}) {
17299
17465
  refusal: `a site within its ${Math.floor(ceiling)} B selection ceiling (the prelude alone is ${fixed} B)`
17300
17466
  };
17301
17467
  }
17302
- const bytes = emitAssemblySource(table, artifact, cfg, roots, true, sites).source.length;
17468
+ const bytes = emitAssemblySource(table, artifact, cfg, roots, true, sites, true).source.length;
17303
17469
  if (bytes <= ceiling) return { sites, bytes: Math.ceil(bytes * SUPERCOMPILE_GROWTH) };
17304
17470
  target *= Math.min(ceiling / bytes, 0.99);
17305
17471
  }