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