parseman 0.50.0 → 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 (55) hide show
  1. package/README.md +14 -10
  2. package/dist/analysis/diagnostics.js +455 -226
  3. package/dist/analysis/diagnostics.js.map +3 -3
  4. package/dist/cli/index.js +445 -191
  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 +446 -192
  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 +491 -306
  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/encode.d.ts.map +1 -1
  34. package/dist/table/index.js +331 -188
  35. package/dist/table/index.js.map +3 -3
  36. package/dist/types.d.ts +8 -0
  37. package/dist/types.d.ts.map +1 -1
  38. package/dist/version.d.ts +1 -1
  39. package/package.json +4 -2
  40. package/src/combinators/choice.ts +34 -1
  41. package/src/combinators/grammar.ts +39 -0
  42. package/src/combinators/keywords.ts +14 -3
  43. package/src/combinators/literal.ts +26 -0
  44. package/src/combinators/map.ts +60 -0
  45. package/src/combinators/ref.ts +26 -7
  46. package/src/combinators/regex.ts +23 -0
  47. package/src/combinators/repeat.ts +109 -16
  48. package/src/combinators/scalar.ts +30 -0
  49. package/src/combinators/sequence.ts +76 -161
  50. package/src/combinators/trivia-skip.ts +14 -1
  51. package/src/parse-context.ts +1 -0
  52. package/src/table/emit-assembly.ts +39 -16
  53. package/src/table/encode.ts +30 -10
  54. package/src/types.ts +8 -0
  55. package/src/version.ts +1 -1
@@ -270,9 +270,43 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
270
270
  }
271
271
  }
272
272
 
273
+ // src/combinators/scalar.ts
274
+ var SCALAR_TAG = /^(?:literal|regex|keywords|sequence|choice|many|oneOrMore|optional|transform|trivia|grammar|sepBy|lazy)$/;
275
+ function scalarOf(combinator) {
276
+ return combinator._parseScalar;
277
+ }
278
+ function scalarTree(parser2, seen) {
279
+ if (seen.has(parser2)) return true;
280
+ if (parser2._parseScalar === void 0) return false;
281
+ seen.add(parser2);
282
+ const def = parser2._def;
283
+ if (!SCALAR_TAG.test(def.tag)) return false;
284
+ if ("parsers" in def && !def.parsers.every((child) => scalarTree(child, seen))) return false;
285
+ if ("parser" in def && !scalarTree(def.parser, seen)) return false;
286
+ if ("separator" in def && !scalarTree(def.separator, seen)) return false;
287
+ return def.tag !== "lazy" || scalarTree(def.thunk(), seen);
288
+ }
289
+ function scalarRootOf(combinator) {
290
+ const scalar = combinator._parseScalar;
291
+ const def = combinator._def;
292
+ return scalar !== void 0 && def.tag === "grammar" && scalarTree(def.parser, /* @__PURE__ */ new Set()) ? scalar : void 0;
293
+ }
294
+
273
295
  // src/combinators/ref.ts
296
+ function withRuleTrivia(trivia2, ctx, run) {
297
+ const savedLabels = ctx.triviaKindLabels;
298
+ ctx.trivia = trivia2;
299
+ ctx.triviaKindLabels = trivia2._meta.triviaKindLabels;
300
+ try {
301
+ return run();
302
+ } finally {
303
+ ctx.trivia = void 0;
304
+ ctx.triviaKindLabels = savedLabels;
305
+ }
306
+ }
274
307
  function ref() {
275
308
  let resolved = null;
309
+ let resolvedScalar = null;
276
310
  let ownBoundary = false;
277
311
  const meta = {
278
312
  firstSet: any(),
@@ -289,25 +323,28 @@ function ref() {
289
323
  return resolved;
290
324
  }
291
325
  },
326
+ _parseScalar(input, pos, ctx) {
327
+ const scalar = resolvedScalar;
328
+ if (!scalar) throw new Error("ref<T>() used before .define() was called");
329
+ const gt = meta.grammarTrivia;
330
+ if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
331
+ return withRuleTrivia(gt, ctx, () => scalar(input, pos, ctx));
332
+ }
333
+ return scalar(input, pos, ctx);
334
+ },
292
335
  parse(input, pos, ctx) {
293
- if (!resolved) throw new Error("ref<T>() used before .define() was called");
336
+ const parser2 = resolved;
337
+ if (!parser2) throw new Error("ref<T>() used before .define() was called");
294
338
  const gt = meta.grammarTrivia;
295
339
  if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
296
- const savedLabels = ctx.triviaKindLabels;
297
- ctx.trivia = gt;
298
- ctx.triviaKindLabels = gt._meta.triviaKindLabels;
299
- try {
300
- return resolved.parse(input, pos, ctx);
301
- } finally {
302
- ctx.trivia = void 0;
303
- ctx.triviaKindLabels = savedLabels;
304
- }
340
+ return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
305
341
  }
306
- return resolved.parse(input, pos, ctx);
342
+ return parser2.parse(input, pos, ctx);
307
343
  },
308
344
  define(p) {
309
345
  if (resolved) throw new Error("ref<T>() already defined");
310
346
  resolved = p;
347
+ resolvedScalar = scalarOf(p);
311
348
  ownBoundary = hasOwnTriviaBoundary(p);
312
349
  meta.firstSet = p._meta.firstSet;
313
350
  meta.canMatchNewline = p._meta.canMatchNewline;
@@ -530,7 +567,7 @@ function pushCstLeaf(ctx, leaf2) {
530
567
  const annotated = leaf2 && typeof leaf2 === "object" && leaf2.span ? { ...leaf2, span: annotateSpanFromLineContext(leaf2.span, ctx) } : leaf2;
531
568
  pushCstChild(ctx, annotated, annotated);
532
569
  }
533
- function pushCstChild(ctx, built, rawEntry2) {
570
+ function pushCstChild(ctx, built, rawEntry) {
534
571
  const b = ctx._cstBuf;
535
572
  if (b) {
536
573
  if (b.rawOnly !== true) {
@@ -541,16 +578,16 @@ function pushCstChild(ctx, built, rawEntry2) {
541
578
  } else b.single = built;
542
579
  }
543
580
  if (b.noRaw === true) b.rawLen = (b.rawLen ?? 0) + 1;
544
- else if (b.raw) b.raw.push(rawEntry2);
581
+ else if (b.raw) b.raw.push(rawEntry);
545
582
  else if (b.rawSingle !== void 0) {
546
- b.raw = [b.rawSingle, rawEntry2];
583
+ b.raw = [b.rawSingle, rawEntry];
547
584
  b.rawSingle = void 0;
548
- } else b.rawSingle = rawEntry2;
585
+ } else b.rawSingle = rawEntry;
549
586
  return;
550
587
  }
551
588
  if (ctx._cstChildren) ctx._cstChildren.push(built);
552
589
  else if (ctx._cstLeaves) ctx._cstLeaves.push(built);
553
- if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry2);
590
+ if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry);
554
591
  }
555
592
  function cstRawLen(ctx) {
556
593
  const b = ctx._cstBuf;
@@ -693,6 +730,7 @@ function createParseContext() {
693
730
  _fe: void 0,
694
731
  _fx: void 0,
695
732
  _fc: void 0,
733
+ _sv: void 0,
696
734
  _probe: void 0,
697
735
  _cstChildren: void 0,
698
736
  _cstLeaves: void 0,
@@ -1530,6 +1568,24 @@ function parser(opts, root) {
1530
1568
  const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
1531
1569
  const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
1532
1570
  const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
1571
+ const rootScalar = scalarOf(root);
1572
+ const scalarEligible = opts.trackLines !== true && opts.recover !== true && !opaqueRootCapture && !forceCaptureTrivia && captureKinds === void 0;
1573
+ const parseScalar = scalarEligible ? (input, pos, ctx) => {
1574
+ const savedTrivia = ctx.trivia;
1575
+ const savedLabels = ctx.triviaKindLabels;
1576
+ if (clearTrivia) {
1577
+ ctx.trivia = void 0;
1578
+ ctx.triviaKindLabels = void 0;
1579
+ } else if (scopeTrivia !== void 0) {
1580
+ ctx.trivia = scopeTrivia;
1581
+ ctx.triviaKindLabels = scopeLabels;
1582
+ }
1583
+ const end = rootScalar(input, pos, ctx);
1584
+ ctx.trivia = savedTrivia;
1585
+ ctx.triviaKindLabels = savedLabels;
1586
+ return end;
1587
+ } : void 0;
1588
+ let publicScalar;
1533
1589
  const grammar = {
1534
1590
  _tag: "grammar",
1535
1591
  _meta: {
@@ -1553,7 +1609,20 @@ function parser(opts, root) {
1553
1609
  constructionTrackLines: trackLinesPolicy,
1554
1610
  ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
1555
1611
  },
1612
+ _parseScalar: parseScalar,
1556
1613
  parse(input, pos, _ctx) {
1614
+ if (pos === void 0 && _ctx === void 0) {
1615
+ publicScalar ??= scalarRootOf(grammar) ?? null;
1616
+ if (publicScalar) {
1617
+ const ctx2 = createParseContext();
1618
+ const end = publicScalar(input, 0, ctx2);
1619
+ if (end < 0) {
1620
+ const at = ~end;
1621
+ return { ok: false, expected: ctx2._fx ?? [], span: { start: at, end: at } };
1622
+ }
1623
+ return { ok: true, value: ctx2._sv, span: { start: 0, end } };
1624
+ }
1625
+ }
1557
1626
  if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
1558
1627
  const trackLines = trackLinesOf(_ctx);
1559
1628
  const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
@@ -2146,10 +2215,32 @@ function regex(pattern, flags = "") {
2146
2215
  const canMatchNewline = raw.canMatchNewline;
2147
2216
  const meta = { firstSet: firstSet2, canMatchNewline, isTrivia: false };
2148
2217
  const def = { tag: "regex", source, flags: resolvedFlags };
2218
+ const expected = directTerminalFailureExpected(def);
2219
+ const parseScalar = (input, pos, ctx) => {
2220
+ const scanEnd = scan?.(input, pos);
2221
+ if (scanEnd !== void 0) {
2222
+ if (scanEnd === null) {
2223
+ ctx._fx = expected;
2224
+ return ~pos;
2225
+ }
2226
+ ctx._sv = input.slice(pos, scanEnd);
2227
+ return scanEnd;
2228
+ }
2229
+ anchored.lastIndex = pos;
2230
+ const match = anchored.exec(input);
2231
+ if (match === null) {
2232
+ ctx._fx = expected;
2233
+ return ~pos;
2234
+ }
2235
+ ctx._sv = match[0];
2236
+ return pos + match[0].length;
2237
+ };
2149
2238
  return {
2150
2239
  _tag: "regex",
2151
2240
  _meta: meta,
2152
2241
  _def: def,
2242
+ _stickyRegex: anchored,
2243
+ _parseScalar: parseScalar,
2153
2244
  parse(input, pos, ctx) {
2154
2245
  const scanEnd = scan?.(input, pos);
2155
2246
  if (scanEnd !== void 0) {
@@ -2194,6 +2285,28 @@ function literal(value, opts = {}) {
2194
2285
  isTrivia: false
2195
2286
  };
2196
2287
  const canMatchNewline = meta.canMatchNewline;
2288
+ const parseScalar = !caseInsensitive && value.length === 1 ? (() => {
2289
+ const code = value.charCodeAt(0);
2290
+ return (input, pos, ctx) => {
2291
+ if (input.charCodeAt(pos) === code) {
2292
+ ctx._sv = value;
2293
+ return pos + 1;
2294
+ }
2295
+ ctx._fx = expected;
2296
+ return ~pos;
2297
+ };
2298
+ })() : (input, pos, ctx) => {
2299
+ const end = pos + value.length;
2300
+ if (end <= input.length) {
2301
+ const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
2302
+ if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
2303
+ ctx._sv = matchedValue;
2304
+ return end;
2305
+ }
2306
+ }
2307
+ ctx._fx = expected;
2308
+ return ~pos;
2309
+ };
2197
2310
  if (caseInsensitive) {
2198
2311
  const upper = value.toUpperCase();
2199
2312
  const lower = value.toLowerCase();
@@ -2234,6 +2347,7 @@ function literal(value, opts = {}) {
2234
2347
  _tag: "literal",
2235
2348
  _meta: meta,
2236
2349
  _def: { tag: "literal", value, caseInsensitive },
2350
+ _parseScalar: parseScalar,
2237
2351
  parse
2238
2352
  };
2239
2353
  }
@@ -2301,16 +2415,26 @@ function keywords(words, opts = {}) {
2301
2415
  caseInsensitive: opts.caseInsensitive ?? false,
2302
2416
  boundary: opts.boundary
2303
2417
  };
2418
+ const expected = directTerminalFailureExpected(def);
2419
+ const parseScalar = (input, pos, ctx) => {
2420
+ re.lastIndex = pos;
2421
+ const m = re.exec(input);
2422
+ if (m === null) {
2423
+ ctx._fx = expected;
2424
+ return ~pos;
2425
+ }
2426
+ ctx._sv = m[0];
2427
+ return pos + m[0].length;
2428
+ };
2304
2429
  return {
2305
2430
  _tag: "keywords",
2306
2431
  _meta: meta,
2307
2432
  _def: def,
2433
+ _parseScalar: parseScalar,
2308
2434
  parse(input, pos, ctx) {
2309
2435
  re.lastIndex = pos;
2310
2436
  const m = re.exec(input);
2311
- if (m === null || m.index !== pos) {
2312
- return failAt(ctx, directTerminalFailureExpected(def), pos);
2313
- }
2437
+ if (m === null) return failAt(ctx, directTerminalFailureExpected(def), pos);
2314
2438
  const value = m[0];
2315
2439
  const span = { start: pos, end: pos + value.length };
2316
2440
  if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
@@ -2341,6 +2465,9 @@ var fastScanner3;
2341
2465
  function needsDeferredTriviaCommit(ctx) {
2342
2466
  return ctx._triviaLog !== void 0 || ctx._rootTriviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
2343
2467
  }
2468
+ function needsTriviaRollback(ctx) {
2469
+ 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;
2470
+ }
2344
2471
  function saveTriviaMark(ctx) {
2345
2472
  const m = saveCstMark(ctx);
2346
2473
  return {
@@ -2452,7 +2579,8 @@ function advanceTrivia(input, cur, ctx) {
2452
2579
  const triviaP = ctx.trivia;
2453
2580
  if (!triviaP) return cur;
2454
2581
  if (!ctx.trackLines) {
2455
- const fast2 = fastTriviaScanner(triviaP);
2582
+ const classified = triviaP._meta.triviaScanner;
2583
+ const fast2 = classified === void 0 ? fastTriviaScanner(triviaP) : classified;
2456
2584
  if (fast2) return fast2(input, cur);
2457
2585
  if (ctx.triviaKindLabels) return skipWithLabels(input, cur, ctx);
2458
2586
  const tr2 = triviaP.parse(input, cur, createDetachedParseContext(ctx.trackLines, ctx.state));
@@ -3043,6 +3171,7 @@ function sequence(...parsers) {
3043
3171
  (adjacency ??= Array.from({ length: parsers.length }, () => null))[i] = a;
3044
3172
  }
3045
3173
  const hasAdjacency = adjacency !== null;
3174
+ const strictArity = !hasAdjacency && (parsers.length === 2 && !matchesEmpty(parsers[1]) || parsers.length === 3 && parsers.every((p) => !matchesEmpty(p))) ? parsers.length : 0;
3046
3175
  const meta = {
3047
3176
  // Union through the nullable prefix — a leading optional()/many() lets a later
3048
3177
  // term's first char start the sequence. Just `parsers[0]` under-approximates.
@@ -3051,165 +3180,96 @@ function sequence(...parsers) {
3051
3180
  isTrivia: false
3052
3181
  };
3053
3182
  const def = { tag: "sequence", parsers };
3054
- let followSentinels;
3055
- function parseTolerant(input, pos, ctx) {
3056
- followSentinels ??= parsers.map((_, i) => {
3057
- const fs = parsers.slice(i + 1).reduce(
3058
- (acc, p) => union(acc, firstSetOf(p)),
3059
- { kind: "empty" }
3060
- );
3061
- return firstSetSentinel(fs);
3062
- });
3063
- const values = def.valueUnused ? void 0 : [];
3183
+ const scalarParsers = parsers.map(scalarOf);
3184
+ const parseScalar = (input, pos, ctx) => {
3064
3185
  let cur = pos;
3065
- const inheritedSync = ctx._sync;
3066
- try {
3067
- for (let i = 0; i < parsers.length; i++) {
3068
- ctx._sync = followSentinels[i] ?? inheritedSync;
3069
- const adj = adjacency === null ? null : adjacency[i];
3070
- if (adj) {
3071
- if (!holdsAdjacency(input, cur, ctx, adj)) return adjacencyFail(cur, adj);
3072
- if (values !== void 0) values.push(null);
3073
- continue;
3074
- }
3075
- if (ctx.trivia && i > 0) {
3076
- const mTlog = cstTlLen(ctx);
3077
- const mLog = ctx._triviaLog?.length ?? 0;
3078
- const mRootLog = ctx._rootTriviaLog?.length ?? 0;
3079
- let scanEnd;
3080
- if (needsDeferredTriviaCommit(ctx)) {
3081
- scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3082
- } else {
3083
- scanEnd = advanceTrivia(input, cur, ctx);
3084
- }
3085
- const scanTlog = cstTlLen(ctx);
3086
- const scanLog = ctx._triviaLog?.length ?? 0;
3087
- const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
3088
- const result2 = parsers[i].parse(input, scanEnd, ctx);
3089
- if (!result2.ok) return result2;
3090
- if (result2.span.end > scanEnd) cur = result2.span.end;
3091
- else rollbackScannedTriviaAt(
3092
- ctx,
3093
- mTlog,
3094
- scanTlog,
3095
- mLog,
3096
- scanLog,
3097
- mRootLog,
3098
- scanRootLog
3099
- );
3100
- if (values !== void 0) values.push(result2.value);
3101
- continue;
3102
- }
3103
- const result = parsers[i].parse(input, cur, ctx);
3104
- if (!result.ok) return result;
3105
- if (values !== void 0) values.push(result.value);
3106
- cur = result.span.end;
3186
+ if (strictArity !== 0) {
3187
+ cur = scalarParsers[0](input, cur, ctx);
3188
+ if (cur < 0) return cur;
3189
+ const first = ctx._sv;
3190
+ if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
3191
+ cur = scalarParsers[1](input, cur, ctx);
3192
+ if (cur < 0) return cur;
3193
+ const second = ctx._sv;
3194
+ if (strictArity === 2) {
3195
+ ctx._sv = def.valueUnused ? void 0 : [first, second];
3196
+ return cur;
3107
3197
  }
3108
- } finally {
3109
- ctx._sync = inheritedSync;
3198
+ if (ctx.trivia) cur = advanceTrivia(input, cur, ctx);
3199
+ cur = scalarParsers[2](input, cur, ctx);
3200
+ if (cur < 0) return cur;
3201
+ ctx._sv = def.valueUnused ? void 0 : [first, second, ctx._sv];
3202
+ return cur;
3110
3203
  }
3111
- return {
3112
- ok: true,
3113
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
3114
- value: values ?? void 0,
3115
- span: { start: pos, end: cur }
3116
- };
3117
- }
3118
- function parseAdjacent(input, pos, ctx) {
3119
3204
  const values = def.valueUnused ? void 0 : [];
3120
- let cur = pos;
3121
- for (let i = 0; i < parsers.length; i++) {
3122
- const adj = adjacency[i];
3123
- if (adj) {
3124
- if (!holdsAdjacency(input, cur, ctx, adj)) return adjacencyFail(cur, adj);
3125
- if (values !== void 0) values.push(null);
3126
- continue;
3127
- }
3128
- if (ctx.trivia && i > 0) {
3129
- let scanEnd;
3130
- const mTlog = cstTlLen(ctx);
3131
- const mLog = ctx._triviaLog?.length ?? 0;
3132
- const mRootLog = ctx._rootTriviaLog?.length ?? 0;
3133
- if (needsDeferredTriviaCommit(ctx)) {
3134
- scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3135
- } else {
3136
- scanEnd = advanceTrivia(input, cur, ctx);
3137
- }
3138
- const scanTlog = cstTlLen(ctx);
3139
- const scanLog = ctx._triviaLog?.length ?? 0;
3140
- const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
3141
- const result2 = parsers[i].parse(input, scanEnd, ctx);
3142
- if (!result2.ok) return result2;
3143
- if (result2.span.end > scanEnd) cur = result2.span.end;
3144
- else rollbackScannedTriviaAt(
3145
- ctx,
3146
- mTlog,
3147
- scanTlog,
3148
- mLog,
3149
- scanLog,
3150
- mRootLog,
3151
- scanRootLog
3152
- );
3153
- if (values !== void 0) values.push(result2.value);
3154
- continue;
3155
- }
3156
- const result = parsers[i].parse(input, cur, ctx);
3157
- if (!result.ok) return result;
3158
- if (values !== void 0) values.push(result.value);
3159
- cur = result.span.end;
3160
- }
3161
- return {
3162
- ok: true,
3163
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
3164
- value: values ?? void 0,
3165
- span: { start: pos, end: cur }
3166
- };
3167
- }
3205
+ for (let i = 0; i < scalarParsers.length; i++) {
3206
+ let termPos = cur;
3207
+ if (i > 0 && ctx.trivia) termPos = advanceTrivia(input, cur, ctx);
3208
+ const end = scalarParsers[i](input, termPos, ctx);
3209
+ if (end < 0) return end;
3210
+ if (values !== void 0) values.push(ctx._sv);
3211
+ if (end > termPos || termPos === cur) cur = end;
3212
+ }
3213
+ ctx._sv = values;
3214
+ return cur;
3215
+ };
3216
+ let followSentinels;
3168
3217
  return {
3169
3218
  _tag: "sequence",
3170
3219
  _meta: meta,
3171
3220
  _def: def,
3221
+ _parseScalar: hasAdjacency ? void 0 : parseScalar,
3172
3222
  parse(input, pos, ctx) {
3173
- if (ctx._tolerant) return parseTolerant(input, pos, ctx);
3174
- if (hasAdjacency) return parseAdjacent(input, pos, ctx);
3223
+ const tolerant = ctx._tolerant === true;
3224
+ if (tolerant) {
3225
+ followSentinels ??= parsers.map((_, i) => firstSetSentinel(
3226
+ parsers.slice(i + 1).reduce(
3227
+ (set, parser2) => union(set, firstSetOf(parser2)),
3228
+ { kind: "empty" }
3229
+ )
3230
+ ));
3231
+ }
3232
+ const inheritedSync = ctx._sync;
3233
+ const deferredTrivia = needsDeferredTriviaCommit(ctx);
3175
3234
  const values = def.valueUnused ? void 0 : [];
3176
3235
  let cur = pos;
3177
- for (let i = 0; i < parsers.length; i++) {
3178
- if (ctx.trivia && i > 0) {
3179
- let scanEnd;
3180
- const mTlog = cstTlLen(ctx);
3181
- const mLog = ctx._triviaLog?.length ?? 0;
3182
- const mRootLog = ctx._rootTriviaLog?.length ?? 0;
3183
- if (needsDeferredTriviaCommit(ctx)) {
3184
- scanEnd = commitTriviaScan(scanTriviaCompact(input, cur, ctx));
3185
- } else {
3186
- scanEnd = advanceTrivia(input, cur, ctx);
3236
+ try {
3237
+ for (let i = 0; i < parsers.length; i++) {
3238
+ if (tolerant) ctx._sync = followSentinels[i] ?? inheritedSync;
3239
+ const assertion = adjacency?.[i];
3240
+ if (assertion) {
3241
+ if (!holdsAdjacency(input, cur, ctx, assertion)) return adjacencyFail(cur, assertion);
3242
+ if (values !== void 0) values.push(null);
3243
+ continue;
3187
3244
  }
3188
- const scanTlog = cstTlLen(ctx);
3189
- const scanLog = ctx._triviaLog?.length ?? 0;
3190
- const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
3191
- const result2 = parsers[i].parse(input, scanEnd, ctx);
3192
- if (!result2.ok) return result2;
3193
- if (result2.span.end > scanEnd) {
3194
- cur = result2.span.end;
3195
- } else {
3245
+ let termPos = cur;
3246
+ const markTlog = deferredTrivia ? cstTlLen(ctx) : 0;
3247
+ const markLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
3248
+ const markRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
3249
+ if (ctx.trivia && i > 0) {
3250
+ termPos = deferredTrivia ? commitTriviaScan(scanTriviaCompact(input, cur, ctx)) : advanceTrivia(input, cur, ctx);
3251
+ }
3252
+ const scanTlog = deferredTrivia ? cstTlLen(ctx) : 0;
3253
+ const scanLog = deferredTrivia ? ctx._triviaLog?.length ?? 0 : 0;
3254
+ const scanRootLog = deferredTrivia ? ctx._rootTriviaLog?.length ?? 0 : 0;
3255
+ const result = parsers[i].parse(input, termPos, ctx);
3256
+ if (!result.ok) return result;
3257
+ if (values !== void 0) values.push(result.value);
3258
+ if (result.span.end > termPos || termPos === cur) cur = result.span.end;
3259
+ else if (deferredTrivia) {
3196
3260
  rollbackScannedTriviaAt(
3197
3261
  ctx,
3198
- mTlog,
3262
+ markTlog,
3199
3263
  scanTlog,
3200
- mLog,
3264
+ markLog,
3201
3265
  scanLog,
3202
- mRootLog,
3266
+ markRootLog,
3203
3267
  scanRootLog
3204
3268
  );
3205
3269
  }
3206
- if (values !== void 0) values.push(result2.value);
3207
- continue;
3208
3270
  }
3209
- const result = parsers[i].parse(input, cur, ctx);
3210
- if (!result.ok) return result;
3211
- if (values !== void 0) values.push(result.value);
3212
- cur = result.span.end;
3271
+ } finally {
3272
+ if (tolerant) ctx._sync = inheritedSync;
3213
3273
  }
3214
3274
  return {
3215
3275
  ok: true,
@@ -3341,7 +3401,8 @@ function choice(...args) {
3341
3401
  disjoint
3342
3402
  };
3343
3403
  const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
3344
- const autoNot = !disjoint && !hasGates && (strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix") ? computeAutoNot(parsers) : parsers.map(() => null);
3404
+ const ordered = strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix";
3405
+ const autoNot = !disjoint && !hasGates && ordered ? computeAutoNot(parsers) : parsers.map(() => null);
3345
3406
  let greedyLitMap = null;
3346
3407
  let sortedParsers = null;
3347
3408
  const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
@@ -3355,6 +3416,37 @@ function choice(...args) {
3355
3416
  } else if (strategy?.tag === "literalsLongestFirst") {
3356
3417
  sortedParsers = strategy.sortedIndices.map((i) => parsers[i]);
3357
3418
  }
3419
+ const scalarParsers = parsers.map(scalarOf);
3420
+ const scalarEligible = !hasGates && parsers.every((p) => p._parseScalar !== void 0) && (disjoint || ordered);
3421
+ const scalarExpected = parsers.flatMap(deriveExpected);
3422
+ const parseScalar = (input, pos, ctx) => {
3423
+ if (disjoint) {
3424
+ const code = pos < input.length ? input.codePointAt(pos) : -1;
3425
+ let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
3426
+ if (idx < 0 && code >= 0) {
3427
+ for (let i = 0; i < parsers.length; i++) {
3428
+ if (inFirstSet(code, parsers[i]._meta.firstSet)) {
3429
+ idx = i;
3430
+ break;
3431
+ }
3432
+ }
3433
+ }
3434
+ if (idx >= 0) {
3435
+ const gate = gates[idx];
3436
+ if (!gate || gate(ctx.state)) return scalarParsers[idx](input, pos, ctx);
3437
+ ctx._fx = deriveExpected(parsers[idx]);
3438
+ return ~pos;
3439
+ }
3440
+ } else {
3441
+ for (let i = 0; i < scalarParsers.length; i++) {
3442
+ if (gates[i] && !gates[i](ctx.state)) continue;
3443
+ const end = scalarParsers[i](input, pos, ctx);
3444
+ if (end >= 0 && (!autoNot[i] || !autoNotFires(input, end, autoNot[i]))) return end;
3445
+ }
3446
+ }
3447
+ ctx._fx = scalarExpected;
3448
+ return ~pos;
3449
+ };
3358
3450
  return {
3359
3451
  _tag: "choice",
3360
3452
  _meta: meta,
@@ -3366,6 +3458,7 @@ function choice(...args) {
3366
3458
  strategy: strategy ?? { tag: "firstMatch" },
3367
3459
  autoNot
3368
3460
  },
3461
+ _parseScalar: scalarEligible ? parseScalar : void 0,
3369
3462
  parse(input, pos, ctx) {
3370
3463
  const expected = [];
3371
3464
  let expectedAt = pos;
@@ -3897,8 +3990,8 @@ function attempt(parser2) {
3897
3990
  }
3898
3991
 
3899
3992
  // src/combinators/repeat.ts
3900
- function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3901
- const mark = saveTriviaMark(ctx);
3993
+ function repItem(combinator, input, cur, ctx, guardable, mandatory, rollbackNeeded) {
3994
+ const mark = rollbackNeeded ? saveTriviaMark(ctx) : void 0;
3902
3995
  let pos = cur;
3903
3996
  if (ctx.trivia) {
3904
3997
  if (needsDeferredTriviaCommit(ctx)) {
@@ -3908,24 +4001,24 @@ function repItem(combinator, input, cur, ctx, guardable, mandatory) {
3908
4001
  }
3909
4002
  }
3910
4003
  if (pos >= input.length && !mandatory) {
3911
- rollbackTrivia(ctx, mark);
4004
+ if (mark !== void 0) rollbackTrivia(ctx, mark);
3912
4005
  return "stop";
3913
4006
  }
3914
4007
  if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
3915
- rollbackTrivia(ctx, mark);
4008
+ if (mark !== void 0) rollbackTrivia(ctx, mark);
3916
4009
  return "stop";
3917
4010
  }
3918
4011
  const result = combinator.parse(input, pos, ctx);
3919
4012
  if (!result.ok) {
3920
- rollbackTrivia(ctx, mark);
4013
+ if (mark !== void 0) rollbackTrivia(ctx, mark);
3921
4014
  if (result.committed) return { fail: result, failPos: pos };
3922
4015
  return { fail: result, failPos: pos };
3923
4016
  }
3924
4017
  if (result.span.end === pos && !mandatory) {
3925
- rollbackTrivia(ctx, mark);
4018
+ if (mark !== void 0) rollbackTrivia(ctx, mark);
3926
4019
  return "stop";
3927
4020
  }
3928
- return { value: result.value, end: result.span.end };
4021
+ return result;
3929
4022
  }
3930
4023
  function resolveBounds(what, opts) {
3931
4024
  const min = opts.min ?? 0;
@@ -3938,6 +4031,21 @@ function resolveBounds(what, opts) {
3938
4031
  if (max < min) bad(`max (${max}) is less than min (${min}) \u2014 the combinator could never succeed`);
3939
4032
  return { min, max };
3940
4033
  }
4034
+ function repeatScalarTail(combinator, child, input, cur, ctx, guardable, values, remaining) {
4035
+ while (cur < input.length && remaining > 0) {
4036
+ let itemPos = cur;
4037
+ if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
4038
+ if (itemPos >= input.length) break;
4039
+ if (guardable && !startsFirstSet(combinator, input, itemPos)) break;
4040
+ const end = child(input, itemPos, ctx);
4041
+ if (end <= itemPos) break;
4042
+ if (values !== void 0) values.push(ctx._sv);
4043
+ cur = end;
4044
+ remaining--;
4045
+ }
4046
+ ctx._sv = values;
4047
+ return cur;
4048
+ }
3941
4049
  function many(combinator, opts = {}) {
3942
4050
  const { min, max } = resolveBounds("many()", opts);
3943
4051
  if (min >= 1) return atLeast(combinator, min, max);
@@ -3949,17 +4057,21 @@ function many(combinator, opts = {}) {
3949
4057
  const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
3950
4058
  let expected;
3951
4059
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
4060
+ const scalarChild = scalarOf(combinator);
4061
+ const parseScalar = (input, pos, ctx) => repeatScalarTail(combinator, scalarChild, input, pos, ctx, guardable, def.valueUnused ? void 0 : [], max);
3952
4062
  return {
3953
4063
  _tag: "many",
3954
4064
  _meta: meta,
3955
4065
  _def: def,
4066
+ _parseScalar: parseScalar,
3956
4067
  parse(input, pos, ctx) {
3957
4068
  const values = def.valueUnused ? void 0 : [];
4069
+ const rollbackNeeded = needsTriviaRollback(ctx);
3958
4070
  let cur = pos;
3959
4071
  let count = 0;
3960
4072
  while (cur < input.length) {
3961
4073
  if (count >= max) break;
3962
- const item = repItem(combinator, input, cur, ctx, guardable, false);
4074
+ const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
3963
4075
  if (item === "stop") break;
3964
4076
  if ("fail" in item) {
3965
4077
  if (!item.fail.ok && item.fail.committed) return item.fail;
@@ -3976,7 +4088,7 @@ function many(combinator, opts = {}) {
3976
4088
  }
3977
4089
  if (values !== void 0) values.push(item.value);
3978
4090
  count++;
3979
- cur = item.end;
4091
+ cur = item.span.end;
3980
4092
  }
3981
4093
  return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
3982
4094
  }
@@ -3994,30 +4106,47 @@ function atLeast(combinator, min, max) {
3994
4106
  const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
3995
4107
  let expected;
3996
4108
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
4109
+ const scalarChild = scalarOf(combinator);
4110
+ const parseScalar = (input, pos, ctx) => {
4111
+ let cur = scalarChild(input, pos, ctx);
4112
+ if (cur < 0) return cur;
4113
+ const values = def.valueUnused ? void 0 : [ctx._sv];
4114
+ for (let count = 1; count < min; count++) {
4115
+ let itemPos = cur;
4116
+ if (ctx.trivia) itemPos = advanceTrivia(input, cur, ctx);
4117
+ const end = scalarChild(input, itemPos, ctx);
4118
+ if (end < 0) return ~cur;
4119
+ cur = end;
4120
+ if (values !== void 0) values.push(ctx._sv);
4121
+ }
4122
+ return repeatScalarTail(combinator, scalarChild, input, cur, ctx, guardable, values, max - min);
4123
+ };
3997
4124
  return {
3998
4125
  _tag: "oneOrMore",
3999
4126
  _meta: meta,
4000
4127
  _def: def,
4128
+ _parseScalar: parseScalar,
4001
4129
  parse(input, pos, ctx) {
4002
4130
  const first = combinator.parse(input, pos, ctx);
4003
4131
  if (!first.ok) return first;
4004
4132
  const values = def.valueUnused ? void 0 : [first.value];
4133
+ const rollbackNeeded = needsTriviaRollback(ctx);
4005
4134
  let cur = first.span.end;
4006
4135
  let count = 1;
4007
4136
  while (count < min) {
4008
- const item = repItem(combinator, input, cur, ctx, guardable, true);
4137
+ const item = repItem(combinator, input, cur, ctx, guardable, true, rollbackNeeded);
4009
4138
  if (item === "stop" || "fail" in item) {
4010
4139
  if (item !== "stop" && !item.fail.ok && item.fail.committed) return item.fail;
4011
4140
  expected ??= deriveExpected(combinator);
4012
4141
  return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
4013
4142
  }
4014
4143
  if (values !== void 0) values.push(item.value);
4015
- cur = item.end;
4144
+ cur = item.span.end;
4016
4145
  count++;
4017
4146
  }
4018
4147
  while (cur < input.length) {
4019
4148
  if (count >= max) break;
4020
- const item = repItem(combinator, input, cur, ctx, guardable, false);
4149
+ const item = repItem(combinator, input, cur, ctx, guardable, false, rollbackNeeded);
4021
4150
  if (item === "stop") break;
4022
4151
  if ("fail" in item) {
4023
4152
  if (!item.fail.ok && item.fail.committed) return item.fail;
@@ -4034,7 +4163,7 @@ function atLeast(combinator, min, max) {
4034
4163
  }
4035
4164
  if (values !== void 0) values.push(item.value);
4036
4165
  count++;
4037
- cur = item.end;
4166
+ cur = item.span.end;
4038
4167
  }
4039
4168
  return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
4040
4169
  }
@@ -4047,10 +4176,22 @@ function optional(combinator) {
4047
4176
  isTrivia: false
4048
4177
  };
4049
4178
  const firstSetSkippable = !matchesEmpty(combinator);
4179
+ const scalarChild = scalarOf(combinator);
4180
+ const parseScalar = (input, pos, ctx) => {
4181
+ if (firstSetSkippable && !startsFirstSet(combinator, input, pos)) {
4182
+ ctx._sv = null;
4183
+ return pos;
4184
+ }
4185
+ const end = scalarChild(input, pos, ctx);
4186
+ if (end >= 0) return end;
4187
+ ctx._sv = null;
4188
+ return pos;
4189
+ };
4050
4190
  return {
4051
4191
  _tag: "optional",
4052
4192
  _meta: meta,
4053
4193
  _def: { tag: "optional", parser: combinator },
4194
+ _parseScalar: parseScalar,
4054
4195
  parse(input, pos, ctx) {
4055
4196
  if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
4056
4197
  return { ok: true, value: null, span: { start: pos, end: pos } };
@@ -4084,6 +4225,43 @@ function sepBy(combinator, separatorArg, opts = {}) {
4084
4225
  expected ??= deriveExpected(combinator);
4085
4226
  return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: at, end: at } };
4086
4227
  };
4228
+ const scalarExpected = deriveExpected(combinator);
4229
+ const scalarChild = scalarOf(combinator);
4230
+ const scalarSeparator = scalarOf(separator);
4231
+ const parseScalar = (input, pos, ctx) => {
4232
+ let cur = scalarChild(input, pos, ctx);
4233
+ if (cur < 0) {
4234
+ if (min >= 1) {
4235
+ ctx._fx = scalarExpected.length > 0 ? scalarExpected : [combinator._tag];
4236
+ return ~pos;
4237
+ }
4238
+ ctx._sv = [];
4239
+ return pos;
4240
+ }
4241
+ const values = [ctx._sv];
4242
+ while (values.length < max && (cur < input.length || values.length < min)) {
4243
+ const beforeSeparator = cur;
4244
+ let separatorPos = cur;
4245
+ if (ctx.trivia) separatorPos = advanceTrivia(input, cur, ctx);
4246
+ const separatorEnd = scalarSeparator(input, separatorPos, ctx);
4247
+ if (separatorEnd < 0) break;
4248
+ let itemPos = separatorEnd;
4249
+ if (ctx.trivia) itemPos = advanceTrivia(input, itemPos, ctx);
4250
+ const itemEnd = scalarChild(input, itemPos, ctx);
4251
+ if (itemEnd < 0) {
4252
+ cur = trailing === "allow" ? separatorEnd : beforeSeparator;
4253
+ break;
4254
+ }
4255
+ values.push(ctx._sv);
4256
+ cur = itemEnd;
4257
+ }
4258
+ if (values.length < min) {
4259
+ ctx._fx = scalarExpected.length > 0 ? scalarExpected : [combinator._tag];
4260
+ return ~cur;
4261
+ }
4262
+ ctx._sv = values;
4263
+ return cur;
4264
+ };
4087
4265
  return {
4088
4266
  _tag: "sepBy",
4089
4267
  _meta: meta,
@@ -4099,6 +4277,7 @@ function sepBy(combinator, separatorArg, opts = {}) {
4099
4277
  // this option surface already; parity is held by test/parity, not by hope.
4100
4278
  ...keepSeparators ? { keepSeparators: true } : {}
4101
4279
  },
4280
+ _parseScalar: keepSeparators ? void 0 : parseScalar,
4102
4281
  parse(input, pos, ctx) {
4103
4282
  const first = combinator.parse(input, pos, ctx);
4104
4283
  const values = [];
@@ -4608,9 +4787,9 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
4608
4787
  const span = ctx.trackLines ? annotateSpanFromLineContext(r.span, ctx) : r.span;
4609
4788
  const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
4610
4789
  const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : (cstOutput || !build && project === void 0) && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState, tags) : projectChild(children, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, hostState, tags) : build(children, fields, span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, span, rawChildren, triviaLog, st, tags) : { _tag: "node", type: nodeType, span: ctx.trackLines ? { ...span } : { start: r.span.start, end: r.span.end }, state: st ?? null, children };
4611
- const rawEntry2 = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
4790
+ const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span };
4612
4791
  if (saved.buf !== void 0 || saved.ch !== void 0) {
4613
- pushCstChild(ctx, built, rawEntry2);
4792
+ pushCstChild(ctx, built, rawEntry);
4614
4793
  }
4615
4794
  return { ok: true, value: built, span };
4616
4795
  }
@@ -4618,11 +4797,54 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
4618
4797
  }
4619
4798
 
4620
4799
  // src/combinators/map.ts
4800
+ var JSON_STRING_BODY = String.raw`(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*`;
4621
4801
  function transform(combinator, fn) {
4802
+ const observesSpan = fn.length > 1;
4803
+ const sequenceDef = combinator._def.tag === "sequence" ? combinator._def : void 0;
4804
+ const terms = sequenceDef?.parsers;
4805
+ const inner = terms?.[1];
4806
+ 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;
4807
+ const child = scalarOf(combinator);
4808
+ const parseScalar = fused ? (() => {
4809
+ const body = inner._stickyRegex;
4810
+ const tuple = ['"', "", '"'];
4811
+ const expected = [JSON.stringify('"')];
4812
+ return (input, pos, ctx) => {
4813
+ if (ctx.trivia !== void 0) {
4814
+ const end2 = child(input, pos, ctx);
4815
+ if (end2 < 0) return end2;
4816
+ ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end: end2 }) : fn(ctx._sv);
4817
+ return end2;
4818
+ }
4819
+ if (input.charCodeAt(pos) !== 34) {
4820
+ ctx._fx = expected;
4821
+ return ~pos;
4822
+ }
4823
+ body.lastIndex = pos + 1;
4824
+ const match = body.exec(input);
4825
+ const close = pos + 1 + match[0].length;
4826
+ if (input.charCodeAt(close) !== 34) {
4827
+ ctx._fx = expected;
4828
+ return ~close;
4829
+ }
4830
+ tuple[1] = match[0];
4831
+ const end = close + 1;
4832
+ ctx._sv = observesSpan ? fn(tuple, { start: pos, end }) : fn(tuple);
4833
+ return end;
4834
+ };
4835
+ })() : /* @__PURE__ */ (() => {
4836
+ return (input, pos, ctx) => {
4837
+ const end = child(input, pos, ctx);
4838
+ if (end < 0) return end;
4839
+ ctx._sv = observesSpan ? fn(ctx._sv, { start: pos, end }) : fn(ctx._sv);
4840
+ return end;
4841
+ };
4842
+ })();
4622
4843
  return {
4623
4844
  _tag: "transform",
4624
4845
  _meta: combinator._meta,
4625
4846
  _def: { tag: "transform", parser: combinator, fn },
4847
+ _parseScalar: parseScalar,
4626
4848
  parse(input, pos, ctx) {
4627
4849
  const result = combinator.parse(input, pos, ctx);
4628
4850
  if (!result.ok) return result;
@@ -4637,9 +4859,11 @@ function trivia(combinator) {
4637
4859
  _meta: {
4638
4860
  ...combinator._meta,
4639
4861
  isTrivia: true,
4862
+ triviaScanner: fastTriviaScanner(combinator),
4640
4863
  ...kindLabels ? { triviaKindLabels: kindLabels } : {}
4641
4864
  },
4642
4865
  _def: { tag: "trivia", parser: combinator },
4866
+ _parseScalar: scalarOf(combinator),
4643
4867
  parse: combinator.parse.bind(combinator)
4644
4868
  };
4645
4869
  }
@@ -5113,108 +5337,6 @@ function evalRuleMapIR(ir) {
5113
5337
  return Object.entries(map);
5114
5338
  }
5115
5339
 
5116
- // src/table/ops.ts
5117
- var OP_LIT = 1;
5118
- var OP_RX = 2;
5119
- var OP_SEQ = 3;
5120
- var OP_SEQV = 4;
5121
- var OP_CHOICE = 5;
5122
- var OP_REP = 6;
5123
- var OP_REPV = 7;
5124
- var OP_OPT = 8;
5125
- var OP_XFORM = 9;
5126
- var OP_NODE = 10;
5127
- var OP_RULE = 11;
5128
- var OP_GATE = 12;
5129
- var OP_NOT = 13;
5130
- var OP_PEEK = 14;
5131
- var OP_LEAF = 15;
5132
- var OP_EMPTY = 16;
5133
- var OP_LIT_TRACK = 17;
5134
- var OP_RX_TRACK = 18;
5135
- var OP_NODE_TRACK = 19;
5136
- var OP_SCOPE = 20;
5137
- var OP_EXPECT = 21;
5138
- var OP_SEQX = 22;
5139
- var OP_SCAN = 23;
5140
- var OP_FIELD = 24;
5141
- var OP_LIT_CI = 27;
5142
- var OP_LIT_CI_TRACK = 28;
5143
- var OP_TOKEN = 29;
5144
- var OP_SCOPE_CAP = 30;
5145
- var OP_WITHCTX = 31;
5146
- var OP_GUARD = 32;
5147
- var OP_ADJ = 33;
5148
- var OP_GREEDY = 34;
5149
- var OP_REJECT = 35;
5150
- var OP_ARMGATE = 36;
5151
- var OP_LIVE = 37;
5152
- var OP_ATTEMPT = 38;
5153
- var OP_LABEL = 39;
5154
- var OP_COV = 40;
5155
- var OP_SCOPE_PLAIN = 41;
5156
- var OP_LEX_BODY = 42;
5157
- var OP_LEX_PROGRAM = 43;
5158
- var OP_DISPATCH = 25;
5159
- var OP_ROUTED = 26;
5160
- var OP_NAMES = {
5161
- [OP_LIT]: "LIT",
5162
- [OP_RX]: "RX",
5163
- [OP_SEQ]: "SEQ",
5164
- [OP_SEQV]: "SEQV",
5165
- [OP_CHOICE]: "CHOICE",
5166
- [OP_REP]: "REP",
5167
- [OP_REPV]: "REPV",
5168
- [OP_OPT]: "OPT",
5169
- [OP_XFORM]: "XFORM",
5170
- [OP_NODE]: "NODE",
5171
- [OP_RULE]: "RULE",
5172
- [OP_GATE]: "GATE",
5173
- [OP_NOT]: "NOT",
5174
- [OP_PEEK]: "PEEK",
5175
- [OP_LEAF]: "LEAF",
5176
- [OP_EMPTY]: "EMPTY",
5177
- [OP_LIT_TRACK]: "LIT_TRACK",
5178
- [OP_RX_TRACK]: "RX_TRACK",
5179
- [OP_NODE_TRACK]: "NODE_TRACK",
5180
- [OP_SCOPE]: "SCOPE",
5181
- [OP_EXPECT]: "EXPECT",
5182
- [OP_SEQX]: "SEQX",
5183
- [OP_SCAN]: "SCAN",
5184
- [OP_FIELD]: "FIELD",
5185
- [OP_LIT_CI]: "LIT_CI",
5186
- [OP_LIT_CI_TRACK]: "LIT_CI_TRACK",
5187
- [OP_DISPATCH]: "DISPATCH",
5188
- [OP_ROUTED]: "ROUTED",
5189
- [OP_TOKEN]: "TOKEN",
5190
- [OP_SCOPE_CAP]: "SCOPE_CAP",
5191
- [OP_WITHCTX]: "WITHCTX",
5192
- [OP_GUARD]: "GUARD",
5193
- [OP_ADJ]: "ADJ",
5194
- [OP_GREEDY]: "GREEDY",
5195
- [OP_REJECT]: "REJECT",
5196
- [OP_ARMGATE]: "ARMGATE",
5197
- [OP_LIVE]: "LIVE",
5198
- [OP_ATTEMPT]: "ATTEMPT",
5199
- [OP_LABEL]: "LABEL",
5200
- [OP_COV]: "COV",
5201
- [OP_SCOPE_PLAIN]: "SCOPE_PLAIN",
5202
- [OP_LEX_BODY]: "LEX_BODY",
5203
- [OP_LEX_PROGRAM]: "LEX_PROGRAM"
5204
- };
5205
-
5206
- // src/table/scan-shapes.ts
5207
- var META2 = new Set("()[]{}*+?|^$.".split(""));
5208
-
5209
- // src/table/assemble.ts
5210
- var EMIT_ENABLED = globalThis.process?.env?.PM_TABLE_EMIT !== "0";
5211
- var EMPTY_TL2 = Object.freeze([]);
5212
- var EMPTY_SENTS = Object.freeze([]);
5213
-
5214
- // src/analysis/duplication.ts
5215
- var WORD_RE_SRC = "-?[A-Za-z][A-Za-z0-9_-]*";
5216
- var WORDS_RE = new RegExp(`^${WORD_RE_SRC}(?:\\|${WORD_RE_SRC})*$`);
5217
-
5218
5340
  // src/compiler/linker.ts
5219
5341
  function normalizeCstCollapse(collapse) {
5220
5342
  if (collapse === true) return () => true;