parseman 0.35.0 → 0.37.0

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 (61) hide show
  1. package/README.md +34 -19
  2. package/dist/analysis/duplication.d.ts +421 -0
  3. package/dist/analysis/duplication.d.ts.map +1 -0
  4. package/dist/analysis/gating.d.ts +25 -0
  5. package/dist/analysis/gating.d.ts.map +1 -1
  6. package/dist/analysis/grammar.d.ts +12 -0
  7. package/dist/analysis/grammar.d.ts.map +1 -0
  8. package/dist/combinators/expect.d.ts +12 -0
  9. package/dist/combinators/expect.d.ts.map +1 -1
  10. package/dist/combinators/parser.d.ts +26 -0
  11. package/dist/combinators/parser.d.ts.map +1 -1
  12. package/dist/compiler/build-arity.d.ts +12 -0
  13. package/dist/compiler/build-arity.d.ts.map +1 -1
  14. package/dist/compiler/codegen.d.ts +43 -1
  15. package/dist/compiler/codegen.d.ts.map +1 -1
  16. package/dist/compiler/linker.d.ts +64 -7
  17. package/dist/compiler/linker.d.ts.map +1 -1
  18. package/dist/cst/host-mode.d.ts +43 -0
  19. package/dist/cst/host-mode.d.ts.map +1 -0
  20. package/dist/functional/doc.d.ts.map +1 -1
  21. package/dist/functional/run.d.ts.map +1 -1
  22. package/dist/index.cjs +1621 -55
  23. package/dist/index.cjs.map +4 -4
  24. package/dist/index.d.ts +6 -2
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +1621 -55
  27. package/dist/index.js.map +4 -4
  28. package/dist/language-service/index.cjs +37 -1
  29. package/dist/language-service/index.cjs.map +3 -3
  30. package/dist/language-service/index.js +37 -1
  31. package/dist/language-service/index.js.map +3 -3
  32. package/dist/oracle/corpus.d.ts +32 -0
  33. package/dist/oracle/corpus.d.ts.map +1 -0
  34. package/dist/oracle/digest.d.ts +21 -0
  35. package/dist/oracle/digest.d.ts.map +1 -0
  36. package/dist/oracle/identity.d.ts +117 -0
  37. package/dist/oracle/identity.d.ts.map +1 -0
  38. package/dist/oracle/index.cjs +423 -0
  39. package/dist/oracle/index.cjs.map +7 -0
  40. package/dist/oracle/index.d.ts +37 -0
  41. package/dist/oracle/index.d.ts.map +1 -0
  42. package/dist/oracle/index.js +400 -0
  43. package/dist/oracle/index.js.map +7 -0
  44. package/dist/plugin/index.cjs +1628 -62
  45. package/dist/plugin/index.cjs.map +4 -4
  46. package/dist/plugin/index.d.ts.map +1 -1
  47. package/dist/plugin/index.js +1628 -62
  48. package/dist/plugin/index.js.map +4 -4
  49. package/dist/run/index.cjs +23 -0
  50. package/dist/run/index.cjs.map +3 -3
  51. package/dist/run/index.js +23 -0
  52. package/dist/run/index.js.map +3 -3
  53. package/dist/spec/index.cjs +2977 -56
  54. package/dist/spec/index.cjs.map +4 -4
  55. package/dist/spec/index.js +2977 -56
  56. package/dist/spec/index.js.map +4 -4
  57. package/dist/spec/model.d.ts.map +1 -1
  58. package/dist/types.d.ts +7 -0
  59. package/dist/types.d.ts.map +1 -1
  60. package/dist/version.d.ts +1 -1
  61. package/package.json +10 -3
@@ -1,5 +1,2916 @@
1
+ // src/combinators/first-set.ts
2
+ function resolveNamedRef(p, resolve) {
3
+ if (resolve === void 0) return void 0;
4
+ const name = p._ruleName;
5
+ return name === void 0 ? void 0 : resolve(name);
6
+ }
7
+ function union(a, b) {
8
+ if (a.kind === "any" || b.kind === "any") return { kind: "any" };
9
+ if (a.kind === "empty") return b;
10
+ if (b.kind === "empty") return a;
11
+ return { kind: "ranges", ranges: mergeRanges([...a.ranges, ...b.ranges]) };
12
+ }
13
+ function intersects(a, b) {
14
+ if (a.kind === "any" || b.kind === "any") return true;
15
+ if (a.kind === "empty" || b.kind === "empty") return false;
16
+ for (const ra of a.ranges) {
17
+ for (const rb of b.ranges) {
18
+ if (ra.lo <= rb.hi && rb.lo <= ra.hi) return true;
19
+ }
20
+ }
21
+ return false;
22
+ }
23
+ function fromChar(code) {
24
+ return { kind: "ranges", ranges: [{ lo: code, hi: code }] };
25
+ }
26
+ function startsFirstSet(combinator, input, pos) {
27
+ const fs = combinator._meta.firstSet;
28
+ if (fs.kind === "any") return true;
29
+ if (fs.kind === "empty") return false;
30
+ const code = input.codePointAt(pos);
31
+ if (code === void 0) return false;
32
+ for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
33
+ return false;
34
+ }
35
+ function any() {
36
+ return { kind: "any" };
37
+ }
38
+ function empty() {
39
+ return { kind: "empty" };
40
+ }
41
+ function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve) {
42
+ if (seen.has(p)) return true;
43
+ seen.add(p);
44
+ const me = (c) => matchesEmpty(c, seen, resolve);
45
+ const d = p._def;
46
+ switch (d.tag) {
47
+ case "literal":
48
+ return d.value.length === 0;
49
+ case "keywords":
50
+ return false;
51
+ case "regex":
52
+ try {
53
+ const m = new RegExp(d.source).exec("");
54
+ return m != null && m[0] === "";
55
+ } catch {
56
+ return true;
57
+ }
58
+ case "many":
59
+ case "optional":
60
+ case "not":
61
+ case "peek":
62
+ return true;
63
+ // zero repetitions / absent / lookahead
64
+ // Default `sepBy` is `(item (sep item)*)?` — it MATCHES THE EMPTY STRING.
65
+ // Any `min >= 1` requires that many ITEMS, so it is nullable only when the
66
+ // item is. (Keying this off `min === 1` reported every `{ min: 2 }` list as
67
+ // nullable — safe, but wrong, and it put a bogus `nullable-prefix` note on
68
+ // the gating diagnostic for a list that can never match empty.)
69
+ case "sepBy":
70
+ return d.min >= 1 ? me(d.parser) : true;
71
+ case "oneOrMore":
72
+ return me(d.parser);
73
+ case "sequence":
74
+ return d.parsers.every(me);
75
+ case "choice":
76
+ return d.parsers.some(me);
77
+ case "transform":
78
+ case "label":
79
+ case "trivia":
80
+ case "token":
81
+ case "leaf":
82
+ case "expect":
83
+ case "withCtx":
84
+ case "node":
85
+ case "grammar":
86
+ case "recover":
87
+ return me(d.parser);
88
+ case "skip":
89
+ return me(d.main);
90
+ case "lazy":
91
+ try {
92
+ return me(d.thunk());
93
+ } catch {
94
+ const t = resolveNamedRef(p, resolve);
95
+ return t ? me(t) : true;
96
+ }
97
+ default:
98
+ return true;
99
+ }
100
+ }
101
+ function isZeroWidthAssertion(p) {
102
+ return p._def.tag === "not";
103
+ }
104
+ function isPositiveLookahead(p) {
105
+ return p._def.tag === "peek";
106
+ }
107
+ function narrowBy(acc, constraint) {
108
+ if (constraint.kind === "any") return acc;
109
+ if (acc === null) return constraint;
110
+ if (acc.kind === "any") return constraint;
111
+ if (acc.kind === "empty" || constraint.kind === "empty") return { kind: "empty" };
112
+ const ranges = [];
113
+ for (const a of acc.ranges) for (const b of constraint.ranges) {
114
+ const lo = Math.max(a.lo, b.lo);
115
+ const hi = Math.min(a.hi, b.hi);
116
+ if (lo <= hi) ranges.push({ lo, hi });
117
+ }
118
+ return ranges.length === 0 ? { kind: "empty" } : { kind: "ranges", ranges };
119
+ }
120
+ function applyAssertion(fs, assertion) {
121
+ if (assertion === null) return fs;
122
+ if (fs.kind === "empty") return assertion;
123
+ return narrowBy(fs, assertion) ?? fs;
124
+ }
125
+ function sequenceFirstSet(parsers) {
126
+ let fs = empty();
127
+ let assertion = null;
128
+ for (const p of parsers) {
129
+ if (isPositiveLookahead(p)) {
130
+ assertion = narrowBy(assertion, p._meta.firstSet);
131
+ continue;
132
+ }
133
+ if (!isZeroWidthAssertion(p)) fs = union(fs, p._meta.firstSet);
134
+ if (!matchesEmpty(p)) return applyAssertion(fs, assertion);
135
+ }
136
+ return applyAssertion(fs, assertion);
137
+ }
138
+ function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve) {
139
+ if (seen.has(p)) return any();
140
+ seen.add(p);
141
+ const fs = (c) => firstSetOf(c, seen, resolve);
142
+ const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve);
143
+ const d = p._def;
144
+ switch (d.tag) {
145
+ case "literal":
146
+ case "regex":
147
+ case "keywords":
148
+ return p._meta.firstSet;
149
+ // terminals: no refs, cached set is exact
150
+ case "lazy":
151
+ try {
152
+ return fs(d.thunk());
153
+ } catch {
154
+ const t = resolveNamedRef(p, resolve);
155
+ return t ? fs(t) : any();
156
+ }
157
+ case "choice": {
158
+ let out = empty();
159
+ for (const arm of d.parsers) out = union(out, fs(arm));
160
+ return out;
161
+ }
162
+ case "sequence": {
163
+ let out = empty();
164
+ let assertion = null;
165
+ for (const term of d.parsers) {
166
+ if (isPositiveLookahead(term)) {
167
+ assertion = narrowBy(assertion, fs(term));
168
+ continue;
169
+ }
170
+ if (!isZeroWidthAssertion(term)) out = union(out, fs(term));
171
+ if (!empties(term)) return applyAssertion(out, assertion);
172
+ }
173
+ return applyAssertion(out, assertion);
174
+ }
175
+ case "peek": {
176
+ const inner = d.parser;
177
+ return empties(inner) ? any() : fs(inner);
178
+ }
179
+ case "oneOrMore":
180
+ case "many":
181
+ case "optional":
182
+ case "transform":
183
+ case "label":
184
+ case "trivia":
185
+ case "token":
186
+ case "leaf":
187
+ case "node":
188
+ case "grammar":
189
+ case "expect":
190
+ return fs(d.parser);
191
+ case "sepBy":
192
+ return fs(d.parser);
193
+ // both min 0 and min 1 start with the item
194
+ case "skip":
195
+ return fs(d.main);
196
+ default:
197
+ return p._meta.firstSet;
198
+ }
199
+ }
200
+ function mergeRanges(ranges) {
201
+ if (ranges.length === 0) return [];
202
+ const sorted = [...ranges].sort((a, b) => a.lo - b.lo);
203
+ const out = [{ lo: sorted[0].lo, hi: sorted[0].hi }];
204
+ for (let i = 1; i < sorted.length; i++) {
205
+ const top = out[out.length - 1];
206
+ const cur = sorted[i];
207
+ if (cur.lo <= top.hi + 1) {
208
+ if (cur.hi > top.hi) top.hi = cur.hi;
209
+ } else {
210
+ out.push({ lo: cur.lo, hi: cur.hi });
211
+ }
212
+ }
213
+ return out;
214
+ }
215
+
216
+ // src/combinators/ref.ts
217
+ function ref() {
218
+ let resolved = null;
219
+ const meta = {
220
+ firstSet: any(),
221
+ canMatchNewline: true,
222
+ isTrivia: false
223
+ };
224
+ const slot = {
225
+ _tag: "lazy",
226
+ _meta: meta,
227
+ _def: {
228
+ tag: "lazy",
229
+ thunk: () => {
230
+ if (!resolved) throw new Error("ref<T>() used before .define() was called");
231
+ return resolved;
232
+ }
233
+ },
234
+ parse(input, pos, ctx) {
235
+ if (!resolved) throw new Error("ref<T>() used before .define() was called");
236
+ return resolved.parse(input, pos, ctx);
237
+ },
238
+ define(p) {
239
+ if (resolved) throw new Error("ref<T>() already defined");
240
+ resolved = p;
241
+ meta.firstSet = p._meta.firstSet;
242
+ meta.canMatchNewline = p._meta.canMatchNewline;
243
+ meta.isTrivia = p._meta.isTrivia;
244
+ if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
245
+ else delete meta.triviaKindLabels;
246
+ if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
247
+ else delete meta.disjoint;
248
+ }
249
+ };
250
+ return slot;
251
+ }
252
+
253
+ // src/compiler/value-usage.ts
254
+ function markUnusedValues(root) {
255
+ const seenConsumed = /* @__PURE__ */ new WeakSet();
256
+ const seenUnconsumed = /* @__PURE__ */ new WeakSet();
257
+ const mark = (def, consumed) => {
258
+ if (consumed) def.valueUnused = false;
259
+ else if (def.valueUnused !== false) def.valueUnused = true;
260
+ };
261
+ const visit = (c, consumed) => {
262
+ const seen = consumed ? seenConsumed : seenUnconsumed;
263
+ if (seen.has(c)) return;
264
+ seen.add(c);
265
+ const def = c._def;
266
+ switch (def.tag) {
267
+ case "many":
268
+ case "oneOrMore":
269
+ mark(def, consumed);
270
+ visit(def.parser, consumed);
271
+ return;
272
+ case "optional":
273
+ visit(def.parser, consumed);
274
+ return;
275
+ case "sequence":
276
+ mark(def, consumed);
277
+ for (const p of def.parsers) visit(p, consumed);
278
+ return;
279
+ case "choice":
280
+ for (const p of def.parsers) visit(p, consumed);
281
+ return;
282
+ case "node":
283
+ visit(def.parser, false);
284
+ return;
285
+ case "transform":
286
+ visit(def.parser, true);
287
+ return;
288
+ case "field":
289
+ visit(def.parser, true);
290
+ return;
291
+ case "skip":
292
+ visit(def.main, consumed);
293
+ visit(def.skipped, false);
294
+ return;
295
+ case "sepBy":
296
+ visit(def.parser, true);
297
+ visit(def.separator, false);
298
+ return;
299
+ case "not":
300
+ case "peek":
301
+ visit(def.parser, false);
302
+ return;
303
+ case "grammar":
304
+ visit(def.parser, consumed);
305
+ if (def.triviaParser) visit(def.triviaParser, false);
306
+ return;
307
+ case "recover":
308
+ visit(def.parser, consumed);
309
+ visit(def.sentinel, false);
310
+ return;
311
+ case "label":
312
+ case "trivia":
313
+ case "token":
314
+ case "attempt":
315
+ case "withCtx":
316
+ case "expect":
317
+ visit(def.parser, consumed);
318
+ return;
319
+ case "leaf":
320
+ visit(def.parser, true);
321
+ return;
322
+ case "lazy":
323
+ return;
324
+ default:
325
+ return;
326
+ }
327
+ };
328
+ const resolveRoot = (c) => {
329
+ const guard = /* @__PURE__ */ new Set();
330
+ let cur = c;
331
+ while (!guard.has(cur)) {
332
+ const d = cur._def;
333
+ if (d.tag !== "lazy") return cur;
334
+ guard.add(cur);
335
+ try {
336
+ cur = d.thunk();
337
+ } catch {
338
+ return c;
339
+ }
340
+ }
341
+ return cur;
342
+ };
343
+ visit(resolveRoot(root), true);
344
+ }
345
+
1
346
  // src/combinators/parser.ts
2
347
  var RULE_ORDER = "__parsemanRuleOrder";
348
+ function tagRule(r, key) {
349
+ ;
350
+ r._ruleName = key;
351
+ if (r._def.tag === "node" && r._def.type === void 0) r._def.type = key;
352
+ }
353
+ function rules(a, b) {
354
+ const factory = typeof a === "function" ? a : b;
355
+ const options = typeof a === "function" ? b : a;
356
+ const cache = {};
357
+ const proxy = new Proxy(cache, {
358
+ get(target, key) {
359
+ if (typeof key !== "string") return void 0;
360
+ const record = target;
361
+ if (!(key in record)) {
362
+ const r = ref();
363
+ tagRule(r, key);
364
+ record[key] = r;
365
+ }
366
+ return record[key];
367
+ }
368
+ });
369
+ const definitions = factory(proxy);
370
+ for (const key of Object.keys(definitions)) {
371
+ const placeholder = cache[key];
372
+ const parser2 = definitions[key];
373
+ if (placeholder !== void 0 && typeof placeholder.define === "function") {
374
+ tagRule(parser2, key);
375
+ placeholder.define(parser2);
376
+ placeholder._meta.firstSet = parser2._meta.firstSet;
377
+ placeholder._meta.canMatchNewline = parser2._meta.canMatchNewline;
378
+ } else {
379
+ tagRule(parser2, key);
380
+ cache[key] = parser2;
381
+ }
382
+ }
383
+ if (options?.trivia != null) {
384
+ for (const key of Object.keys(definitions)) {
385
+ const rule = cache[key];
386
+ if (rule && !rule._meta.isTrivia) rule._meta.grammarTrivia = options.trivia;
387
+ }
388
+ }
389
+ if (options?.scanSkip != null) {
390
+ for (const key of Object.keys(definitions)) {
391
+ const rule = cache[key];
392
+ if (rule && !rule._meta.isTrivia) rule._meta.grammarScanSkip = options.scanSkip;
393
+ }
394
+ }
395
+ if (options?.hostMode === "cst") {
396
+ for (const key of Object.keys(definitions)) {
397
+ const rule = cache[key];
398
+ if (rule && !rule._meta.isTrivia) rule._meta.grammarHostMode = "cst";
399
+ }
400
+ }
401
+ for (const key of Object.keys(definitions)) {
402
+ markUnusedValues(cache[key]);
403
+ }
404
+ Object.defineProperty(cache, RULE_ORDER, {
405
+ value: Object.keys(definitions),
406
+ enumerable: false,
407
+ configurable: true
408
+ });
409
+ return cache;
410
+ }
411
+
412
+ // src/cst/capture-buffer.ts
413
+ var EMPTY = [];
414
+ var EMPTY_TL = [];
415
+ function cstCaptureActive(ctx) {
416
+ return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0;
417
+ }
418
+ function beginCstNodeCapture(ctx) {
419
+ const saved = {
420
+ ch: ctx._cstChildren,
421
+ lv: ctx._cstLeaves,
422
+ raw: ctx._cstRawChildren,
423
+ tl: ctx._cstTriviaLog,
424
+ cap: ctx.captureTrivia,
425
+ buf: ctx._cstBuf
426
+ };
427
+ ctx._cstBuf = {};
428
+ ctx._cstChildren = void 0;
429
+ ctx._cstLeaves = void 0;
430
+ ctx._cstRawChildren = void 0;
431
+ ctx._cstTriviaLog = void 0;
432
+ ctx.captureTrivia = true;
433
+ return saved;
434
+ }
435
+ function finishCstBuf(buf) {
436
+ if (!buf) return { children: EMPTY, rawChildren: EMPTY, triviaLog: EMPTY_TL };
437
+ const children = buf.ch ?? (buf.single !== void 0 ? [buf.single] : EMPTY);
438
+ const rawChildren = buf.raw ?? (buf.rawSingle !== void 0 ? [buf.rawSingle] : EMPTY);
439
+ const triviaLog = buf.tl ?? EMPTY_TL;
440
+ return { children, rawChildren, triviaLog };
441
+ }
442
+ function endCstNodeCapture(ctx, saved) {
443
+ const materialized = finishCstBuf(ctx._cstBuf);
444
+ ctx._cstBuf = saved.buf;
445
+ ctx._cstChildren = saved.ch;
446
+ ctx._cstLeaves = saved.lv;
447
+ ctx._cstRawChildren = saved.raw;
448
+ ctx._cstTriviaLog = saved.tl;
449
+ ctx.captureTrivia = saved.cap;
450
+ return materialized;
451
+ }
452
+ function pushCstLeaf(ctx, leaf2) {
453
+ pushCstChild(ctx, leaf2, leaf2);
454
+ }
455
+ function pushCstChild(ctx, built, rawEntry) {
456
+ const b = ctx._cstBuf;
457
+ if (b) {
458
+ if (b.ch) b.ch.push(built);
459
+ else if (b.single !== void 0) {
460
+ b.ch = [b.single, built];
461
+ b.single = void 0;
462
+ } else b.single = built;
463
+ if (b.raw) b.raw.push(rawEntry);
464
+ else if (b.rawSingle !== void 0) {
465
+ b.raw = [b.rawSingle, rawEntry];
466
+ b.rawSingle = void 0;
467
+ } else b.rawSingle = rawEntry;
468
+ return;
469
+ }
470
+ if (ctx._cstChildren) ctx._cstChildren.push(built);
471
+ else if (ctx._cstLeaves) ctx._cstLeaves.push(built);
472
+ if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry);
473
+ }
474
+ function cstRawLen(ctx) {
475
+ const b = ctx._cstBuf;
476
+ if (b) {
477
+ if (b.raw) return b.raw.length;
478
+ return b.rawSingle !== void 0 ? 1 : 0;
479
+ }
480
+ return ctx._cstRawChildren?.length ?? 0;
481
+ }
482
+ function cstLeavesLen(ctx) {
483
+ const b = ctx._cstBuf;
484
+ if (b) {
485
+ if (b.ch) return b.ch.length;
486
+ return b.single !== void 0 ? 1 : 0;
487
+ }
488
+ return ctx._cstLeaves?.length ?? 0;
489
+ }
490
+ function cstTlLen(ctx) {
491
+ const b = ctx._cstBuf;
492
+ if (b) return b.tl?.length ?? 0;
493
+ return ctx._cstTriviaLog?.length ?? 0;
494
+ }
495
+ function saveCstMark(ctx) {
496
+ return {
497
+ raw: cstRawLen(ctx),
498
+ tlog: cstTlLen(ctx),
499
+ leaves: cstLeavesLen(ctx),
500
+ fields: ctx._fields?.length ?? 0,
501
+ // Speculative rollback must truncate the flat recovery-error sink in lockstep
502
+ // with the CST leaves: a branch that recovered (pushing a ParseError to
503
+ // ctx._errors AND embedding it as a CST child via captureError) then failed
504
+ // must remove BOTH, or the flat error survives as a GHOST that a tree walk
505
+ // can't see (flat run().errors would disagree with the embedded set).
506
+ errors: ctx._errors?.length ?? 0
507
+ };
508
+ }
509
+ function rollbackBufList(b, keyMulti, keySingle, len) {
510
+ const arr = b[keyMulti];
511
+ if (arr) {
512
+ if (len === 0) b[keyMulti] = void 0;
513
+ else if (len === 1) {
514
+ b[keySingle] = arr[0];
515
+ b[keyMulti] = void 0;
516
+ } else if (arr.length !== len) arr.length = len;
517
+ return;
518
+ }
519
+ if (len === 0) b[keySingle] = void 0;
520
+ }
521
+ function rollbackCstCapture(ctx, mark) {
522
+ if (ctx._errors && mark.errors !== void 0 && ctx._errors.length !== mark.errors) ctx._errors.length = mark.errors;
523
+ const b = ctx._cstBuf;
524
+ if (b) {
525
+ rollbackBufList(b, "raw", "rawSingle", mark.raw);
526
+ rollbackBufList(b, "ch", "single", mark.leaves);
527
+ if (b.tl) {
528
+ if (mark.tlog === 0) b.tl = void 0;
529
+ else if (b.tl.length !== mark.tlog) b.tl.length = mark.tlog;
530
+ }
531
+ if (ctx._fields && ctx._fields.length !== mark.fields) ctx._fields.length = mark.fields;
532
+ return;
533
+ }
534
+ if (ctx._cstRawChildren && ctx._cstRawChildren.length !== mark.raw) ctx._cstRawChildren.length = mark.raw;
535
+ if (ctx._cstTriviaLog && ctx._cstTriviaLog.length !== mark.tlog) ctx._cstTriviaLog.length = mark.tlog;
536
+ if (ctx._cstLeaves && ctx._cstLeaves.length !== mark.leaves) ctx._cstLeaves.length = mark.leaves;
537
+ if (ctx._fields && ctx._fields.length !== mark.fields) ctx._fields.length = mark.fields;
538
+ }
539
+ function pushCstTriviaEntry(ctx, start, end, kindIndex) {
540
+ const insertIdx = cstRawLen(ctx);
541
+ const b = ctx._cstBuf;
542
+ const withKind = ctx.triviaKindLabels !== void 0 && kindIndex !== void 0;
543
+ if (b) {
544
+ if (!b.tl) {
545
+ b.tl = withKind ? [start, end, insertIdx, kindIndex] : [start, end, insertIdx];
546
+ } else if (withKind) {
547
+ b.tl.push(start, end, insertIdx, kindIndex);
548
+ } else {
549
+ b.tl.push(start, end, insertIdx);
550
+ }
551
+ return;
552
+ }
553
+ if (ctx._cstTriviaLog) {
554
+ if (withKind) ctx._cstTriviaLog.push(start, end, insertIdx, kindIndex);
555
+ else ctx._cstTriviaLog.push(start, end, insertIdx);
556
+ }
557
+ }
558
+ function pushTriviaLogEntry(ctx, start, end, kindIndex) {
559
+ if (!ctx._triviaLog) return;
560
+ if (ctx.triviaKindLabels !== void 0 && kindIndex !== void 0) {
561
+ ctx._triviaLog.push(start, end, kindIndex);
562
+ } else {
563
+ ctx._triviaLog.push(start, end);
564
+ }
565
+ }
566
+
567
+ // src/recovery/scan.ts
568
+ function probeAt(sentinel, input, pos, ctx) {
569
+ const s = {
570
+ _probe: ctx._probe,
571
+ _errors: ctx._errors,
572
+ _cstLeaves: ctx._cstLeaves,
573
+ _cstChildren: ctx._cstChildren,
574
+ _cstRawChildren: ctx._cstRawChildren,
575
+ _cstTriviaLog: ctx._cstTriviaLog,
576
+ _triviaLog: ctx._triviaLog,
577
+ _fields: ctx._fields,
578
+ _cstBuf: ctx._cstBuf,
579
+ _tolerant: ctx._tolerant,
580
+ _sync: ctx._sync
581
+ };
582
+ ctx._probe = void 0;
583
+ ctx._errors = void 0;
584
+ ctx._cstLeaves = void 0;
585
+ ctx._cstChildren = void 0;
586
+ ctx._cstRawChildren = void 0;
587
+ ctx._cstTriviaLog = void 0;
588
+ ctx._triviaLog = void 0;
589
+ ctx._fields = void 0;
590
+ ctx._cstBuf = void 0;
591
+ ctx._tolerant = void 0;
592
+ ctx._sync = void 0;
593
+ try {
594
+ return sentinel.parse(input, pos, ctx).ok;
595
+ } finally {
596
+ ctx._probe = s._probe;
597
+ ctx._errors = s._errors;
598
+ ctx._cstLeaves = s._cstLeaves;
599
+ ctx._cstChildren = s._cstChildren;
600
+ ctx._cstRawChildren = s._cstRawChildren;
601
+ ctx._cstTriviaLog = s._cstTriviaLog;
602
+ ctx._triviaLog = s._triviaLog;
603
+ ctx._fields = s._fields;
604
+ ctx._cstBuf = s._cstBuf;
605
+ ctx._tolerant = s._tolerant;
606
+ ctx._sync = s._sync;
607
+ }
608
+ }
609
+ function orSentinel(a, b) {
610
+ if (b === void 0) return a;
611
+ return {
612
+ _tag: "orSentinel",
613
+ _meta: { firstSet: { kind: "any" }, canMatchNewline: false, isTrivia: false },
614
+ _def: { tag: "unknown" },
615
+ parse(input, pos, ctx) {
616
+ const ra = a.parse(input, pos, ctx);
617
+ if (ra.ok) return ra;
618
+ return b.parse(input, pos, ctx);
619
+ }
620
+ };
621
+ }
622
+ function firstSetSentinel(fs) {
623
+ if (fs.kind !== "ranges" || fs.ranges.length === 0) return null;
624
+ const ranges = fs.ranges;
625
+ return {
626
+ _tag: "firstSetSentinel",
627
+ _meta: { firstSet: fs, canMatchNewline: false, isTrivia: false },
628
+ _def: { tag: "unknown" },
629
+ parse(input, pos) {
630
+ const code = pos < input.length ? input.codePointAt(pos) : void 0;
631
+ if (code !== void 0) {
632
+ for (const r of ranges) {
633
+ if (code >= r.lo && code <= r.hi) return { ok: true, value: null, span: { start: pos, end: pos } };
634
+ }
635
+ }
636
+ return { ok: false, expected: [], span: { start: pos, end: pos } };
637
+ }
638
+ };
639
+ }
640
+ function recoverScan(input, from, ctx, sync, expected) {
641
+ let scanPos = from;
642
+ while (scanPos < input.length && !probeAt(sync, input, scanPos, ctx)) scanPos++;
643
+ const error = { _tag: "parseError", span: { start: from, end: scanPos }, expected };
644
+ ctx._errors?.push(error);
645
+ return { error, end: scanPos };
646
+ }
647
+ function matchesAt(sentinel, input, pos, ctx) {
648
+ return probeAt(sentinel, input, pos, ctx);
649
+ }
650
+ function captureError(ctx, error) {
651
+ if (cstCaptureActive(ctx)) pushCstChild(ctx, error, error);
652
+ }
653
+
654
+ // src/combinators/expect.ts
655
+ function deriveExpected(c) {
656
+ return [...new Set(derive(c, /* @__PURE__ */ new Set()))];
657
+ }
658
+ function derive(c, seen) {
659
+ const deriveExpected2 = (p) => derive(p, seen);
660
+ const def = c._def;
661
+ switch (def.tag) {
662
+ case "literal":
663
+ return [JSON.stringify(def.value)];
664
+ case "regex":
665
+ return [`/${def.source}/`];
666
+ case "keywords":
667
+ return def.words.map((w) => JSON.stringify(w));
668
+ case "label":
669
+ return [def.label];
670
+ case "choice":
671
+ return def.parsers.flatMap(deriveExpected2);
672
+ // Union through the NULLABLE prefix, mirroring `sequenceFirstSet`. A leading
673
+ // `optional(…)`/`many(…)` can match nothing, so the term after it is equally
674
+ // able to fail first — deriving from term 0 alone named a token the parse
675
+ // never actually required. A leading `not(…)` is zero-width and contributes
676
+ // nothing (its own expectation is about what must NOT be here), but it is
677
+ // nullable, so keep scanning past it. Stop at the first term that must match.
678
+ case "sequence": {
679
+ const out = [];
680
+ for (const term of def.parsers) {
681
+ if (!isZeroWidthAssertion(term)) out.push(...deriveExpected2(term));
682
+ if (!matchesEmpty(term)) break;
683
+ }
684
+ return out;
685
+ }
686
+ case "attempt":
687
+ return deriveExpected2(def.parser);
688
+ // Delegating wrappers whose first-token failure is their inner parser's — must
689
+ // pass through so a start-failure (and the first-set-miss fast-path in attempt/
690
+ // node, which reads this) names the real expected token, not the wrapper tag.
691
+ case "field":
692
+ case "withCtx":
693
+ case "recover":
694
+ return deriveExpected2(def.parser);
695
+ case "skip":
696
+ return deriveExpected2(def.main);
697
+ case "expect":
698
+ return def.expected;
699
+ case "node":
700
+ case "grammar":
701
+ case "trivia":
702
+ case "token":
703
+ case "leaf":
704
+ case "optional":
705
+ case "many":
706
+ case "oneOrMore":
707
+ case "transform":
708
+ case "not":
709
+ case "peek":
710
+ return deriveExpected2(def.parser);
711
+ case "lazy": {
712
+ const name = c._ruleName;
713
+ if (seen.has(c)) return name ? [name] : [];
714
+ seen.add(c);
715
+ try {
716
+ return deriveExpected2(def.thunk());
717
+ } catch {
718
+ return name ? [name] : [];
719
+ } finally {
720
+ seen.delete(c);
721
+ }
722
+ }
723
+ default:
724
+ return [];
725
+ }
726
+ }
727
+ function expect(combinator, label2) {
728
+ const expected = label2 !== void 0 ? [label2] : deriveExpected(combinator);
729
+ const meta = {
730
+ firstSet: combinator._meta.firstSet,
731
+ canMatchNewline: combinator._meta.canMatchNewline,
732
+ isTrivia: false
733
+ };
734
+ return {
735
+ _tag: "expect",
736
+ _meta: meta,
737
+ _def: { tag: "expect", parser: combinator, label: label2, expected },
738
+ parse(input, pos, ctx) {
739
+ const result = combinator.parse(input, pos, ctx);
740
+ if (result.ok) return result;
741
+ const error = { _tag: "parseError", span: { start: pos, end: pos }, expected };
742
+ ctx._errors?.push(error);
743
+ if (ctx._tolerant) captureError(ctx, error);
744
+ return { ok: true, value: error, span: { start: pos, end: pos } };
745
+ }
746
+ };
747
+ }
748
+
749
+ // src/combinators/choice.ts
750
+ function choice(...args) {
751
+ const parsers = args.map((a) => "gate" in a ? a.combinator : a);
752
+ const gates = args.map((a) => "gate" in a ? a.gate : null);
753
+ const hasGates = gates.some((g) => g !== null);
754
+ const disjoint = areDisjoint(parsers.map((p) => p._meta.firstSet)) && parsers.every((p) => !matchesEmpty(p));
755
+ let combined = { kind: "empty" };
756
+ for (const p of parsers) combined = union(combined, p._meta.firstSet);
757
+ const meta = {
758
+ firstSet: combined,
759
+ canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
760
+ isTrivia: false,
761
+ disjoint
762
+ };
763
+ const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
764
+ const autoNot = !disjoint && !hasGates && (strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix") ? computeAutoNot(parsers) : parsers.map(() => null);
765
+ let greedyLitMap = null;
766
+ let sortedParsers = null;
767
+ const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
768
+ if (strategy?.tag === "greedyClassify") {
769
+ greedyLitMap = /* @__PURE__ */ new Map();
770
+ for (let i = 0; i < parsers.length; i++) {
771
+ if (i === strategy.superIndex) continue;
772
+ const litVal = getCoreLiteralValue(parsers[i]);
773
+ if (litVal !== null) greedyLitMap.set(litVal, i);
774
+ }
775
+ } else if (strategy?.tag === "literalsLongestFirst") {
776
+ sortedParsers = strategy.sortedIndices.map((i) => parsers[i]);
777
+ }
778
+ return {
779
+ _tag: "choice",
780
+ _meta: meta,
781
+ _def: {
782
+ tag: "choice",
783
+ parsers,
784
+ gates,
785
+ disjoint,
786
+ strategy: strategy ?? { tag: "firstMatch" },
787
+ autoNot
788
+ },
789
+ parse(input, pos, ctx) {
790
+ const expected = [];
791
+ if (disjoint && pos < input.length) {
792
+ const code = input.codePointAt(pos);
793
+ let idx = code < 128 ? asciiDispatch[code] : -1;
794
+ if (idx < 0) {
795
+ for (let i = 0; i < parsers.length; i++) {
796
+ if (inFirstSet(code, parsers[i]._meta.firstSet)) {
797
+ idx = i;
798
+ break;
799
+ }
800
+ }
801
+ }
802
+ if (idx >= 0) {
803
+ const gate = gates[idx];
804
+ if (gate && !gate(ctx.state)) {
805
+ return { ok: false, expected: deriveExpected(parsers[idx]), span: { start: pos, end: pos } };
806
+ }
807
+ const result = parsers[idx].parse(input, pos, ctx);
808
+ if (result.ok) return result;
809
+ expected.push(...result.expected);
810
+ return { ok: false, expected, span: { start: pos, end: pos } };
811
+ }
812
+ return {
813
+ ok: false,
814
+ expected: parsers.flatMap((p) => {
815
+ const r = p.parse(input, pos, ctx);
816
+ return r.ok ? [] : r.expected;
817
+ }),
818
+ span: { start: pos, end: pos }
819
+ };
820
+ }
821
+ if (strategy?.tag === "greedyClassify") {
822
+ const superResult = parsers[strategy.superIndex].parse(input, pos, ctx);
823
+ if (!superResult.ok) return superResult;
824
+ const end = superResult.span.end;
825
+ const litIdx = greedyLitMap.get(input.slice(pos, end));
826
+ if (litIdx !== void 0) {
827
+ const litVal = getCoreLiteralValue(parsers[litIdx]);
828
+ const value = applyTransforms(parsers[litIdx], litVal, { start: pos, end });
829
+ return { ok: true, value, span: { start: pos, end } };
830
+ }
831
+ return superResult;
832
+ }
833
+ if (strategy?.tag === "literalsLongestFirst") {
834
+ for (const p of sortedParsers) {
835
+ const r = p.parse(input, pos, ctx);
836
+ if (r.ok) return r;
837
+ expected.push(...r.expected);
838
+ }
839
+ return { ok: false, expected, span: { start: pos, end: pos } };
840
+ }
841
+ for (let i = 0; i < parsers.length; i++) {
842
+ if (gates[i] && !gates[i](ctx.state)) continue;
843
+ const mark = saveCstMark(ctx);
844
+ const logLen = ctx._triviaLog?.length;
845
+ const result = parsers[i].parse(input, pos, ctx);
846
+ if (!result.ok) {
847
+ rollbackCstCapture(ctx, mark);
848
+ if (logLen !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== logLen) ctx._triviaLog.length = logLen;
849
+ expected.push(...result.expected);
850
+ continue;
851
+ }
852
+ const checks = autoNot[i];
853
+ if (checks && autoNotFires(input, result.span.end, checks)) {
854
+ rollbackCstCapture(ctx, mark);
855
+ if (logLen !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== logLen) ctx._triviaLog.length = logLen;
856
+ continue;
857
+ }
858
+ return result;
859
+ }
860
+ return { ok: false, expected, span: { start: pos, end: pos } };
861
+ }
862
+ };
863
+ }
864
+ function detectStrategy(parsers) {
865
+ const regexIndices = [];
866
+ const literalIndices = [];
867
+ for (let i = 0; i < parsers.length; i++) {
868
+ if (getCoreRegexDef(parsers[i]) !== null) regexIndices.push(i);
869
+ else if (getCoreLiteralValue(parsers[i]) !== null) literalIndices.push(i);
870
+ }
871
+ if (regexIndices.length === 1 && literalIndices.length === parsers.length - 1 && literalIndices.length > 0) {
872
+ const superIndex = regexIndices[0];
873
+ const regexDef = getCoreRegexDef(parsers[superIndex]);
874
+ const flags = "y" + regexDef.flags.replace(/[gy]/g, "");
875
+ const re = new RegExp(regexDef.source, flags);
876
+ const allSubsumed = literalIndices.every((i) => {
877
+ const litVal = getCoreLiteralValue(parsers[i]);
878
+ re.lastIndex = 0;
879
+ const m = re.exec(litVal);
880
+ return m !== null && m[0] === litVal;
881
+ });
882
+ if (allSubsumed) return { tag: "greedyClassify", superIndex };
883
+ }
884
+ if (parsers.length === literalIndices.length) {
885
+ const sortedIndices = [...literalIndices].sort(
886
+ (a, b) => getCoreLiteralValue(parsers[b]).length - getCoreLiteralValue(parsers[a]).length
887
+ );
888
+ return { tag: "literalsLongestFirst", sortedIndices };
889
+ }
890
+ const shared = detectSharedPrefix(parsers);
891
+ if (shared !== null) return shared;
892
+ return { tag: "firstMatch" };
893
+ }
894
+ function bareLeadingTermKey(term) {
895
+ const d = term._def;
896
+ if (d.tag === "literal" && !d.caseInsensitive) return `L:${d.value}`;
897
+ if (d.tag === "regex") return `R:${d.source}\0${d.flags}`;
898
+ return null;
899
+ }
900
+ function detectSharedPrefix(parsers) {
901
+ if (parsers.length < 2) return null;
902
+ let key = null;
903
+ let prefix = null;
904
+ const members = [];
905
+ for (let i = 0; i < parsers.length; i++) {
906
+ const term0 = leadingTermOfArm(parsers[i]);
907
+ if (term0 === null) return null;
908
+ const k = bareLeadingTermKey(term0);
909
+ if (k === null) return null;
910
+ if (key === null) {
911
+ key = k;
912
+ prefix = term0;
913
+ } else if (k !== key) return null;
914
+ members.push(i);
915
+ }
916
+ if (prefix === null || members.length < 2) return null;
917
+ return { tag: "sharedPrefix", prefix, members };
918
+ }
919
+ function leadingTermOfArm(arm) {
920
+ let d = arm._def;
921
+ for (; ; ) {
922
+ if (d.tag === "node" || d.tag === "grammar" || d.tag === "transform" || d.tag === "label") {
923
+ d = d.parser._def;
924
+ continue;
925
+ }
926
+ break;
927
+ }
928
+ if (d.tag !== "sequence" || d.parsers.length < 2) return null;
929
+ return d.parsers[0];
930
+ }
931
+ function computeAutoNot(parsers) {
932
+ return parsers.map((p, i) => {
933
+ const litVal = getCoreLiteralValue(p);
934
+ if (litVal === null) return null;
935
+ const checks = [];
936
+ for (let j2 = i + 1; j2 < parsers.length; j2++) {
937
+ const other = parsers[j2];
938
+ const otherLit = getCoreLiteralValue(other);
939
+ if (otherLit !== null && otherLit.startsWith(litVal) && otherLit.length > litVal.length) {
940
+ checks.push({ kind: "startsWith", value: otherLit.slice(litVal.length) });
941
+ continue;
942
+ }
943
+ const regexDef = getCoreRegexDef(other);
944
+ if (regexDef !== null) {
945
+ const contSet = continuationFirstSet(litVal, regexDef.source, regexDef.flags);
946
+ if (contSet !== null) checks.push({ kind: "firstSet", set: contSet });
947
+ }
948
+ }
949
+ return checks.length > 0 ? checks : null;
950
+ });
951
+ }
952
+ function autoNotFires(input, end, checks) {
953
+ for (const check of checks) {
954
+ if (check.kind === "firstSet") {
955
+ const code = end < input.length ? input.codePointAt(end) ?? -1 : -1;
956
+ if (inFirstSet(code, check.set)) return true;
957
+ } else {
958
+ if (input.startsWith(check.value, end)) return true;
959
+ }
960
+ }
961
+ return false;
962
+ }
963
+ function getCoreLiteralValue(p) {
964
+ const def = p._def;
965
+ if (def.tag === "literal" && !def.caseInsensitive) return def.value;
966
+ if (def.tag === "transform") return getCoreLiteralValue(def.parser);
967
+ return null;
968
+ }
969
+ function getCoreRegexDef(p) {
970
+ const def = p._def;
971
+ if (def.tag === "regex") return { source: def.source, flags: def.flags };
972
+ if (def.tag === "transform") return getCoreRegexDef(def.parser);
973
+ if (def.tag === "label") return getCoreRegexDef(def.parser);
974
+ return null;
975
+ }
976
+ function applyTransforms(p, value, span) {
977
+ const def = p._def;
978
+ if (def.tag === "transform") {
979
+ const inner = applyTransforms(def.parser, value, span);
980
+ return def.fn(inner, span);
981
+ }
982
+ return value;
983
+ }
984
+ function continuationFirstSet(lit, source, flags) {
985
+ const re = new RegExp(source, "y" + flags.replace(/[gy]/g, ""));
986
+ re.lastIndex = 0;
987
+ const base = re.exec(lit);
988
+ if (!base || base[0] !== lit) return null;
989
+ const contCodes = [];
990
+ for (let code = 1; code < 128; code++) {
991
+ re.lastIndex = 0;
992
+ const m = re.exec(lit + String.fromCharCode(code));
993
+ if (m && m[0].length > lit.length) contCodes.push(code);
994
+ }
995
+ if (contCodes.length === 0) return null;
996
+ return codesToFirstSet(contCodes);
997
+ }
998
+ function codesToFirstSet(codes) {
999
+ codes.sort((a, b) => a - b);
1000
+ const ranges = [];
1001
+ let lo = codes[0], hi = codes[0];
1002
+ for (let i = 1; i < codes.length; i++) {
1003
+ if (codes[i] === hi + 1) {
1004
+ hi = codes[i];
1005
+ } else {
1006
+ ranges.push({ lo, hi });
1007
+ lo = hi = codes[i];
1008
+ }
1009
+ }
1010
+ ranges.push({ lo, hi });
1011
+ return { kind: "ranges", ranges };
1012
+ }
1013
+ function inFirstSet(code, fs) {
1014
+ if (fs.kind === "any") return true;
1015
+ if (fs.kind === "empty") return false;
1016
+ for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
1017
+ return false;
1018
+ }
1019
+ function areDisjoint(sets) {
1020
+ if (sets.some((s) => s.kind === "any")) return false;
1021
+ for (let i = 0; i < sets.length; i++)
1022
+ for (let j2 = i + 1; j2 < sets.length; j2++)
1023
+ if (intersects(sets[i], sets[j2])) return false;
1024
+ return true;
1025
+ }
1026
+ function buildAsciiDispatch(parsers) {
1027
+ const table = Array(128).fill(-1);
1028
+ for (let i = 0; i < parsers.length; i++) {
1029
+ const fs = parsers[i]._meta.firstSet;
1030
+ if (fs.kind !== "ranges") continue;
1031
+ for (const { lo, hi } of fs.ranges) {
1032
+ for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) {
1033
+ table[code] = i;
1034
+ }
1035
+ }
1036
+ }
1037
+ return table;
1038
+ }
1039
+
1040
+ // src/analysis/duplication.ts
1041
+ var WORD_RE_SRC = "-?[A-Za-z][A-Za-z0-9_-]*";
1042
+ var WORDS_RE = new RegExp(`^${WORD_RE_SRC}(?:\\|${WORD_RE_SRC})*$`);
1043
+
1044
+ // src/combinators/probe.ts
1045
+ function failAt(ctx, expected, pos) {
1046
+ const r = { ok: false, expected, span: { start: pos, end: pos } };
1047
+ const probe = ctx._probe;
1048
+ if (probe !== void 0 && pos <= probe.offset) {
1049
+ const best = probe.best;
1050
+ if (best === null || pos > best.span.start) {
1051
+ probe.best = r;
1052
+ } else if (pos === best.span.start) {
1053
+ probe.best = { ...best, expected: [...best.expected, ...expected] };
1054
+ }
1055
+ }
1056
+ return r;
1057
+ }
1058
+
1059
+ // src/combinators/literal.ts
1060
+ function asciiFoldEq(a, b) {
1061
+ if (a.length !== b.length) return false;
1062
+ for (let i = 0; i < a.length; i++) {
1063
+ let ca = a.charCodeAt(i);
1064
+ let cb = b.charCodeAt(i);
1065
+ if (ca >= 65 && ca <= 90) ca += 32;
1066
+ if (cb >= 65 && cb <= 90) cb += 32;
1067
+ if (ca !== cb) return false;
1068
+ }
1069
+ return true;
1070
+ }
1071
+ function literal(value, opts = {}) {
1072
+ const caseInsensitive = opts.caseInsensitive ?? false;
1073
+ const firstSet = value.length > 0 ? fromChar(value.codePointAt(0)) : empty();
1074
+ const meta = {
1075
+ firstSet,
1076
+ canMatchNewline: value.includes("\n"),
1077
+ isTrivia: false
1078
+ };
1079
+ if (caseInsensitive) {
1080
+ const upper = value.toUpperCase();
1081
+ const lower = value.toLowerCase();
1082
+ const firstUpper = upper.codePointAt(0);
1083
+ const firstLower = lower.codePointAt(0);
1084
+ meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? { kind: "ranges", ranges: [{ lo: firstLower, hi: firstLower }] } : { kind: "ranges", ranges: [
1085
+ { lo: firstLower, hi: firstLower },
1086
+ { lo: firstUpper, hi: firstUpper }
1087
+ ] } : firstSet;
1088
+ }
1089
+ const expected = [JSON.stringify(value)];
1090
+ const parse = !caseInsensitive && value.length === 1 ? (() => {
1091
+ const code = value.charCodeAt(0);
1092
+ return function parse2(input, pos, ctx) {
1093
+ if (input.charCodeAt(pos) === code) {
1094
+ const span = { start: pos, end: pos + 1 };
1095
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
1096
+ return { ok: true, value, span };
1097
+ }
1098
+ return failAt(ctx, expected, pos);
1099
+ };
1100
+ })() : function parse2(input, pos, ctx) {
1101
+ const end = pos + value.length;
1102
+ if (end > input.length) {
1103
+ return failAt(ctx, expected, pos);
1104
+ }
1105
+ const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
1106
+ if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
1107
+ const span = { start: pos, end };
1108
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: matchedValue, span });
1109
+ return { ok: true, value: matchedValue, span };
1110
+ }
1111
+ return failAt(ctx, expected, pos);
1112
+ };
1113
+ return {
1114
+ _tag: "literal",
1115
+ _meta: meta,
1116
+ _def: { tag: "literal", value, caseInsensitive },
1117
+ parse
1118
+ };
1119
+ }
1120
+
1121
+ // src/regex/classes.ts
1122
+ var CLASS_ESCAPES = { t: 9, n: 10, r: 13, f: 12, v: 11, "0": 0 };
1123
+ var SPACE_RANGES = [
1124
+ [9, 13],
1125
+ [32, 32],
1126
+ [160, 160],
1127
+ [5760, 5760],
1128
+ [8192, 8202],
1129
+ [8232, 8232],
1130
+ [8233, 8233],
1131
+ [8239, 8239],
1132
+ [8287, 8287],
1133
+ [12288, 12288],
1134
+ [65279, 65279]
1135
+ ];
1136
+ function shorthandRanges(ch) {
1137
+ if (ch === "d") return [[48, 57]];
1138
+ if (ch === "s") return SPACE_RANGES;
1139
+ return [[48, 57], [65, 90], [97, 122], [95, 95]];
1140
+ }
1141
+ function readUnicodeEscape(body, i) {
1142
+ if (body[i] !== "\\" || body[i + 1] !== "u") return null;
1143
+ const hex = body.slice(i + 2, i + 6);
1144
+ if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
1145
+ return { cp: Number.parseInt(hex, 16), next: i + 6 };
1146
+ }
1147
+ function parseClassRanges(body) {
1148
+ const ranges = [];
1149
+ let i = 0;
1150
+ const readAtom = () => {
1151
+ const ch = body[i];
1152
+ if (ch === void 0) return null;
1153
+ if (ch === "\\") {
1154
+ const uni = readUnicodeEscape(body, i);
1155
+ if (uni) {
1156
+ i = uni.next;
1157
+ return { cp: uni.cp };
1158
+ }
1159
+ const e = body[i + 1];
1160
+ if (e === void 0) return null;
1161
+ i += 2;
1162
+ if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
1163
+ if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
1164
+ if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
1165
+ return { cp: e.codePointAt(0) };
1166
+ }
1167
+ i += ch.length;
1168
+ return { cp: ch.codePointAt(0) };
1169
+ };
1170
+ while (i < body.length) {
1171
+ const lo = readAtom();
1172
+ if (lo === null) return null;
1173
+ if ("set" in lo) {
1174
+ ranges.push(...lo.set);
1175
+ continue;
1176
+ }
1177
+ if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
1178
+ i += 1;
1179
+ const hi = readAtom();
1180
+ if (hi === null || "set" in hi) return null;
1181
+ ranges.push([lo.cp, hi.cp]);
1182
+ } else {
1183
+ ranges.push([lo.cp, lo.cp]);
1184
+ }
1185
+ }
1186
+ return ranges.length ? ranges : null;
1187
+ }
1188
+
1189
+ // src/combinators/regex.ts
1190
+ var firstSetAnalyzer = null;
1191
+ var permissiveFirstSet = () => ({ firstSet: any(), canMatchNewline: true });
1192
+ var SCAN_BAIL_AT = 64;
1193
+ function inRanges(cp, ranges) {
1194
+ for (let i = 0; i < ranges.length; i++) {
1195
+ const [lo, hi] = ranges[i];
1196
+ if (cp >= lo && cp <= hi) return true;
1197
+ }
1198
+ return false;
1199
+ }
1200
+ function readClassRanges(body) {
1201
+ if (body.startsWith("^")) return null;
1202
+ return parseClassRanges(body);
1203
+ }
1204
+ function shortScanner(source, flags) {
1205
+ if (/[imsuvy]/.test(flags)) return null;
1206
+ let ranges = null;
1207
+ let quant = "";
1208
+ if (source[0] === "[") {
1209
+ let end = 1;
1210
+ while (end < source.length && source[end] !== "]") {
1211
+ if (source[end] === "\\") end += 2;
1212
+ else end++;
1213
+ }
1214
+ if (source[end] !== "]") return null;
1215
+ ranges = readClassRanges(source.slice(1, end));
1216
+ quant = source.slice(end + 1);
1217
+ } else if (source[0] === "\\" && (source[1] === "d" || source[1] === "w" || source[1] === "s")) {
1218
+ ranges = shorthandRanges(source[1]);
1219
+ quant = source.slice(2);
1220
+ }
1221
+ if (!ranges || quant !== "+" && quant !== "*") return null;
1222
+ const minOne = quant === "+";
1223
+ return (input, pos) => {
1224
+ let end = pos;
1225
+ while (end < input.length && inRanges(input.charCodeAt(end), ranges)) {
1226
+ end++;
1227
+ if (end - pos >= SCAN_BAIL_AT) return void 0;
1228
+ }
1229
+ return minOne && end === pos ? null : end;
1230
+ };
1231
+ }
1232
+ function asciiCaseFold(fs) {
1233
+ if (fs.kind !== "ranges") return fs;
1234
+ const ranges = fs.ranges.map((r) => ({ lo: r.lo, hi: r.hi }));
1235
+ const add = (lo, hi) => {
1236
+ if (lo <= hi) ranges.push({ lo, hi });
1237
+ };
1238
+ for (const r of fs.ranges) {
1239
+ const uLo = Math.max(r.lo, 65), uHi = Math.min(r.hi, 90);
1240
+ add(uLo + 32, uHi + 32);
1241
+ const lLo = Math.max(r.lo, 97), lHi = Math.min(r.hi, 122);
1242
+ add(lLo - 32, lHi - 32);
1243
+ }
1244
+ ranges.sort((a, b) => a.lo - b.lo);
1245
+ const merged = [];
1246
+ for (const r of ranges) {
1247
+ const last = merged[merged.length - 1];
1248
+ if (last && r.lo <= last.hi + 1) last.hi = Math.max(last.hi, r.hi);
1249
+ else merged.push({ lo: r.lo, hi: r.hi });
1250
+ }
1251
+ return { kind: "ranges", ranges: merged };
1252
+ }
1253
+ function regex(pattern, flags = "") {
1254
+ const source = typeof pattern === "string" ? pattern : pattern.source;
1255
+ const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
1256
+ const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
1257
+ const scan = shortScanner(source, resolvedFlags);
1258
+ const raw = (firstSetAnalyzer ?? permissiveFirstSet)(source);
1259
+ const firstSet = !resolvedFlags.includes("i") ? raw.firstSet : resolvedFlags.includes("u") || resolvedFlags.includes("v") ? any() : asciiCaseFold(raw.firstSet);
1260
+ const canMatchNewline = raw.canMatchNewline;
1261
+ const meta = { firstSet, canMatchNewline, isTrivia: false };
1262
+ return {
1263
+ _tag: "regex",
1264
+ _meta: meta,
1265
+ _def: { tag: "regex", source, flags: resolvedFlags },
1266
+ parse(input, pos, ctx) {
1267
+ const scanEnd = scan?.(input, pos);
1268
+ if (scanEnd !== void 0) {
1269
+ if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
1270
+ const value = input.slice(pos, scanEnd);
1271
+ const span2 = { start: pos, end: scanEnd };
1272
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span: span2 });
1273
+ return { ok: true, value, span: span2 };
1274
+ }
1275
+ anchored.lastIndex = pos;
1276
+ const m = anchored.exec(input);
1277
+ if (m === null) {
1278
+ return failAt(ctx, [`/${source}/`], pos);
1279
+ }
1280
+ const span = { start: pos, end: pos + m[0].length };
1281
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value: m[0], span });
1282
+ return { ok: true, value: m[0], span };
1283
+ }
1284
+ };
1285
+ }
1286
+
1287
+ // src/cst/trivia-kinds.ts
1288
+ function unwrapTrivia(p) {
1289
+ let cur = p;
1290
+ while (cur._def.tag === "trivia") cur = cur._def.parser;
1291
+ return cur;
1292
+ }
1293
+ function peelLabel(p) {
1294
+ if (p._def.tag === "label") return { label: p._def.label, parser: p._def.parser };
1295
+ return null;
1296
+ }
1297
+ function analyzeLabeledTrivia(trivia2) {
1298
+ let core = unwrapTrivia(trivia2);
1299
+ let minRepeats = 1;
1300
+ if (core._def.tag === "oneOrMore") {
1301
+ core = core._def.parser;
1302
+ minRepeats = 1;
1303
+ } else if (core._def.tag === "many") {
1304
+ core = core._def.parser;
1305
+ minRepeats = 0;
1306
+ }
1307
+ const arms = [];
1308
+ if (core._def.tag === "choice") {
1309
+ for (let i = 0; i < core._def.parsers.length; i++) {
1310
+ const peeled = peelLabel(core._def.parsers[i]);
1311
+ if (!peeled) return null;
1312
+ arms.push({ label: peeled.label, kindIndex: i, parser: peeled.parser });
1313
+ }
1314
+ } else {
1315
+ const peeled = peelLabel(core);
1316
+ if (!peeled) return null;
1317
+ arms.push({ label: peeled.label, kindIndex: 0, parser: peeled.parser });
1318
+ }
1319
+ return { labels: arms.map((a) => a.label), arms, minRepeats };
1320
+ }
1321
+ function matchArmAt(input, pos, arm) {
1322
+ const r = arm.parse(input, pos, { trackLines: false });
1323
+ if (!r.ok || r.span.end <= pos) return null;
1324
+ return { end: r.span.end };
1325
+ }
1326
+ function scanLabeledTriviaChunks(input, cur, spec) {
1327
+ const chunks = [];
1328
+ let pos = cur;
1329
+ while (pos < input.length) {
1330
+ let matched = null;
1331
+ for (const arm of spec.arms) {
1332
+ const m = matchArmAt(input, pos, arm.parser);
1333
+ if (m) {
1334
+ matched = { end: m.end, kindIndex: arm.kindIndex };
1335
+ break;
1336
+ }
1337
+ }
1338
+ if (!matched) break;
1339
+ chunks.push({ start: pos, end: matched.end, kindIndex: matched.kindIndex });
1340
+ pos = matched.end;
1341
+ }
1342
+ if (chunks.length < spec.minRepeats) {
1343
+ return { end: cur, chunks: [] };
1344
+ }
1345
+ return { end: pos, chunks };
1346
+ }
1347
+ function scanFastWsCommentsChunks(input, cur, wsKind, commentKind) {
1348
+ const chunks = [];
1349
+ let pos = cur;
1350
+ while (pos < input.length) {
1351
+ const c = input.charCodeAt(pos);
1352
+ if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {
1353
+ const start = pos;
1354
+ pos++;
1355
+ while (pos < input.length) {
1356
+ const c2 = input.charCodeAt(pos);
1357
+ if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) pos++;
1358
+ else break;
1359
+ }
1360
+ chunks.push({ start, end: pos, kindIndex: wsKind });
1361
+ continue;
1362
+ }
1363
+ if (c === 47 && input.charCodeAt(pos + 1) === 42) {
1364
+ let j2 = pos + 2;
1365
+ while (j2 + 1 < input.length && !(input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47)) j2++;
1366
+ if (j2 + 1 < input.length && input.charCodeAt(j2) === 42 && input.charCodeAt(j2 + 1) === 47) {
1367
+ const start = pos;
1368
+ pos = j2 + 2;
1369
+ chunks.push({ start, end: pos, kindIndex: commentKind });
1370
+ continue;
1371
+ }
1372
+ break;
1373
+ }
1374
+ break;
1375
+ }
1376
+ return { end: pos, chunks };
1377
+ }
1378
+ function tryFastLabeledScan(input, cur, trivia2) {
1379
+ const spec = analyzeLabeledTrivia(trivia2);
1380
+ if (!spec || spec.arms.length !== 2) return null;
1381
+ const wsArm = spec.arms.find((a) => {
1382
+ const src = getCoreRegexDef(a.parser)?.source;
1383
+ return src != null && !src.includes("\\*");
1384
+ });
1385
+ const commentArm = spec.arms.find((a) => {
1386
+ const src = getCoreRegexDef(a.parser)?.source;
1387
+ return src != null && src.includes("\\*");
1388
+ });
1389
+ if (!wsArm || !commentArm) return null;
1390
+ const { chunks } = scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1391
+ if (chunks.length < spec.minRepeats) return { end: cur, chunks: [] };
1392
+ return scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1393
+ }
1394
+ function recordTriviaChunks(ctx, chunks) {
1395
+ const kinds = ctx.triviaKindLabels;
1396
+ const mask = ctx._triviaCaptureMask;
1397
+ for (const ch of chunks) {
1398
+ pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1399
+ if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
1400
+ if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) {
1401
+ pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1402
+ }
1403
+ }
1404
+ }
1405
+ }
1406
+ function triviaKindMask(labels, keep) {
1407
+ if (!labels) return void 0;
1408
+ let mask = 0;
1409
+ for (const name of keep) {
1410
+ const idx = labels.indexOf(name);
1411
+ if (idx >= 0) mask |= 1 << idx;
1412
+ }
1413
+ return mask;
1414
+ }
1415
+
1416
+ // src/combinators/trivia-skip.ts
1417
+ var NOOP_COMMIT = () => {
1418
+ };
1419
+ var fastTriviaCache = /* @__PURE__ */ new WeakMap();
1420
+ function needsDeferredTriviaCommit(ctx) {
1421
+ return ctx._triviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
1422
+ }
1423
+ function saveTriviaMark(ctx) {
1424
+ const m = saveCstMark(ctx);
1425
+ return { raw: m.raw, tlog: m.tlog, leaves: m.leaves, fields: m.fields, errors: m.errors, log: ctx._triviaLog ? ctx._triviaLog.length : 0 };
1426
+ }
1427
+ function rollbackTrivia(ctx, mark) {
1428
+ rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields, errors: mark.errors });
1429
+ if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
1430
+ }
1431
+ function saveLookaheadMark(ctx) {
1432
+ return { ...saveTriviaMark(ctx), probeBest: ctx._probe ? ctx._probe.best : null };
1433
+ }
1434
+ function rollbackLookahead(ctx, mark) {
1435
+ rollbackTrivia(ctx, mark);
1436
+ if (ctx._probe) ctx._probe.best = mark.probeBest;
1437
+ }
1438
+ function scanWithLabels(input, cur, ctx) {
1439
+ const triviaP = ctx.trivia;
1440
+ const spec = analyzeLabeledTrivia(triviaP);
1441
+ if (!spec) return { end: cur, commit: NOOP_COMMIT };
1442
+ const fast = tryFastLabeledScan(input, cur, triviaP);
1443
+ const { end, chunks } = fast ?? scanLabeledTriviaChunks(input, cur, spec);
1444
+ if (end === cur) return { end: cur, commit: NOOP_COMMIT };
1445
+ return {
1446
+ end,
1447
+ commit: () => recordTriviaChunks(ctx, chunks)
1448
+ };
1449
+ }
1450
+ function advanceTrivia(input, cur, ctx) {
1451
+ const triviaP = ctx.trivia;
1452
+ if (!triviaP) return cur;
1453
+ const fast = fastTriviaScanner(triviaP);
1454
+ if (fast) return fast(input, cur);
1455
+ if (ctx.triviaKindLabels) {
1456
+ const scan = scanWithLabels(input, cur, ctx);
1457
+ return scan.end;
1458
+ }
1459
+ const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
1460
+ return tr.ok && tr.span.end > cur ? tr.span.end : cur;
1461
+ }
1462
+ function scanTrivia(input, cur, ctx) {
1463
+ const triviaP = ctx.trivia;
1464
+ if (!triviaP) return { end: cur, commit: NOOP_COMMIT };
1465
+ const log = ctx._triviaLog;
1466
+ const captureTl = ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0);
1467
+ const fast = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
1468
+ if (fast && log === void 0 && !captureTl) {
1469
+ return { end: fast(input, cur), commit: NOOP_COMMIT };
1470
+ }
1471
+ if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) {
1472
+ return scanWithLabels(input, cur, ctx);
1473
+ }
1474
+ if (log !== void 0 || captureTl) {
1475
+ const tr2 = triviaP.parse(input, cur, {
1476
+ trackLines: log !== void 0 ? false : ctx.trackLines,
1477
+ state: ctx.state
1478
+ });
1479
+ if (!tr2.ok || tr2.span.end === cur) return { end: cur, commit: NOOP_COMMIT };
1480
+ const end = tr2.span.end;
1481
+ return {
1482
+ end,
1483
+ commit: () => {
1484
+ pushTriviaLogEntry(ctx, cur, end);
1485
+ if (captureTl) pushCstTriviaEntry(ctx, cur, end);
1486
+ }
1487
+ };
1488
+ }
1489
+ const tr = triviaP.parse(input, cur, { trackLines: ctx.trackLines, state: ctx.state });
1490
+ return { end: tr.ok ? tr.span.end : cur, commit: NOOP_COMMIT };
1491
+ }
1492
+ function consumeTrivia(input, cur, ctx) {
1493
+ if (!needsDeferredTriviaCommit(ctx)) return advanceTrivia(input, cur, ctx);
1494
+ const scan = scanTrivia(input, cur, ctx);
1495
+ scan.commit();
1496
+ return scan.end;
1497
+ }
1498
+ function fastTriviaScanner(trivia2) {
1499
+ const cached = fastTriviaCache.get(trivia2);
1500
+ if (cached !== void 0) return cached;
1501
+ const scanner = buildFastTriviaScanner(trivia2);
1502
+ fastTriviaCache.set(trivia2, scanner);
1503
+ return scanner;
1504
+ }
1505
+ function buildFastTriviaScanner(trivia2) {
1506
+ const core = trivia2._def.tag === "trivia" ? trivia2._def.parser : trivia2;
1507
+ const direct = regexTriviaScanner(core);
1508
+ if (direct) return direct;
1509
+ const repeat = core._def.tag === "oneOrMore" || core._def.tag === "many" && core._def.min >= 1 ? core._def.parser : null;
1510
+ if (!repeat) return null;
1511
+ const one = regexTriviaScanner(repeat);
1512
+ if (one) return loopScanner([one]);
1513
+ if (repeat._def.tag !== "choice") return null;
1514
+ const arms = repeat._def.parsers.map(regexTriviaScanner);
1515
+ if (arms.some((s) => s === null)) return null;
1516
+ return loopScanner(arms);
1517
+ }
1518
+ function loopScanner(arms) {
1519
+ return (input, cur) => {
1520
+ let pos = cur;
1521
+ scan: while (pos < input.length) {
1522
+ for (const arm of arms) {
1523
+ const end = arm(input, pos);
1524
+ if (end > pos) {
1525
+ pos = end;
1526
+ continue scan;
1527
+ }
1528
+ }
1529
+ break;
1530
+ }
1531
+ return pos;
1532
+ };
1533
+ }
1534
+ function regexTriviaScanner(parser2) {
1535
+ if (parser2._def.tag !== "regex" || parser2._def.flags) return null;
1536
+ const source = parser2._def.source;
1537
+ return classRunSource(source) ?? altStarSource(source) ?? (blockCommentSource(source) ? scanBlockComment : null);
1538
+ }
1539
+ function inRanges2(cp, ranges) {
1540
+ for (let i = 0; i < ranges.length; i++) {
1541
+ const r = ranges[i];
1542
+ if (cp >= r[0] && cp <= r[1]) return true;
1543
+ }
1544
+ return false;
1545
+ }
1546
+ function classScanner(classBody) {
1547
+ const ranges = parseClassRanges(classBody);
1548
+ if (!ranges) return null;
1549
+ return (input, cur) => {
1550
+ let pos = cur;
1551
+ while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1552
+ return pos;
1553
+ };
1554
+ }
1555
+ function lineCommentScanner(commentCode) {
1556
+ return (input, cur) => {
1557
+ if (input.charCodeAt(cur) !== commentCode) return cur;
1558
+ let pos = cur + 1;
1559
+ while (pos < input.length) {
1560
+ const cc = input.charCodeAt(pos);
1561
+ if (cc === 10 || cc === 13) break;
1562
+ pos++;
1563
+ }
1564
+ return pos;
1565
+ };
1566
+ }
1567
+ function classRunSource(source) {
1568
+ const m = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]$/.exec(source);
1569
+ return m ? classScanner(m[1]) : null;
1570
+ }
1571
+ function classifyTriviaArm(arm) {
1572
+ const cls = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]?$/.exec(arm);
1573
+ if (cls) {
1574
+ const ranges = parseClassRanges(cls[1]);
1575
+ return ranges ? { kind: "class", ranges } : null;
1576
+ }
1577
+ const lc = /^(\\?.)\[\^\\n\\r\]\*$/.exec(arm);
1578
+ if (lc) {
1579
+ const marker = lc[1];
1580
+ return { kind: "comment", code: (marker.length === 2 ? marker[1] : marker[0]).charCodeAt(0) };
1581
+ }
1582
+ return null;
1583
+ }
1584
+ function armScanner(arm) {
1585
+ if (arm.kind === "comment") return lineCommentScanner(arm.code);
1586
+ const ranges = arm.ranges;
1587
+ return (input, cur) => {
1588
+ let pos = cur;
1589
+ while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1590
+ return pos;
1591
+ };
1592
+ }
1593
+ function fusedTriviaScanner(ranges, commentCodes) {
1594
+ const c0 = commentCodes[0];
1595
+ const single = commentCodes.length === 1;
1596
+ return (input, cur) => {
1597
+ let pos = cur;
1598
+ const len = input.length;
1599
+ for (; ; ) {
1600
+ const c = input.charCodeAt(pos);
1601
+ if (pos < len && inRanges2(c, ranges)) {
1602
+ pos++;
1603
+ continue;
1604
+ }
1605
+ if (single ? c === c0 : commentCodes.includes(c)) {
1606
+ pos++;
1607
+ while (pos < len) {
1608
+ const cc = input.charCodeAt(pos);
1609
+ if (cc === 10 || cc === 13) break;
1610
+ pos++;
1611
+ }
1612
+ continue;
1613
+ }
1614
+ break;
1615
+ }
1616
+ return pos;
1617
+ };
1618
+ }
1619
+ function splitTopLevelAlts(body) {
1620
+ const arms = [];
1621
+ let inClass = false;
1622
+ let start = 0;
1623
+ for (let i = 0; i < body.length; i++) {
1624
+ const c = body[i];
1625
+ if (c === "\\") {
1626
+ i++;
1627
+ continue;
1628
+ }
1629
+ if (inClass) {
1630
+ if (c === "]") inClass = false;
1631
+ continue;
1632
+ }
1633
+ if (c === "[") inClass = true;
1634
+ else if (c === "(") return null;
1635
+ else if (c === "|") {
1636
+ arms.push(body.slice(start, i));
1637
+ start = i + 1;
1638
+ }
1639
+ }
1640
+ arms.push(body.slice(start));
1641
+ return arms;
1642
+ }
1643
+ function altStarSource(source) {
1644
+ const m = /^\(\?:(.*)\)[*+]$/.exec(source);
1645
+ if (!m) return null;
1646
+ const armSrcs = splitTopLevelAlts(m[1]);
1647
+ if (!armSrcs || armSrcs.length < 2) return null;
1648
+ const arms = [];
1649
+ for (const src of armSrcs) {
1650
+ const arm = classifyTriviaArm(src);
1651
+ if (!arm) return null;
1652
+ arms.push(arm);
1653
+ }
1654
+ const ranges = [];
1655
+ const commentCodes = [];
1656
+ for (const arm of arms) {
1657
+ if (arm.kind === "class") ranges.push(...arm.ranges);
1658
+ else commentCodes.push(arm.code);
1659
+ }
1660
+ if (commentCodes.some((code) => inRanges2(code, ranges))) {
1661
+ return loopScanner(arms.map(armScanner));
1662
+ }
1663
+ if (commentCodes.length === 0) return armScanner({ kind: "class", ranges });
1664
+ return fusedTriviaScanner(ranges, commentCodes);
1665
+ }
1666
+ function blockCommentSource(source) {
1667
+ return source === "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/" || source === "\\/\\*[^]*?\\*\\/";
1668
+ }
1669
+ function scanBlockComment(input, cur) {
1670
+ if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
1671
+ const close = input.indexOf("*/", cur + 2);
1672
+ return close === -1 ? cur : close + 2;
1673
+ }
1674
+
1675
+ // src/combinators/sequence.ts
1676
+ function sequence(...parsers) {
1677
+ const meta = {
1678
+ // Union through the nullable prefix — a leading optional()/many() lets a later
1679
+ // term's first char start the sequence. Just `parsers[0]` under-approximates.
1680
+ firstSet: sequenceFirstSet(parsers),
1681
+ canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
1682
+ isTrivia: false
1683
+ };
1684
+ const def = { tag: "sequence", parsers };
1685
+ let followSentinels;
1686
+ function parseTolerant(input, pos, ctx) {
1687
+ followSentinels ??= parsers.map((_, i) => {
1688
+ const fs = parsers.slice(i + 1).reduce(
1689
+ (acc, p) => union(acc, firstSetOf(p)),
1690
+ { kind: "empty" }
1691
+ );
1692
+ return firstSetSentinel(fs);
1693
+ });
1694
+ const values = def.valueUnused ? void 0 : [];
1695
+ let cur = pos;
1696
+ const inheritedSync = ctx._sync;
1697
+ try {
1698
+ for (let i = 0; i < parsers.length; i++) {
1699
+ ctx._sync = followSentinels[i] ?? inheritedSync;
1700
+ if (ctx.trivia && i > 0) {
1701
+ const mark = saveTriviaMark(ctx);
1702
+ let scanEnd;
1703
+ if (needsDeferredTriviaCommit(ctx)) {
1704
+ const scan = scanTrivia(input, cur, ctx);
1705
+ scan.commit();
1706
+ scanEnd = scan.end;
1707
+ } else {
1708
+ scanEnd = advanceTrivia(input, cur, ctx);
1709
+ }
1710
+ const result2 = parsers[i].parse(input, scanEnd, ctx);
1711
+ if (!result2.ok) return result2;
1712
+ if (result2.span.end > scanEnd) cur = result2.span.end;
1713
+ else rollbackTrivia(ctx, mark);
1714
+ if (values !== void 0) values.push(result2.value);
1715
+ continue;
1716
+ }
1717
+ const result = parsers[i].parse(input, cur, ctx);
1718
+ if (!result.ok) return result;
1719
+ if (values !== void 0) values.push(result.value);
1720
+ cur = result.span.end;
1721
+ }
1722
+ } finally {
1723
+ ctx._sync = inheritedSync;
1724
+ }
1725
+ return {
1726
+ ok: true,
1727
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1728
+ value: values ?? void 0,
1729
+ span: { start: pos, end: cur }
1730
+ };
1731
+ }
1732
+ return {
1733
+ _tag: "sequence",
1734
+ _meta: meta,
1735
+ _def: def,
1736
+ parse(input, pos, ctx) {
1737
+ if (ctx._tolerant) return parseTolerant(input, pos, ctx);
1738
+ const values = def.valueUnused ? void 0 : [];
1739
+ let cur = pos;
1740
+ for (let i = 0; i < parsers.length; i++) {
1741
+ if (ctx.trivia && i > 0) {
1742
+ let scanEnd;
1743
+ let mark = saveTriviaMark(ctx);
1744
+ if (needsDeferredTriviaCommit(ctx)) {
1745
+ const scan = scanTrivia(input, cur, ctx);
1746
+ scan.commit();
1747
+ scanEnd = scan.end;
1748
+ } else {
1749
+ scanEnd = advanceTrivia(input, cur, ctx);
1750
+ }
1751
+ const result2 = parsers[i].parse(input, scanEnd, ctx);
1752
+ if (!result2.ok) return result2;
1753
+ if (result2.span.end > scanEnd) {
1754
+ cur = result2.span.end;
1755
+ } else {
1756
+ rollbackTrivia(ctx, mark);
1757
+ }
1758
+ if (values !== void 0) values.push(result2.value);
1759
+ continue;
1760
+ }
1761
+ const result = parsers[i].parse(input, cur, ctx);
1762
+ if (!result.ok) return result;
1763
+ if (values !== void 0) values.push(result.value);
1764
+ cur = result.span.end;
1765
+ }
1766
+ return {
1767
+ ok: true,
1768
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1769
+ value: values ?? void 0,
1770
+ span: { start: pos, end: cur }
1771
+ };
1772
+ }
1773
+ };
1774
+ }
1775
+
1776
+ // src/combinators/repeat.ts
1777
+ function repItem(combinator, input, cur, ctx, guardable) {
1778
+ const mark = saveTriviaMark(ctx);
1779
+ let pos = cur;
1780
+ if (ctx.trivia) {
1781
+ if (needsDeferredTriviaCommit(ctx)) {
1782
+ const scan = scanTrivia(input, cur, ctx);
1783
+ scan.commit();
1784
+ pos = scan.end;
1785
+ } else {
1786
+ pos = advanceTrivia(input, cur, ctx);
1787
+ }
1788
+ }
1789
+ if (pos >= input.length) {
1790
+ rollbackTrivia(ctx, mark);
1791
+ return "stop";
1792
+ }
1793
+ if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
1794
+ rollbackTrivia(ctx, mark);
1795
+ return "stop";
1796
+ }
1797
+ const result = combinator.parse(input, pos, ctx);
1798
+ if (!result.ok) {
1799
+ rollbackTrivia(ctx, mark);
1800
+ return { fail: result, failPos: pos };
1801
+ }
1802
+ if (result.span.end === pos) {
1803
+ rollbackTrivia(ctx, mark);
1804
+ return "stop";
1805
+ }
1806
+ return { value: result.value, end: result.span.end };
1807
+ }
1808
+ function resolveBounds(what, opts) {
1809
+ const min = opts.min ?? 0;
1810
+ const max = opts.max ?? Infinity;
1811
+ const bad = (msg) => {
1812
+ throw new RangeError(`parseman: ${what} ${msg}`);
1813
+ };
1814
+ if (!Number.isInteger(min) || min < 0) bad(`min must be a non-negative integer (got ${String(opts.min)})`);
1815
+ if (max !== Infinity && (!Number.isInteger(max) || max < 1)) bad(`max must be a positive integer (got ${String(opts.max)})`);
1816
+ if (max < min) bad(`max (${max}) is less than min (${min}) \u2014 the combinator could never succeed`);
1817
+ return { min, max };
1818
+ }
1819
+ function many(combinator, opts = {}) {
1820
+ const { min, max } = resolveBounds("many()", opts);
1821
+ if (min >= 1) return atLeast(combinator, min, max);
1822
+ const meta = {
1823
+ firstSet: combinator._meta.firstSet,
1824
+ canMatchNewline: combinator._meta.canMatchNewline,
1825
+ isTrivia: false
1826
+ };
1827
+ const def = { tag: "many", parser: combinator, min: 0, ...max === Infinity ? {} : { max } };
1828
+ let expected;
1829
+ const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
1830
+ return {
1831
+ _tag: "many",
1832
+ _meta: meta,
1833
+ _def: def,
1834
+ parse(input, pos, ctx) {
1835
+ const values = def.valueUnused ? void 0 : [];
1836
+ let cur = pos;
1837
+ let count = 0;
1838
+ while (cur < input.length) {
1839
+ if (count >= max) break;
1840
+ const item = repItem(combinator, input, cur, ctx, guardable);
1841
+ if (item === "stop") break;
1842
+ if ("fail" in item) {
1843
+ const sync = ctx._tolerant ? ctx._sync : void 0;
1844
+ if (sync === void 0) break;
1845
+ if (matchesAt(sync, input, item.failPos, ctx)) break;
1846
+ expected ??= deriveExpected(combinator);
1847
+ const { error, end } = recoverScan(input, item.failPos, ctx, sync, expected);
1848
+ if (values !== void 0) values.push(error);
1849
+ captureError(ctx, error);
1850
+ count++;
1851
+ cur = end;
1852
+ continue;
1853
+ }
1854
+ if (values !== void 0) values.push(item.value);
1855
+ count++;
1856
+ cur = item.end;
1857
+ }
1858
+ return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
1859
+ }
1860
+ };
1861
+ }
1862
+ function oneOrMore(combinator, opts = {}) {
1863
+ return many(combinator, { ...opts, min: opts.min ?? 1 });
1864
+ }
1865
+ function atLeast(combinator, min, max) {
1866
+ const meta = {
1867
+ firstSet: combinator._meta.firstSet,
1868
+ canMatchNewline: combinator._meta.canMatchNewline,
1869
+ isTrivia: false
1870
+ };
1871
+ const def = { tag: "oneOrMore", parser: combinator, min, ...max === Infinity ? {} : { max } };
1872
+ let expected;
1873
+ const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
1874
+ return {
1875
+ _tag: "oneOrMore",
1876
+ _meta: meta,
1877
+ _def: def,
1878
+ parse(input, pos, ctx) {
1879
+ const first = combinator.parse(input, pos, ctx);
1880
+ if (!first.ok) return first;
1881
+ const values = def.valueUnused ? void 0 : [first.value];
1882
+ let cur = first.span.end;
1883
+ let count = 1;
1884
+ while (count < min) {
1885
+ const item = repItem(combinator, input, cur, ctx, guardable);
1886
+ if (item === "stop" || "fail" in item) {
1887
+ expected ??= deriveExpected(combinator);
1888
+ return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: cur, end: cur } };
1889
+ }
1890
+ if (values !== void 0) values.push(item.value);
1891
+ cur = item.end;
1892
+ count++;
1893
+ }
1894
+ while (cur < input.length) {
1895
+ if (count >= max) break;
1896
+ const item = repItem(combinator, input, cur, ctx, guardable);
1897
+ if (item === "stop") break;
1898
+ if ("fail" in item) {
1899
+ const sync = ctx._tolerant ? ctx._sync : void 0;
1900
+ if (sync === void 0) break;
1901
+ if (matchesAt(sync, input, item.failPos, ctx)) break;
1902
+ expected ??= deriveExpected(combinator);
1903
+ const { error, end } = recoverScan(input, item.failPos, ctx, sync, expected);
1904
+ if (values !== void 0) values.push(error);
1905
+ captureError(ctx, error);
1906
+ count++;
1907
+ cur = end;
1908
+ continue;
1909
+ }
1910
+ if (values !== void 0) values.push(item.value);
1911
+ count++;
1912
+ cur = item.end;
1913
+ }
1914
+ return { ok: true, value: values ?? void 0, span: { start: pos, end: cur } };
1915
+ }
1916
+ };
1917
+ }
1918
+ function optional(combinator) {
1919
+ const meta = {
1920
+ firstSet: combinator._meta.firstSet,
1921
+ canMatchNewline: combinator._meta.canMatchNewline,
1922
+ isTrivia: false
1923
+ };
1924
+ const firstSetSkippable = !matchesEmpty(combinator);
1925
+ return {
1926
+ _tag: "optional",
1927
+ _meta: meta,
1928
+ _def: { tag: "optional", parser: combinator },
1929
+ parse(input, pos, ctx) {
1930
+ if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) {
1931
+ return { ok: true, value: null, span: { start: pos, end: pos } };
1932
+ }
1933
+ const mark = saveTriviaMark(ctx);
1934
+ const result = combinator.parse(input, pos, ctx);
1935
+ if (result.ok) return result;
1936
+ rollbackTrivia(ctx, mark);
1937
+ return { ok: true, value: null, span: { start: pos, end: pos } };
1938
+ }
1939
+ };
1940
+ }
1941
+ function sepBy(combinator, separator, opts = {}) {
1942
+ const { min, max } = resolveBounds("sepBy()", opts);
1943
+ const trailing = opts.trailing ?? "forbid";
1944
+ const meta = {
1945
+ firstSet: combinator._meta.firstSet,
1946
+ canMatchNewline: combinator._meta.canMatchNewline || separator._meta.canMatchNewline,
1947
+ isTrivia: false
1948
+ };
1949
+ let expected;
1950
+ const failAt2 = (at) => {
1951
+ expected ??= deriveExpected(combinator);
1952
+ return { ok: false, expected: expected.length > 0 ? expected : [combinator._tag], span: { start: at, end: at } };
1953
+ };
1954
+ return {
1955
+ _tag: "sepBy",
1956
+ _meta: meta,
1957
+ _def: {
1958
+ tag: "sepBy",
1959
+ parser: combinator,
1960
+ separator,
1961
+ min,
1962
+ ...max === Infinity ? {} : { max },
1963
+ ...trailing === "forbid" ? {} : { trailing }
1964
+ },
1965
+ parse(input, pos, ctx) {
1966
+ const first = combinator.parse(input, pos, ctx);
1967
+ const values = [];
1968
+ let cur;
1969
+ if (first.ok) {
1970
+ values.push(first.value);
1971
+ cur = first.span.end;
1972
+ } else {
1973
+ const term = ctx._tolerant ? ctx._sync : void 0;
1974
+ if (term === void 0 || matchesAt(term, input, pos, ctx)) {
1975
+ if (min >= 1) return failAt2(pos);
1976
+ return { ok: true, value: [], span: { start: pos, end: pos } };
1977
+ }
1978
+ expected ??= deriveExpected(combinator);
1979
+ const rec = recoverScan(input, pos, ctx, orSentinel(separator, term), expected);
1980
+ values.push(rec.error);
1981
+ captureError(ctx, rec.error);
1982
+ cur = rec.end;
1983
+ }
1984
+ while (cur < input.length) {
1985
+ if (values.length >= max) break;
1986
+ const loopMark = saveTriviaMark(ctx);
1987
+ let sepPos = cur;
1988
+ if (ctx.trivia) {
1989
+ if (needsDeferredTriviaCommit(ctx)) {
1990
+ const scan = scanTrivia(input, cur, ctx);
1991
+ scan.commit();
1992
+ sepPos = scan.end;
1993
+ } else {
1994
+ sepPos = advanceTrivia(input, cur, ctx);
1995
+ }
1996
+ }
1997
+ const sep = separator.parse(input, sepPos, ctx);
1998
+ if (!sep.ok) {
1999
+ rollbackTrivia(ctx, loopMark);
2000
+ break;
2001
+ }
2002
+ const sepMark = trailing === "forbid" ? void 0 : saveTriviaMark(ctx);
2003
+ let nextPos = sep.span.end;
2004
+ if (ctx.trivia) {
2005
+ if (needsDeferredTriviaCommit(ctx)) {
2006
+ const scan = scanTrivia(input, sep.span.end, ctx);
2007
+ scan.commit();
2008
+ nextPos = scan.end;
2009
+ } else {
2010
+ nextPos = advanceTrivia(input, sep.span.end, ctx);
2011
+ }
2012
+ }
2013
+ const next = combinator.parse(input, nextPos, ctx);
2014
+ if (!next.ok) {
2015
+ const term = ctx._tolerant ? ctx._sync : void 0;
2016
+ if (term !== void 0 && !matchesAt(term, input, nextPos, ctx)) {
2017
+ expected ??= deriveExpected(combinator);
2018
+ const rec = recoverScan(input, nextPos, ctx, orSentinel(separator, term), expected);
2019
+ values.push(rec.error);
2020
+ captureError(ctx, rec.error);
2021
+ cur = rec.end;
2022
+ continue;
2023
+ }
2024
+ if (sepMark !== void 0) {
2025
+ rollbackTrivia(ctx, sepMark);
2026
+ cur = sep.span.end;
2027
+ break;
2028
+ }
2029
+ rollbackTrivia(ctx, loopMark);
2030
+ break;
2031
+ }
2032
+ values.push(next.value);
2033
+ cur = next.span.end;
2034
+ }
2035
+ if (values.length < min) return failAt2(cur);
2036
+ return { ok: true, value: values, span: { start: pos, end: cur } };
2037
+ }
2038
+ };
2039
+ }
2040
+
2041
+ // src/combinators/map.ts
2042
+ function transform(combinator, fn) {
2043
+ return {
2044
+ _tag: "transform",
2045
+ _meta: combinator._meta,
2046
+ _def: { tag: "transform", parser: combinator, fn },
2047
+ parse(input, pos, ctx) {
2048
+ const result = combinator.parse(input, pos, ctx);
2049
+ if (!result.ok) return result;
2050
+ return { ok: true, value: fn(result.value, result.span), span: result.span };
2051
+ }
2052
+ };
2053
+ }
2054
+ function skip(main, skipped) {
2055
+ return {
2056
+ _tag: "skip",
2057
+ _meta: main._meta,
2058
+ _def: { tag: "skip", main, skipped },
2059
+ parse(input, pos, ctx) {
2060
+ const result = main.parse(input, pos, ctx);
2061
+ if (!result.ok) return result;
2062
+ const s = skipped.parse(input, result.span.end, ctx);
2063
+ if (!s.ok) return result;
2064
+ return { ok: true, value: result.value, span: { start: result.span.start, end: s.span.end } };
2065
+ }
2066
+ };
2067
+ }
2068
+ function trivia(combinator) {
2069
+ const kindLabels = analyzeLabeledTrivia(combinator)?.labels;
2070
+ return {
2071
+ _tag: combinator._tag,
2072
+ _meta: {
2073
+ ...combinator._meta,
2074
+ isTrivia: true,
2075
+ ...kindLabels ? { triviaKindLabels: kindLabels } : {}
2076
+ },
2077
+ _def: { tag: "trivia", parser: combinator },
2078
+ parse: combinator.parse.bind(combinator)
2079
+ };
2080
+ }
2081
+ function label(name, combinator) {
2082
+ return {
2083
+ _tag: combinator._tag,
2084
+ _meta: combinator._meta,
2085
+ _def: { tag: "label", label: name, parser: combinator },
2086
+ parse(input, pos, ctx) {
2087
+ const result = combinator.parse(input, pos, ctx);
2088
+ if (!result.ok) return { ok: false, expected: [name], span: result.span };
2089
+ return result;
2090
+ }
2091
+ };
2092
+ }
2093
+ function field(name, combinator) {
2094
+ return {
2095
+ _tag: combinator._tag,
2096
+ _meta: combinator._meta,
2097
+ _def: { tag: "field", name, parser: combinator },
2098
+ parse(input, pos, ctx) {
2099
+ const result = combinator.parse(input, pos, ctx);
2100
+ if (!result.ok) return result;
2101
+ ctx._fields?.push({ name, value: result.value, span: result.span });
2102
+ return result;
2103
+ }
2104
+ };
2105
+ }
2106
+
2107
+ // src/combinators/scanTo.ts
2108
+ function resolveScanSkip(explicitSkip, raw, ctx) {
2109
+ if (raw) return [];
2110
+ const trivia2 = ctx.trivia;
2111
+ const ambient = ctx.scanSkip;
2112
+ if (!trivia2 && !ambient) return explicitSkip;
2113
+ const out = [];
2114
+ if (trivia2) out.push(trivia2);
2115
+ if (ambient) out.push(...ambient);
2116
+ out.push(...explicitSkip);
2117
+ return out;
2118
+ }
2119
+ function scanTo(sentinel, { skip: skip2, raw = false, orEOF = false } = {}) {
2120
+ const meta = {
2121
+ firstSet: any(),
2122
+ canMatchNewline: true,
2123
+ isTrivia: false
2124
+ };
2125
+ const explicitSkip = skip2 ?? [];
2126
+ return {
2127
+ _tag: "scanTo",
2128
+ _meta: meta,
2129
+ _def: { tag: "scanTo", sentinel, skip: explicitSkip, raw, orEOF },
2130
+ parse(input, pos, ctx) {
2131
+ let cur = pos;
2132
+ const skip3 = resolveScanSkip(explicitSkip, raw, ctx);
2133
+ const probeCtx = {
2134
+ trackLines: ctx.trackLines,
2135
+ state: ctx.state,
2136
+ ...ctx._errors !== void 0 ? { _errors: ctx._errors } : {}
2137
+ };
2138
+ const emit = (end) => {
2139
+ if (end > pos && cstCaptureActive(ctx)) {
2140
+ const leaf2 = { _tag: "leaf", value: input.slice(pos, end), span: { start: pos, end } };
2141
+ pushCstLeaf(ctx, leaf2);
2142
+ }
2143
+ };
2144
+ while (cur < input.length) {
2145
+ const s = sentinel.parse(input, cur, probeCtx);
2146
+ if (s.ok) {
2147
+ emit(cur);
2148
+ return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
2149
+ }
2150
+ let advanced = false;
2151
+ for (const skipper of skip3) {
2152
+ const r = skipper.parse(input, cur, probeCtx);
2153
+ if (r.ok && r.span.end > cur) {
2154
+ cur = r.span.end;
2155
+ advanced = true;
2156
+ break;
2157
+ }
2158
+ }
2159
+ if (!advanced) cur++;
2160
+ }
2161
+ if (orEOF) {
2162
+ emit(cur);
2163
+ return { ok: true, value: input.slice(pos, cur), span: { start: pos, end: cur } };
2164
+ }
2165
+ const sentDef = sentinel._def;
2166
+ const expected = sentDef.tag === "literal" ? [JSON.stringify(sentDef.value)] : ["sentinel"];
2167
+ return { ok: false, expected, span: { start: pos, end: cur } };
2168
+ }
2169
+ };
2170
+ }
2171
+
2172
+ // src/compiler/scannable-run.ts
2173
+ var META = new Set("()[]{}*+?|^$.".split(""));
2174
+
2175
+ // src/compiler/trivia-fast-path.ts
2176
+ var CAP_RECORD = [
2177
+ ` if (_cap && _e > _pos) {`,
2178
+ ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
2179
+ ` if (_ctx._cstTriviaLog !== undefined && _ctx.captureTrivia) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
2180
+ ` }`
2181
+ ].join("\n");
2182
+
2183
+ // src/compiler/build-arity.ts
2184
+ function cstOutputHost(build) {
2185
+ return build?._parsemanCstOutput === true;
2186
+ }
2187
+ var PARAM_LIST_RE = (
2188
+ // (params) => ... | function name?(params) ... | single-ident arrow `x => ...`
2189
+ /^(?:function\b[^(]*\(([^)]*)\)|\(([^)]*)\)\s*=>|([A-Za-z_$][\w$]*)\s*=>)/
2190
+ );
2191
+ var CONFIRMABLE_PARAM_RE = /^[A-Za-z_$][\w$]*\s*\??\s*(?::[^,=]+)?$/;
2192
+ function confirmedBuildArity(src) {
2193
+ const s = src.trim();
2194
+ const m = PARAM_LIST_RE.exec(s);
2195
+ if (!m) return null;
2196
+ if (m[3] !== void 0) return 1;
2197
+ const inner = (m[1] ?? m[2] ?? "").trim();
2198
+ if (inner === "") return 0;
2199
+ const parts = inner.split(",");
2200
+ for (const part of parts) {
2201
+ if (!CONFIRMABLE_PARAM_RE.test(part.trim())) return null;
2202
+ }
2203
+ if (/\barguments\b/.test(s)) return null;
2204
+ return parts.length;
2205
+ }
2206
+ function buildReadsTrivia(def) {
2207
+ if (!def.build) return true;
2208
+ const src = def.buildSrc ?? def.build.toString();
2209
+ const arity = confirmedBuildArity(src);
2210
+ if (arity === null) return true;
2211
+ return arity >= 5;
2212
+ }
2213
+ function buildReadsState(def) {
2214
+ if (!def.build) return true;
2215
+ const src = def.buildSrc ?? def.build.toString();
2216
+ const arity = confirmedBuildArity(src);
2217
+ if (arity === null) return true;
2218
+ return arity >= 6;
2219
+ }
2220
+
2221
+ // src/compiler/fields.ts
2222
+ function buildReadsFields(def) {
2223
+ if (!def.build) return true;
2224
+ const src = def.buildSrc ?? def.build.toString();
2225
+ const arity = confirmedBuildArity(src);
2226
+ if (arity === null) return true;
2227
+ return arity >= 2;
2228
+ }
2229
+ function parserHasOwnFields(p, seen = /* @__PURE__ */ new Set()) {
2230
+ if (seen.has(p)) return false;
2231
+ seen.add(p);
2232
+ const d = p._def;
2233
+ switch (d.tag) {
2234
+ case "field":
2235
+ return true;
2236
+ case "node":
2237
+ return false;
2238
+ case "lazy": {
2239
+ try {
2240
+ return parserHasOwnFields(d.thunk(), seen);
2241
+ } catch {
2242
+ return false;
2243
+ }
2244
+ }
2245
+ case "sequence":
2246
+ case "choice":
2247
+ return d.parsers.some((x) => parserHasOwnFields(x, seen));
2248
+ case "sepBy":
2249
+ return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.separator, seen);
2250
+ case "skip":
2251
+ return parserHasOwnFields(d.main, seen) || parserHasOwnFields(d.skipped, seen);
2252
+ case "grammar":
2253
+ return parserHasOwnFields(d.parser, seen) || (d.triviaParser ? parserHasOwnFields(d.triviaParser, seen) : false);
2254
+ case "scanTo":
2255
+ return parserHasOwnFields(d.sentinel, seen) || d.skip.some((x) => parserHasOwnFields(x, seen));
2256
+ case "recover":
2257
+ return parserHasOwnFields(d.parser, seen) || parserHasOwnFields(d.sentinel, seen);
2258
+ case "many":
2259
+ case "oneOrMore":
2260
+ case "optional":
2261
+ case "attempt":
2262
+ case "transform":
2263
+ case "trivia":
2264
+ case "token":
2265
+ case "leaf":
2266
+ case "label":
2267
+ case "expect":
2268
+ case "withCtx":
2269
+ case "not":
2270
+ case "peek":
2271
+ return parserHasOwnFields(d.parser, seen);
2272
+ default:
2273
+ return false;
2274
+ }
2275
+ }
2276
+ function buildFieldMap(captures) {
2277
+ if (!captures?.length) return void 0;
2278
+ const out = {};
2279
+ for (const cap of captures) {
2280
+ const entry = { value: cap.value, span: cap.span };
2281
+ const current = out[cap.name];
2282
+ if (current === void 0) out[cap.name] = entry;
2283
+ else if (Array.isArray(current)) current.push(entry);
2284
+ else out[cap.name] = [current, entry];
2285
+ }
2286
+ return out;
2287
+ }
2288
+
2289
+ // src/combinators/case-fold.ts
2290
+ function canonical(ch) {
2291
+ const u = ch.toUpperCase();
2292
+ if (u.length !== 1) return ch;
2293
+ if (ch.codePointAt(0) >= 128 && u.codePointAt(0) < 128) return ch;
2294
+ return u;
2295
+ }
2296
+ var foldIndex = null;
2297
+ function buildFoldIndex() {
2298
+ const byCanonical = /* @__PURE__ */ new Map();
2299
+ for (let cp = 0; cp < 65536; cp++) {
2300
+ if (cp >= 55296 && cp <= 57343) continue;
2301
+ const key = canonical(String.fromCharCode(cp));
2302
+ const bucket = byCanonical.get(key);
2303
+ if (bucket) bucket.push(cp);
2304
+ else byCanonical.set(key, [cp]);
2305
+ }
2306
+ const index = /* @__PURE__ */ new Map();
2307
+ for (const members of byCanonical.values()) {
2308
+ if (members.length < 2) continue;
2309
+ for (const cp of members) index.set(cp, members);
2310
+ }
2311
+ return index;
2312
+ }
2313
+ function caseFoldVariants(cp) {
2314
+ if (cp < 128) {
2315
+ if (cp >= 65 && cp <= 90) return [cp, cp + 32];
2316
+ if (cp >= 97 && cp <= 122) return [cp, cp - 32];
2317
+ return [cp];
2318
+ }
2319
+ if (cp > 65535) return [cp];
2320
+ foldIndex ??= buildFoldIndex();
2321
+ return foldIndex.get(cp) ?? [cp];
2322
+ }
2323
+
2324
+ // src/combinators/keywords.ts
2325
+ function escapeRe(s) {
2326
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2327
+ }
2328
+ function keywords(words, opts = {}) {
2329
+ const sorted = [...new Set(words)].sort((a, b) => b.length - a.length);
2330
+ const alt = sorted.map(escapeRe).join("|");
2331
+ const boundary = opts.boundary ? `(?![${opts.boundary}])` : "";
2332
+ const flags = opts.caseInsensitive ? "iy" : "uy";
2333
+ const re = new RegExp(`(?:${alt})${boundary}`, flags);
2334
+ let firstSet = empty();
2335
+ for (const w of sorted) {
2336
+ if (w.length === 0) continue;
2337
+ const cp = w.codePointAt(0);
2338
+ firstSet = union(firstSet, fromChar(cp));
2339
+ if (opts.caseInsensitive) {
2340
+ for (const v of caseFoldVariants(cp)) firstSet = union(firstSet, fromChar(v));
2341
+ }
2342
+ }
2343
+ const meta = { firstSet, canMatchNewline: false, isTrivia: false };
2344
+ return {
2345
+ _tag: "keywords",
2346
+ _meta: meta,
2347
+ _def: { tag: "keywords", words: sorted, caseInsensitive: opts.caseInsensitive ?? false, boundary: opts.boundary },
2348
+ parse(input, pos, ctx) {
2349
+ re.lastIndex = pos;
2350
+ const m = re.exec(input);
2351
+ if (m === null || m.index !== pos) {
2352
+ return failAt(ctx, ["keyword"], pos);
2353
+ }
2354
+ const value = m[0];
2355
+ const span = { start: pos, end: pos + value.length };
2356
+ if (cstCaptureActive(ctx)) pushCstLeaf(ctx, { _tag: "leaf", value, span });
2357
+ return { ok: true, value, span };
2358
+ }
2359
+ };
2360
+ }
2361
+
2362
+ // src/combinators/attempt.ts
2363
+ function attempt(parser2) {
2364
+ const guardable = parser2._meta.firstSet.kind !== "any" && !matchesEmpty(parser2);
2365
+ let failExpected;
2366
+ return {
2367
+ _tag: "attempt",
2368
+ _meta: parser2._meta,
2369
+ _def: { tag: "attempt", parser: parser2 },
2370
+ parse(input, pos, ctx) {
2371
+ if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(parser2, input, pos)) {
2372
+ if (failExpected === void 0) {
2373
+ const e = deriveExpected(parser2);
2374
+ failExpected = e.length > 0 ? e : [parser2._tag];
2375
+ }
2376
+ return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
2377
+ }
2378
+ const mark = saveCstMark(ctx);
2379
+ const log = ctx._triviaLog?.length;
2380
+ const result = parser2.parse(input, pos, ctx);
2381
+ if (result.ok) return result;
2382
+ rollbackCstCapture(ctx, mark);
2383
+ if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
2384
+ return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
2385
+ }
2386
+ };
2387
+ }
2388
+
2389
+ // src/combinators/not.ts
2390
+ function not(combinator) {
2391
+ const meta = {
2392
+ firstSet: any(),
2393
+ // we don't know what NOT matches
2394
+ canMatchNewline: false,
2395
+ isTrivia: false
2396
+ };
2397
+ return {
2398
+ _tag: "not",
2399
+ _meta: meta,
2400
+ _def: { tag: "not", parser: combinator },
2401
+ parse(input, pos, ctx) {
2402
+ const mark = saveLookaheadMark(ctx);
2403
+ const result = combinator.parse(input, pos, ctx);
2404
+ rollbackLookahead(ctx, mark);
2405
+ if (result.ok) {
2406
+ return { ok: false, expected: [`not(${combinator._tag})`], span: { start: pos, end: pos } };
2407
+ }
2408
+ return { ok: true, value: null, span: { start: pos, end: pos } };
2409
+ }
2410
+ };
2411
+ }
2412
+
2413
+ // src/combinators/peek.ts
2414
+ function peek(combinator) {
2415
+ const meta = {
2416
+ // A nullable body imposes no first-char constraint — `any()`, not its set.
2417
+ firstSet: matchesEmpty(combinator) ? any() : combinator._meta.firstSet,
2418
+ canMatchNewline: false,
2419
+ isTrivia: false
2420
+ };
2421
+ return {
2422
+ _tag: "peek",
2423
+ _meta: meta,
2424
+ _def: { tag: "peek", parser: combinator },
2425
+ parse(input, pos, ctx) {
2426
+ const mark = saveLookaheadMark(ctx);
2427
+ const result = combinator.parse(input, pos, ctx);
2428
+ rollbackLookahead(ctx, mark);
2429
+ if (result.ok) return { ok: true, value: null, span: { start: pos, end: pos } };
2430
+ return { ok: false, expected: [`peek(${combinator._tag})`], span: { start: pos, end: pos } };
2431
+ }
2432
+ };
2433
+ }
2434
+
2435
+ // src/combinators/node.ts
2436
+ function unwrapChild(child) {
2437
+ return child !== null && typeof child === "object" && child._tag === "leaf" ? child.value : child;
2438
+ }
2439
+ function isCstChild(value) {
2440
+ return typeof value === "object" && value !== null && (value._tag === "node" || value._tag === "leaf" || value._tag === "parseError");
2441
+ }
2442
+ function missingInferredType() {
2443
+ throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
2444
+ }
2445
+ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2446
+ const hasExplicitType = typeof typeOrCombinator === "string";
2447
+ const type = hasExplicitType ? typeOrCombinator : void 0;
2448
+ const combinator = hasExplicitType ? combinatorOrBuild : typeOrCombinator;
2449
+ const build = hasExplicitType ? buildOrOpts : combinatorOrBuild;
2450
+ const opts = hasExplicitType ? maybeOpts : buildOrOpts;
2451
+ const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
2452
+ const meta = {
2453
+ firstSet: combinator._meta.firstSet,
2454
+ canMatchNewline: combinator._meta.canMatchNewline,
2455
+ isTrivia: false
2456
+ };
2457
+ const unwrap = opts?.unwrap === true;
2458
+ const collapse = opts?.collapse === true;
2459
+ const captureTrivia = opts?.captureTrivia === true;
2460
+ const trailingTrivia = opts?.trailingTrivia === true;
2461
+ if (unwrap && collapse) {
2462
+ throw new Error("node() options cannot set both unwrap and collapse");
2463
+ }
2464
+ const def = unwrap || collapse || captureTrivia || trailingTrivia ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {} } : baseDef;
2465
+ const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : true);
2466
+ const clonesState = build ? buildReadsState(def) : true;
2467
+ const hasOwnFields = parserHasOwnFields(combinator);
2468
+ const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : true);
2469
+ const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
2470
+ let failExpected;
2471
+ return {
2472
+ _tag: "node",
2473
+ _meta: meta,
2474
+ _def: def,
2475
+ parse(input, pos, ctx) {
2476
+ if (guardable && ctx._probe === void 0 && !ctx._tolerant && !startsFirstSet(combinator, input, pos)) {
2477
+ if (failExpected === void 0) {
2478
+ const e = deriveExpected(combinator);
2479
+ failExpected = e.length > 0 ? e : [combinator._tag];
2480
+ }
2481
+ return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
2482
+ }
2483
+ const hostCst = build !== void 0 && cstOutputHost(ctx.build);
2484
+ const effTrivia = capturesTrivia || hostCst;
2485
+ const effFields = capturesFields || hostCst && hasOwnFields;
2486
+ const saved = beginCstNodeCapture(ctx);
2487
+ const savedFields = ctx._fields;
2488
+ ctx._fields = effFields ? [] : void 0;
2489
+ const savedMask = ctx._triviaCaptureMask;
2490
+ if (build === void 0 && ctx.build?._parsemanTriviaKinds !== void 0 && def.type !== void 0) {
2491
+ ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
2492
+ }
2493
+ if (!effTrivia) ctx.captureTrivia = false;
2494
+ let r = combinator.parse(input, pos, ctx);
2495
+ if (r.ok && trailingTrivia && ctx.trivia) {
2496
+ const end = consumeTrivia(input, r.span.end, ctx);
2497
+ r = { ...r, span: { start: r.span.start, end } };
2498
+ }
2499
+ const fields = effFields ? buildFieldMap(ctx._fields) : void 0;
2500
+ ctx._fields = savedFields;
2501
+ ctx._triviaCaptureMask = savedMask;
2502
+ const { children, rawChildren, triviaLog } = endCstNodeCapture(ctx, saved);
2503
+ if (!r.ok) return r;
2504
+ const st = clonesState && ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
2505
+ const nodeType = def.type ?? missingInferredType();
2506
+ const cstOutput = cstOutputHost(ctx.build);
2507
+ const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
2508
+ const built = unwrap && children.length === 1 ? unwrapChild(children[0]) : collapse && children.length === 1 ? children[0] : !build && ctx.build?._parsemanCstCollapse && children.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children[0], children, rawChildren) ? children[0] : build ? cstOutput && ctx.build ? ctx.build(nodeType, children, fields, r.span, rawChildren, triviaLog, hostState) : build(children, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children };
2509
+ 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: r.span };
2510
+ if (saved.buf !== void 0 || saved.ch !== void 0) {
2511
+ pushCstChild(ctx, built, rawEntry);
2512
+ }
2513
+ return { ok: true, value: built, span: r.span };
2514
+ }
2515
+ };
2516
+ }
2517
+
2518
+ // src/compiler/line-index.ts
2519
+ function buildLineIndex(input) {
2520
+ const lineStarts = [0];
2521
+ for (let i = 0; i < input.length; i++) {
2522
+ if (input.charCodeAt(i) === 10) lineStarts.push(i + 1);
2523
+ }
2524
+ return { lineStarts };
2525
+ }
2526
+ function offsetToLineCol(index, offset) {
2527
+ const { lineStarts } = index;
2528
+ let lo = 0;
2529
+ let hi = lineStarts.length - 1;
2530
+ while (lo < hi) {
2531
+ const mid = lo + hi + 1 >> 1;
2532
+ if (lineStarts[mid] <= offset) lo = mid;
2533
+ else hi = mid - 1;
2534
+ }
2535
+ return { line: lo + 1, col: offset - lineStarts[lo] + 1 };
2536
+ }
2537
+ function annotateSpan(span, index) {
2538
+ const s = offsetToLineCol(index, span.start);
2539
+ const e = offsetToLineCol(index, span.end);
2540
+ return {
2541
+ ...span,
2542
+ startLine: s.line,
2543
+ startColumn: s.col,
2544
+ endLine: e.line,
2545
+ endColumn: e.col
2546
+ };
2547
+ }
2548
+
2549
+ // src/combinators/grammar.ts
2550
+ function parser(opts, root) {
2551
+ const clearTrivia = opts.trivia === null;
2552
+ return {
2553
+ _tag: "grammar",
2554
+ _meta: root._meta,
2555
+ _def: {
2556
+ tag: "grammar",
2557
+ parser: root,
2558
+ triviaParser: clearTrivia ? void 0 : opts.trivia ?? void 0,
2559
+ clearTrivia,
2560
+ ...opts.captureTrivia ? { captureTrivia: true } : {},
2561
+ trackLines: opts.trackLines ?? false
2562
+ },
2563
+ parse(input, pos, _ctx) {
2564
+ const trackLines = opts.trackLines ?? _ctx?.trackLines ?? false;
2565
+ const ctx = {
2566
+ ..._ctx,
2567
+ trackLines,
2568
+ // trivia: null clears (contiguous terms); a Combinator sets; undefined inherits.
2569
+ ...clearTrivia ? {
2570
+ trivia: void 0,
2571
+ triviaKindLabels: void 0
2572
+ } : opts.trivia != null ? {
2573
+ trivia: opts.trivia,
2574
+ ...opts.trivia._meta.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {}
2575
+ } : {},
2576
+ ...opts.captureTrivia || _ctx?.captureTrivia ? { captureTrivia: true } : {},
2577
+ // Kind-filter for per-node capture. Resolve against this scope's trivia
2578
+ // labels — this parser's own trivia if it declares one, else the INHERITED
2579
+ // labels (`_ctx.triviaKindLabels`), so captureTriviaKinds still applies when
2580
+ // trivia is inherited rather than re-declared here. No labels → undefined
2581
+ // (capture all).
2582
+ ...opts.captureTriviaKinds && !clearTrivia ? { _triviaCaptureMask: triviaKindMask(opts.trivia?._meta.triviaKindLabels ?? _ctx?.triviaKindLabels, opts.captureTriviaKinds) } : {}
2583
+ };
2584
+ const result = root.parse(input, pos ?? 0, ctx);
2585
+ if (trackLines) {
2586
+ const idx = buildLineIndex(input);
2587
+ return { ...result, span: annotateSpan(result.span, idx) };
2588
+ }
2589
+ return result;
2590
+ }
2591
+ };
2592
+ }
2593
+
2594
+ // src/combinators/token.ts
2595
+ function token(root) {
2596
+ const meta = {
2597
+ firstSet: root._meta.firstSet,
2598
+ canMatchNewline: root._meta.canMatchNewline,
2599
+ isTrivia: false
2600
+ };
2601
+ return {
2602
+ _tag: "token",
2603
+ _meta: meta,
2604
+ _def: { tag: "token", parser: root },
2605
+ parse(input, pos, ctx) {
2606
+ const savedTrivia = ctx.trivia;
2607
+ const savedKinds = ctx.triviaKindLabels;
2608
+ const savedBuf = ctx._cstBuf;
2609
+ const savedChildren = ctx._cstChildren;
2610
+ const savedLeaves = ctx._cstLeaves;
2611
+ const savedRaw = ctx._cstRawChildren;
2612
+ const savedTriviaLog = ctx._cstTriviaLog;
2613
+ const savedOuterTriviaLog = ctx._triviaLog;
2614
+ const wasCapturing = cstCaptureActive(ctx);
2615
+ ctx.trivia = void 0;
2616
+ ctx.triviaKindLabels = void 0;
2617
+ ctx._cstBuf = void 0;
2618
+ ctx._cstChildren = void 0;
2619
+ ctx._cstLeaves = void 0;
2620
+ ctx._cstRawChildren = void 0;
2621
+ ctx._cstTriviaLog = void 0;
2622
+ delete ctx._triviaLog;
2623
+ let result;
2624
+ try {
2625
+ result = root.parse(input, pos, ctx);
2626
+ } finally {
2627
+ ctx.trivia = savedTrivia;
2628
+ ctx.triviaKindLabels = savedKinds;
2629
+ ctx._cstBuf = savedBuf;
2630
+ ctx._cstChildren = savedChildren;
2631
+ ctx._cstLeaves = savedLeaves;
2632
+ ctx._cstRawChildren = savedRaw;
2633
+ ctx._cstTriviaLog = savedTriviaLog;
2634
+ if (savedOuterTriviaLog === void 0) delete ctx._triviaLog;
2635
+ else ctx._triviaLog = savedOuterTriviaLog;
2636
+ }
2637
+ if (!result.ok) return result;
2638
+ const span = result.span;
2639
+ const value = input.slice(pos, span.end);
2640
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span });
2641
+ return { ok: true, value, span };
2642
+ }
2643
+ };
2644
+ }
2645
+ function leaf(root, fn) {
2646
+ const meta = {
2647
+ firstSet: root._meta.firstSet,
2648
+ canMatchNewline: root._meta.canMatchNewline,
2649
+ isTrivia: false
2650
+ };
2651
+ return {
2652
+ _tag: "leaf",
2653
+ _meta: meta,
2654
+ _def: { tag: "leaf", parser: root, fn },
2655
+ parse(input, pos, ctx) {
2656
+ const savedBuf = ctx._cstBuf;
2657
+ const savedChildren = ctx._cstChildren;
2658
+ const savedLeaves = ctx._cstLeaves;
2659
+ const savedRaw = ctx._cstRawChildren;
2660
+ const savedTriviaLog = ctx._cstTriviaLog;
2661
+ const savedOuterTriviaLog = ctx._triviaLog;
2662
+ const wasCapturing = cstCaptureActive(ctx);
2663
+ ctx._cstBuf = void 0;
2664
+ ctx._cstChildren = void 0;
2665
+ ctx._cstLeaves = void 0;
2666
+ ctx._cstRawChildren = void 0;
2667
+ ctx._cstTriviaLog = void 0;
2668
+ delete ctx._triviaLog;
2669
+ let result;
2670
+ try {
2671
+ result = root.parse(input, pos, ctx);
2672
+ } finally {
2673
+ ctx._cstBuf = savedBuf;
2674
+ ctx._cstChildren = savedChildren;
2675
+ ctx._cstLeaves = savedLeaves;
2676
+ ctx._cstRawChildren = savedRaw;
2677
+ ctx._cstTriviaLog = savedTriviaLog;
2678
+ if (savedOuterTriviaLog === void 0) delete ctx._triviaLog;
2679
+ else ctx._triviaLog = savedOuterTriviaLog;
2680
+ }
2681
+ if (!result.ok) return result;
2682
+ const value = fn(result.value, result.span);
2683
+ if (wasCapturing) pushCstLeaf(ctx, { _tag: "leaf", value, span: result.span });
2684
+ return { ok: true, value, span: result.span };
2685
+ }
2686
+ };
2687
+ }
2688
+
2689
+ // src/combinators/withCtx.ts
2690
+ function withCtx(extra, combinator) {
2691
+ const meta = {
2692
+ firstSet: combinator._meta.firstSet,
2693
+ canMatchNewline: combinator._meta.canMatchNewline,
2694
+ isTrivia: false
2695
+ };
2696
+ return {
2697
+ _tag: "withCtx",
2698
+ _meta: meta,
2699
+ _def: { tag: "withCtx", extra, parser: combinator },
2700
+ parse(input, pos, ctx) {
2701
+ return combinator.parse(input, pos, { ...ctx, state: extra });
2702
+ }
2703
+ };
2704
+ }
2705
+
2706
+ // src/compiler/ir-serialize.ts
2707
+ function evalRuleMapIR(ir) {
2708
+ const _tf = (child, src, recognitionOnly = false) => {
2709
+ let fn2;
2710
+ try {
2711
+ fn2 = (0, eval)(`(${src})`);
2712
+ } catch {
2713
+ fn2 = () => {
2714
+ throw new Error("IR transform fn not materialized");
2715
+ };
2716
+ }
2717
+ const t = transform(child, fn2);
2718
+ t._def.fnSrc = src;
2719
+ if (recognitionOnly) t._def.recognitionOnly = true;
2720
+ return t;
2721
+ };
2722
+ const _lf = (child, src) => {
2723
+ let fn2;
2724
+ try {
2725
+ fn2 = (0, eval)(`(${src})`);
2726
+ } catch {
2727
+ fn2 = () => {
2728
+ throw new Error("IR leaf fn not materialized");
2729
+ };
2730
+ }
2731
+ const l = leaf(child, fn2);
2732
+ l._def.fnSrc = src;
2733
+ return l;
2734
+ };
2735
+ const _nd = (type, child, src, opts, staticError) => {
2736
+ if (staticError !== void 0 && staticError.length > 0) {
2737
+ throw new Error(`IR direct node builder for ${type} must be macro-static and self-contained; unsupported binding(s): ${staticError.join(", ")}`);
2738
+ }
2739
+ const n = node(type, child, (() => {
2740
+ throw new Error("IR node build requires static re-lowering");
2741
+ }), opts);
2742
+ n._def.buildSrc = src;
2743
+ if (staticError !== void 0) n._def.buildStaticError = staticError;
2744
+ return n;
2745
+ };
2746
+ const _gch = (items) => {
2747
+ const gateSrcs = [];
2748
+ const arms = items.map((it) => {
2749
+ if (Array.isArray(it)) {
2750
+ const [src, comb] = it;
2751
+ gateSrcs.push(src);
2752
+ let gate;
2753
+ try {
2754
+ gate = (0, eval)(`(${src})`);
2755
+ } catch {
2756
+ gate = () => {
2757
+ throw new Error("IR gate fn not materialized");
2758
+ };
2759
+ }
2760
+ return { gate, combinator: comb };
2761
+ }
2762
+ gateSrcs.push(null);
2763
+ return it;
2764
+ });
2765
+ const c = choice(...arms);
2766
+ const gates = c._def.gates;
2767
+ if (gates && gates.length !== gateSrcs.length) {
2768
+ throw new Error(`_gch: gateSrcs length ${gateSrcs.length} != choice gates length ${gates.length}`);
2769
+ }
2770
+ ;
2771
+ c._def.gateSrcs = gateSrcs;
2772
+ return c;
2773
+ };
2774
+ const _wc = (src, inner) => {
2775
+ let extra;
2776
+ try {
2777
+ extra = (0, eval)(`(${src})`);
2778
+ } catch {
2779
+ extra = void 0;
2780
+ }
2781
+ const w = withCtx(extra, inner);
2782
+ w._def.extraSrc = src;
2783
+ return w;
2784
+ };
2785
+ const fn = new Function(
2786
+ "rules",
2787
+ "ref",
2788
+ "regex",
2789
+ "literal",
2790
+ "keywords",
2791
+ "sequence",
2792
+ "choice",
2793
+ "attempt",
2794
+ "many",
2795
+ "oneOrMore",
2796
+ "optional",
2797
+ "sepBy",
2798
+ "not",
2799
+ "peek",
2800
+ "node",
2801
+ "parser",
2802
+ "scanTo",
2803
+ "token",
2804
+ "leaf",
2805
+ "transform",
2806
+ "skip",
2807
+ "trivia",
2808
+ "label",
2809
+ "field",
2810
+ "expect",
2811
+ "_tf",
2812
+ "_lf",
2813
+ "_nd",
2814
+ "_gch",
2815
+ "_wc",
2816
+ `return (${ir})`
2817
+ );
2818
+ const map = fn(
2819
+ rules,
2820
+ ref,
2821
+ regex,
2822
+ literal,
2823
+ keywords,
2824
+ sequence,
2825
+ choice,
2826
+ attempt,
2827
+ many,
2828
+ oneOrMore,
2829
+ optional,
2830
+ sepBy,
2831
+ not,
2832
+ peek,
2833
+ node,
2834
+ parser,
2835
+ scanTo,
2836
+ token,
2837
+ leaf,
2838
+ transform,
2839
+ skip,
2840
+ trivia,
2841
+ label,
2842
+ field,
2843
+ expect,
2844
+ _tf,
2845
+ _lf,
2846
+ _nd,
2847
+ _gch,
2848
+ _wc
2849
+ );
2850
+ return Object.entries(map);
2851
+ }
2852
+
2853
+ // src/compiler/linker.ts
2854
+ function normalizeCstCollapse(collapse) {
2855
+ if (collapse === true) return () => true;
2856
+ if (Array.isArray(collapse)) {
2857
+ const types = new Set(collapse);
2858
+ return (type) => types.has(type);
2859
+ }
2860
+ return typeof collapse === "function" ? collapse : void 0;
2861
+ }
2862
+ function buildCstNode(type, children, _fields, span, _rawChildren, _triviaLog, state) {
2863
+ return { _tag: "node", type, span: { start: span.start, end: span.end }, state: state ?? null, children: [...children] };
2864
+ }
2865
+ function cstBuildHost(typeOrOptions, children, _fields, span, rawChildren, triviaLog, state) {
2866
+ if (typeof typeOrOptions === "string") {
2867
+ return buildCstNode(typeOrOptions, children ?? [], _fields, span ?? { start: 0, end: 0 }, rawChildren, triviaLog, state);
2868
+ }
2869
+ const collapse = normalizeCstCollapse(typeOrOptions?.collapse);
2870
+ const host = (type, children2, fields, span2, rawChildren2, triviaLog2, state2) => buildCstNode(type, children2 ?? [], fields, span2, rawChildren2, triviaLog2, state2);
2871
+ host._parsemanCstOutput = true;
2872
+ if (collapse) host._parsemanCstCollapse = collapse;
2873
+ return host;
2874
+ }
2875
+ cstBuildHost._parsemanCstOutput = true;
2876
+ var COMPOSED_PIECES = /* @__PURE__ */ Symbol.for("parseman.composedPieces");
2877
+ function composedPiecesOf(grammar) {
2878
+ const pieces = grammar[COMPOSED_PIECES];
2879
+ return Array.isArray(pieces) ? pieces : void 0;
2880
+ }
2881
+ function isIRPiece(p) {
2882
+ return !!p && typeof p === "object" && typeof p.ir === "string" && typeof p.ns === "string" && !("ruleFns" in p);
2883
+ }
2884
+ function carriedRuleMapsDetailed(carried) {
2885
+ const maps = [];
2886
+ const opaque = [];
2887
+ for (const p of carried) {
2888
+ if (isIRPiece(p)) {
2889
+ maps.push(evalRuleMapIR(p.ir));
2890
+ continue;
2891
+ }
2892
+ const ruleFns = p.ruleFns;
2893
+ opaque.push({ ns: p.ns, ruleNames: ruleFns instanceof Map ? [...ruleFns.keys()] : [] });
2894
+ }
2895
+ return { maps, opaque };
2896
+ }
2897
+ function recoverComposedRules(grammar) {
2898
+ const carried = composedPiecesOf(grammar);
2899
+ if (carried === void 0) return void 0;
2900
+ const { maps, opaque } = carriedRuleMapsDetailed(carried);
2901
+ const rules2 = /* @__PURE__ */ new Map();
2902
+ for (const map of maps) for (const [name, rule] of map) {
2903
+ if (rule._def.tag === "lazy") {
2904
+ try {
2905
+ rule._def.thunk();
2906
+ } catch {
2907
+ continue;
2908
+ }
2909
+ }
2910
+ rules2.set(name, rule);
2911
+ }
2912
+ return { rules: rules2, opaque };
2913
+ }
3
2914
 
4
2915
  // src/spec/model.ts
5
2916
  function ruleNameOf(c) {
@@ -197,6 +3108,16 @@ function toRecord(grammar) {
197
3108
  const name = ruleNameOf(grammar) ?? "start";
198
3109
  return { [name]: grammar };
199
3110
  }
3111
+ const recovered = recoverComposedRules(grammar);
3112
+ if (recovered !== void 0) {
3113
+ if (recovered.opaque.length > 0) {
3114
+ const named = recovered.opaque.map((o) => `"${o.ns}"${o.ruleNames.length > 0 ? ` (${o.ruleNames.length} rule(s))` : ""}`).join(", ");
3115
+ throw new TypeError(
3116
+ `parseman spec: this composed grammar includes opaque precompiled artifact(s) ${named} that carry compiled rule functions rather than re-lowerable IR. Their rules cannot be rendered, and emitting a spec without them would silently understate the grammar. Recompile the contributing grammar(s) so they carry IR.`
3117
+ );
3118
+ }
3119
+ return Object.fromEntries(recovered.rules);
3120
+ }
200
3121
  return grammar;
201
3122
  }
202
3123
  function isCombinator(x) {
@@ -262,25 +3183,25 @@ function repeatOp(min, max) {
262
3183
  if (min === 0 && max === 1) return "?";
263
3184
  return `{${min},${max}}`;
264
3185
  }
265
- function render(node) {
266
- switch (node.kind) {
3186
+ function render(node2) {
3187
+ switch (node2.kind) {
267
3188
  case "terminal":
268
- return { text: node.literal ? quote(node.text) : node.text, level: ATOM };
3189
+ return { text: node2.literal ? quote(node2.text) : node2.text, level: ATOM };
269
3190
  case "ref":
270
- return { text: node.name, level: ATOM };
3191
+ return { text: node2.name, level: ATOM };
271
3192
  case "empty":
272
3193
  return { text: "", level: ATOM };
273
3194
  case "annotation":
274
- return { text: `/* ${node.text} */`, level: ATOM };
3195
+ return { text: `/* ${node2.text} */`, level: ATOM };
275
3196
  case "seq": {
276
- const text = node.items.map((it) => {
3197
+ const text = node2.items.map((it) => {
277
3198
  const r = render(it);
278
3199
  return wrap(r.text, r.level, CAT);
279
3200
  }).filter((t) => t.length > 0).join(" ");
280
3201
  return { text, level: CAT };
281
3202
  }
282
3203
  case "choice": {
283
- const text = node.items.map((it) => {
3204
+ const text = node2.items.map((it) => {
284
3205
  const r = render(it);
285
3206
  return wrap(r.text, r.level, ALT);
286
3207
  }).join(" | ");
@@ -289,27 +3210,27 @@ function render(node) {
289
3210
  case "star":
290
3211
  case "plus":
291
3212
  case "opt": {
292
- const r = render(node.item);
293
- const op = node.kind === "opt" ? "?" : node.kind === "star" ? repeatOp(0, node.max) : repeatOp(node.min ?? 1, node.max);
3213
+ const r = render(node2.item);
3214
+ const op = node2.kind === "opt" ? "?" : node2.kind === "star" ? repeatOp(0, node2.max) : repeatOp(node2.min ?? 1, node2.max);
294
3215
  return { text: `${wrap(r.text, r.level, ATOM)}${op}`, level: ATOM };
295
3216
  }
296
3217
  case "sepBy": {
297
- const item = render(node.item);
298
- const sep = render(node.sep);
3218
+ const item = render(node2.item);
3219
+ const sep = render(node2.sep);
299
3220
  const itemA = wrap(item.text, item.level, ATOM);
300
3221
  const sepA = wrap(sep.text, sep.level, CAT);
301
- const tail = `(${sepA} ${itemA})${repeatOp(Math.max(node.min - 1, 0), node.max === void 0 ? void 0 : node.max - 1)}`;
302
- const trail = node.trailing === "allow" ? ` ${sepA}?` : "";
3222
+ const tail = `(${sepA} ${itemA})${repeatOp(Math.max(node2.min - 1, 0), node2.max === void 0 ? void 0 : node2.max - 1)}`;
3223
+ const trail = node2.trailing === "allow" ? ` ${sepA}?` : "";
303
3224
  const body = `${itemA} ${tail}${trail}`;
304
- return node.min === 0 ? { text: `(${body})?`, level: ATOM } : { text: body, level: CAT };
3225
+ return node2.min === 0 ? { text: `(${body})?`, level: ATOM } : { text: body, level: CAT };
305
3226
  }
306
3227
  case "not": {
307
- const r = render(node.item);
3228
+ const r = render(node2.item);
308
3229
  return { text: `!${wrap(r.text, r.level, ATOM)}`, level: ATOM };
309
3230
  }
310
3231
  // PEG notation: `&` positive lookahead, `!` negative.
311
3232
  case "peek": {
312
- const r = render(node.item);
3233
+ const r = render(node2.item);
313
3234
  return { text: `&${wrap(r.text, r.level, ATOM)}`, level: ATOM };
314
3235
  }
315
3236
  }
@@ -321,8 +3242,8 @@ function renderProduction(p) {
321
3242
  function renderEBNF(model) {
322
3243
  return model.productions.map(renderProduction).join("\n") + "\n";
323
3244
  }
324
- function renderExpr(node) {
325
- return render(node).text;
3245
+ function renderExpr(node2) {
3246
+ return render(node2).text;
326
3247
  }
327
3248
 
328
3249
  // src/spec/railroad-lib.ts
@@ -883,41 +3804,41 @@ function boundLabel(min, max) {
883
3804
  if (max === min) return `${min}\xD7`;
884
3805
  return `${min}\u2013${max} times`;
885
3806
  }
886
- function toDsl(node) {
887
- switch (node.kind) {
3807
+ function toDsl(node2) {
3808
+ switch (node2.kind) {
888
3809
  case "terminal":
889
- return `Terminal(${j(node.text)})`;
3810
+ return `Terminal(${j(node2.text)})`;
890
3811
  case "ref":
891
- return `NonTerminal(${j(node.name)})`;
3812
+ return `NonTerminal(${j(node2.name)})`;
892
3813
  case "empty":
893
3814
  return `Skip()`;
894
3815
  case "annotation":
895
- return `Comment(${j(node.text)})`;
3816
+ return `Comment(${j(node2.text)})`;
896
3817
  case "seq":
897
- return `Sequence(${node.items.map(toDsl).join(", ")})`;
3818
+ return `Sequence(${node2.items.map(toDsl).join(", ")})`;
898
3819
  case "choice":
899
- return `Choice(0, ${node.items.map(toDsl).join(", ")})`;
3820
+ return `Choice(0, ${node2.items.map(toDsl).join(", ")})`;
900
3821
  case "star": {
901
- const b = boundLabel(0, node.max);
902
- return b ? `ZeroOrMore(${toDsl(node.item)}, Comment(${j(b)}))` : `ZeroOrMore(${toDsl(node.item)})`;
3822
+ const b = boundLabel(0, node2.max);
3823
+ return b ? `ZeroOrMore(${toDsl(node2.item)}, Comment(${j(b)}))` : `ZeroOrMore(${toDsl(node2.item)})`;
903
3824
  }
904
3825
  case "plus": {
905
- const b = boundLabel(node.min ?? 1, node.max);
906
- return b ? `OneOrMore(${toDsl(node.item)}, Comment(${j(b)}))` : `OneOrMore(${toDsl(node.item)})`;
3826
+ const b = boundLabel(node2.min ?? 1, node2.max);
3827
+ return b ? `OneOrMore(${toDsl(node2.item)}, Comment(${j(b)}))` : `OneOrMore(${toDsl(node2.item)})`;
907
3828
  }
908
3829
  case "opt":
909
- return `Optional(${toDsl(node.item)})`;
3830
+ return `Optional(${toDsl(node2.item)})`;
910
3831
  case "sepBy": {
911
- const b = boundLabel(node.min, node.max);
912
- const loop = b ? `Sequence(${toDsl(node.sep)}, Comment(${j(b)}))` : toDsl(node.sep);
913
- const rep = `OneOrMore(${toDsl(node.item)}, ${loop})`;
914
- const withTrail = node.trailing === void 0 ? rep : `Sequence(${rep}, Optional(${toDsl(node.sep)}))`;
915
- return node.min === 0 ? `Optional(${withTrail})` : withTrail;
3832
+ const b = boundLabel(node2.min, node2.max);
3833
+ const loop = b ? `Sequence(${toDsl(node2.sep)}, Comment(${j(b)}))` : toDsl(node2.sep);
3834
+ const rep = `OneOrMore(${toDsl(node2.item)}, ${loop})`;
3835
+ const withTrail = node2.trailing === void 0 ? rep : `Sequence(${rep}, Optional(${toDsl(node2.sep)}))`;
3836
+ return node2.min === 0 ? `Optional(${withTrail})` : withTrail;
916
3837
  }
917
3838
  case "not":
918
- return `Sequence(Comment("not"), ${toDsl(node.item)})`;
3839
+ return `Sequence(Comment("not"), ${toDsl(node2.item)})`;
919
3840
  case "peek":
920
- return `Sequence(Comment("peek"), ${toDsl(node.item)})`;
3841
+ return `Sequence(Comment("peek"), ${toDsl(node2.item)})`;
921
3842
  }
922
3843
  }
923
3844
  var _builders = null;
@@ -928,41 +3849,41 @@ function builders() {
928
3849
  _builders = mod;
929
3850
  return _builders;
930
3851
  }
931
- function toDiagramNode(b, node) {
932
- switch (node.kind) {
3852
+ function toDiagramNode(b, node2) {
3853
+ switch (node2.kind) {
933
3854
  case "terminal":
934
- return b.Terminal(node.text);
3855
+ return b.Terminal(node2.text);
935
3856
  case "ref":
936
- return b.NonTerminal(node.name);
3857
+ return b.NonTerminal(node2.name);
937
3858
  case "empty":
938
3859
  return b.Skip();
939
3860
  case "annotation":
940
- return b.Comment(node.text);
3861
+ return b.Comment(node2.text);
941
3862
  case "seq":
942
- return b.Sequence(...node.items.map((n) => toDiagramNode(b, n)));
3863
+ return b.Sequence(...node2.items.map((n) => toDiagramNode(b, n)));
943
3864
  case "choice":
944
- return b.Choice(0, ...node.items.map((n) => toDiagramNode(b, n)));
3865
+ return b.Choice(0, ...node2.items.map((n) => toDiagramNode(b, n)));
945
3866
  case "star": {
946
- const lbl = boundLabel(0, node.max);
947
- return lbl ? b.ZeroOrMore(toDiagramNode(b, node.item), b.Comment(lbl)) : b.ZeroOrMore(toDiagramNode(b, node.item));
3867
+ const lbl = boundLabel(0, node2.max);
3868
+ return lbl ? b.ZeroOrMore(toDiagramNode(b, node2.item), b.Comment(lbl)) : b.ZeroOrMore(toDiagramNode(b, node2.item));
948
3869
  }
949
3870
  case "plus": {
950
- const lbl = boundLabel(node.min ?? 1, node.max);
951
- return lbl ? b.OneOrMore(toDiagramNode(b, node.item), b.Comment(lbl)) : b.OneOrMore(toDiagramNode(b, node.item));
3871
+ const lbl = boundLabel(node2.min ?? 1, node2.max);
3872
+ return lbl ? b.OneOrMore(toDiagramNode(b, node2.item), b.Comment(lbl)) : b.OneOrMore(toDiagramNode(b, node2.item));
952
3873
  }
953
3874
  case "opt":
954
- return b.Optional(toDiagramNode(b, node.item));
3875
+ return b.Optional(toDiagramNode(b, node2.item));
955
3876
  case "sepBy": {
956
- const lbl = boundLabel(node.min, node.max);
957
- const sep = toDiagramNode(b, node.sep);
958
- const rep = b.OneOrMore(toDiagramNode(b, node.item), lbl ? b.Sequence(sep, b.Comment(lbl)) : sep);
959
- const withTrail = node.trailing === void 0 ? rep : b.Sequence(rep, b.Optional(toDiagramNode(b, node.sep)));
960
- return node.min === 0 ? b.Optional(withTrail) : withTrail;
3877
+ const lbl = boundLabel(node2.min, node2.max);
3878
+ const sep = toDiagramNode(b, node2.sep);
3879
+ const rep = b.OneOrMore(toDiagramNode(b, node2.item), lbl ? b.Sequence(sep, b.Comment(lbl)) : sep);
3880
+ const withTrail = node2.trailing === void 0 ? rep : b.Sequence(rep, b.Optional(toDiagramNode(b, node2.sep)));
3881
+ return node2.min === 0 ? b.Optional(withTrail) : withTrail;
961
3882
  }
962
3883
  case "not":
963
- return b.Sequence(b.Comment("not"), toDiagramNode(b, node.item));
3884
+ return b.Sequence(b.Comment("not"), toDiagramNode(b, node2.item));
964
3885
  case "peek":
965
- return b.Sequence(b.Comment("peek"), toDiagramNode(b, node.item));
3886
+ return b.Sequence(b.Comment("peek"), toDiagramNode(b, node2.item));
966
3887
  }
967
3888
  }
968
3889
  function renderRailroadSvg(model) {