parseman 0.60.4 → 0.60.6

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 (54) hide show
  1. package/dist/analysis/commitment.d.ts.map +1 -1
  2. package/dist/analysis/diagnostics.js +31 -5
  3. package/dist/analysis/diagnostics.js.map +1 -1
  4. package/dist/cli/index.js +639 -613
  5. package/dist/cli/index.js.map +3 -3
  6. package/dist/combinators/parser.d.ts +34 -3
  7. package/dist/combinators/parser.d.ts.map +1 -1
  8. package/dist/combinators/trivia-boundary.d.ts +5 -3
  9. package/dist/combinators/trivia-boundary.d.ts.map +1 -1
  10. package/dist/compiler/compile-linkable-table.d.ts.map +1 -1
  11. package/dist/compiler/linker.d.ts +11 -3
  12. package/dist/compiler/linker.d.ts.map +1 -1
  13. package/dist/compiler/token-capability.js +6 -0
  14. package/dist/compiler/token-capability.js.map +1 -1
  15. package/dist/index.d.ts +2 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +93 -25
  18. package/dist/index.js.map +1 -1
  19. package/dist/plugin/evaluator.d.ts +3 -1
  20. package/dist/plugin/evaluator.d.ts.map +1 -1
  21. package/dist/plugin/index.d.ts.map +1 -1
  22. package/dist/plugin/index.js +116 -75
  23. package/dist/plugin/index.js.map +1 -1
  24. package/dist/spec/index.js +3 -1
  25. package/dist/spec/index.js.map +1 -1
  26. package/dist/spec/model.d.ts.map +1 -1
  27. package/dist/table/assemble.d.ts.map +1 -1
  28. package/dist/table/emit-assembly.d.ts.map +1 -1
  29. package/dist/table/encode.d.ts.map +1 -1
  30. package/dist/table/exec.d.ts.map +1 -1
  31. package/dist/table/index.js +31 -5
  32. package/dist/table/index.js.map +1 -1
  33. package/dist/table/ops.d.ts +6 -0
  34. package/dist/table/ops.d.ts.map +1 -1
  35. package/dist/version.d.ts +1 -1
  36. package/package.json +1 -1
  37. package/src/analysis/commitment.ts +3 -1
  38. package/src/combinators/grammar.ts +1 -1
  39. package/src/combinators/parser.ts +82 -9
  40. package/src/combinators/trivia-boundary.ts +11 -3
  41. package/src/compiler/compile-linkable-table.ts +4 -1
  42. package/src/compiler/ir-serialize.ts +10 -4
  43. package/src/compiler/linker.ts +22 -12
  44. package/src/index.ts +2 -1
  45. package/src/plugin/evaluator.ts +16 -5
  46. package/src/plugin/index.ts +27 -104
  47. package/src/spec/model.ts +3 -1
  48. package/src/table/assemble.ts +11 -1
  49. package/src/table/emit-assembly.ts +10 -1
  50. package/src/table/encode.ts +16 -9
  51. package/src/table/exec.ts +11 -9
  52. package/src/table/ops.ts +6 -0
  53. package/src/table/site-labels.ts +3 -3
  54. package/src/version.ts +1 -1
package/dist/cli/index.js CHANGED
@@ -48,6 +48,12 @@ function hasOwnTriviaBoundary(p, depth = MAX_DEPTH) {
48
48
  case "oneOrMore":
49
49
  case "sepBy":
50
50
  return true;
51
+ // A scope that names or clears trivia keeps an outer install out of its body.
52
+ // Any other inherits, so it falls through at no cost in depth: line tracking
53
+ // wraps every rule in one, and must not change what this walk sees.
54
+ case "grammar":
55
+ if (d.triviaParser || d.clearTrivia) return false;
56
+ depth++;
51
57
  // Transparent wrappers — they add no position, so ask what they wrap.
52
58
  case "node":
53
59
  case "transform":
@@ -4167,214 +4173,544 @@ function scalarRootOf(combinator) {
4167
4173
  return scalar !== void 0 && def.tag === "grammar" && scalarTree(def.parser, /* @__PURE__ */ new Set()) ? scalar : void 0;
4168
4174
  }
4169
4175
 
4170
- // src/combinators/choice.ts
4171
- function choice(...args) {
4172
- const parsers = args.map((a) => "gate" in a ? a.combinator : a);
4173
- const gates = args.map((a) => "gate" in a ? a.gate : null);
4174
- const hasGates = gates.some((g) => g !== null);
4175
- const disjoint = areDisjoint(parsers.map((p) => p._meta.firstSet)) && parsers.every((p) => !matchesEmpty(p));
4176
- let combined = { kind: "empty" };
4177
- for (const p of parsers) combined = union(combined, p._meta.firstSet);
4178
- const meta = {
4179
- firstSet: combined,
4180
- canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
4181
- isTrivia: false,
4182
- disjoint
4183
- };
4184
- const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
4185
- const ordered = strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix";
4186
- const autoNot = !disjoint && !hasGates && ordered ? computeAutoNot(parsers) : parsers.map(() => null);
4187
- let greedyLitMap = null;
4188
- let sortedParsers = null;
4189
- const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
4190
- if (strategy?.tag === "greedyClassify") {
4191
- greedyLitMap = /* @__PURE__ */ new Map();
4192
- for (let i = 0; i < parsers.length; i++) {
4193
- if (i === strategy.superIndex) continue;
4194
- const litVal = getCoreLiteralValue(parsers[i]);
4195
- if (litVal !== null) greedyLitMap.set(litVal, i);
4196
- }
4197
- } else if (strategy?.tag === "literalsLongestFirst") {
4198
- sortedParsers = strategy.sortedIndices.map((i) => parsers[i]);
4176
+ // src/combinators/ref.ts
4177
+ function withRuleTrivia(trivia2, ctx, run) {
4178
+ const savedLabels = ctx.triviaKindLabels;
4179
+ ctx.trivia = trivia2;
4180
+ ctx.triviaKindLabels = trivia2._meta.triviaKindLabels;
4181
+ try {
4182
+ return run();
4183
+ } finally {
4184
+ ctx.trivia = void 0;
4185
+ ctx.triviaKindLabels = savedLabels;
4199
4186
  }
4200
- const scalarParsers = parsers.map(scalarOf);
4201
- const scalarEligible = !hasGates && parsers.every((p) => p._parseScalar !== void 0) && (disjoint || ordered);
4202
- const scalarExpected = parsers.flatMap(deriveExpected);
4203
- const parseScalar = (input, pos, ctx) => {
4204
- if (disjoint) {
4205
- const code = pos < input.length ? input.codePointAt(pos) : -1;
4206
- let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
4207
- if (idx < 0 && code >= 0) {
4208
- for (let i = 0; i < parsers.length; i++) {
4209
- if (inFirstSet(code, parsers[i]._meta.firstSet)) {
4210
- idx = i;
4211
- break;
4212
- }
4213
- }
4214
- }
4215
- if (idx >= 0) {
4216
- const gate = gates[idx];
4217
- if (!gate || gate(ctx.state)) return scalarParsers[idx](input, pos, ctx);
4218
- ctx._fx = deriveExpected(parsers[idx]);
4219
- return ~pos;
4220
- }
4221
- } else {
4222
- for (let i = 0; i < scalarParsers.length; i++) {
4223
- if (gates[i] && !gates[i](ctx.state)) continue;
4224
- const end = scalarParsers[i](input, pos, ctx);
4225
- if (end >= 0 && (!autoNot[i] || !autoNotFires(input, end, autoNot[i]))) return end;
4226
- }
4227
- }
4228
- ctx._fx = scalarExpected;
4229
- return ~pos;
4187
+ }
4188
+ var UNDEFINED_REF = new Error("ref<T>() used before .define() was called");
4189
+ function ref() {
4190
+ let resolved = null;
4191
+ let resolvedScalar = null;
4192
+ let ownBoundary = false;
4193
+ const meta = {
4194
+ firstSet: any(),
4195
+ canMatchNewline: true,
4196
+ isTrivia: false
4230
4197
  };
4231
- return {
4232
- _tag: "choice",
4198
+ const slot = {
4199
+ _tag: "lazy",
4233
4200
  _meta: meta,
4234
4201
  _def: {
4235
- tag: "choice",
4236
- parsers,
4237
- gates,
4238
- disjoint,
4239
- strategy: strategy ?? { tag: "firstMatch" },
4240
- autoNot
4241
- },
4242
- _parseScalar: scalarEligible ? parseScalar : void 0,
4243
- parse(input, pos, ctx) {
4244
- const expected = [];
4245
- let expectedAt = pos;
4246
- if (disjoint) {
4247
- const code = pos < input.length ? input.codePointAt(pos) : -1;
4248
- let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
4249
- if (idx < 0 && code >= 0) {
4250
- for (let i = 0; i < parsers.length; i++) {
4251
- if (inFirstSet(code, parsers[i]._meta.firstSet)) {
4252
- idx = i;
4253
- break;
4254
- }
4255
- }
4256
- }
4257
- if (idx >= 0) {
4258
- const gate = gates[idx];
4259
- if (gate && !gate(ctx.state)) {
4260
- return { ok: false, expected: deriveExpected(parsers[idx]), span: { start: pos, end: pos } };
4261
- }
4262
- const result = parsers[idx].parse(input, pos, ctx);
4263
- if (result.ok) return result;
4264
- expected.push(...result.expected);
4265
- if (result.committed) return { ok: false, expected, span: { start: pos, end: pos }, committed: true };
4266
- return { ok: false, expected, span: { start: pos, end: pos } };
4267
- }
4268
- if (ctx._probe !== void 0 || ctx._tolerant) for (const p of parsers) p.parse(input, pos, ctx);
4269
- return { ok: false, expected: [...scalarExpected], span: { start: pos, end: pos } };
4270
- }
4271
- if (strategy?.tag === "greedyClassify") {
4272
- const superResult = parsers[strategy.superIndex].parse(input, pos, ctx);
4273
- if (!superResult.ok) return superResult;
4274
- const end = superResult.span.end;
4275
- const litIdx = greedyLitMap.get(input.slice(pos, end));
4276
- if (litIdx !== void 0) {
4277
- const litVal = getCoreLiteralValue(parsers[litIdx]);
4278
- const value = applyTransforms(parsers[litIdx], litVal, { start: pos, end });
4279
- return { ok: true, value, span: { start: pos, end } };
4280
- }
4281
- return superResult;
4282
- }
4283
- if (strategy?.tag === "literalsLongestFirst") {
4284
- for (const p of sortedParsers) {
4285
- const r = p.parse(input, pos, ctx);
4286
- if (r.ok) return r;
4287
- expected.push(...r.expected);
4288
- }
4289
- return { ok: false, expected, span: { start: pos, end: pos } };
4202
+ tag: "lazy",
4203
+ thunk: () => {
4204
+ if (!resolved) throw UNDEFINED_REF;
4205
+ return resolved;
4290
4206
  }
4291
- for (let i = 0; i < parsers.length; i++) {
4292
- if (gates[i] && !gates[i](ctx.state)) continue;
4293
- const mark = saveTriviaMark(ctx);
4294
- const split = ctx._columnsSplit;
4295
- const result = parsers[i].parse(input, pos, ctx);
4296
- if (!result.ok) {
4297
- rollbackTrivia(ctx, mark);
4298
- ctx._columnsSplit = split;
4299
- const at = result.span.start;
4300
- if (at > expectedAt) {
4301
- expectedAt = at;
4302
- expected.length = 0;
4303
- }
4304
- if (at === expectedAt) expected.push(...result.expected);
4305
- if (result.committed) return { ok: false, expected, span: result.span, committed: true };
4306
- continue;
4307
- }
4308
- const checks = autoNot[i];
4309
- if (checks && autoNotFires(input, result.span.end, checks)) {
4310
- rollbackTrivia(ctx, mark);
4311
- continue;
4312
- }
4313
- return result;
4207
+ },
4208
+ _parseScalar(input, pos, ctx) {
4209
+ const scalar = resolvedScalar;
4210
+ if (!scalar) throw new Error("ref<T>() used before .define() was called");
4211
+ const gt = meta.grammarTrivia;
4212
+ if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
4213
+ return withRuleTrivia(gt, ctx, () => scalar(input, pos, ctx));
4314
4214
  }
4315
- if (expected.length === 0) {
4316
- for (const parser2 of parsers) expected.push(...deriveExpected(parser2));
4215
+ return scalar(input, pos, ctx);
4216
+ },
4217
+ parse(input, pos, ctx) {
4218
+ const parser2 = resolved;
4219
+ if (!parser2) throw new Error("ref<T>() used before .define() was called");
4220
+ const gt = meta.grammarTrivia;
4221
+ if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
4222
+ return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
4317
4223
  }
4318
- return { ok: false, expected, span: { start: pos, end: pos } };
4224
+ return parser2.parse(input, pos, ctx);
4225
+ },
4226
+ define(p) {
4227
+ if (resolved) throw new Error("ref<T>() already defined");
4228
+ resolved = p;
4229
+ resolvedScalar = scalarOf(p);
4230
+ ownBoundary = hasOwnTriviaBoundary(p);
4231
+ meta.firstSet = p._meta.firstSet;
4232
+ meta.canMatchNewline = p._meta.canMatchNewline;
4233
+ meta.isTrivia = p._meta.isTrivia;
4234
+ if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
4235
+ else delete meta.triviaKindLabels;
4236
+ if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
4237
+ else delete meta.disjoint;
4319
4238
  }
4320
4239
  };
4240
+ return slot;
4321
4241
  }
4322
- function detectStrategy(parsers) {
4323
- const regexIndices = [];
4324
- const literalIndices = [];
4325
- for (let i = 0; i < parsers.length; i++) {
4326
- if (getCoreRegexDef(parsers[i]) !== null) regexIndices.push(i);
4327
- else if (getCoreLiteralValue(parsers[i]) !== null) literalIndices.push(i);
4328
- }
4329
- if (regexIndices.length === 1 && literalIndices.length === parsers.length - 1 && literalIndices.length > 0) {
4330
- const superIndex = regexIndices[0];
4331
- const regexDef = getCoreRegexDef(parsers[superIndex]);
4332
- const flags = "y" + regexDef.flags.replace(/[gy]/g, "");
4333
- const re = new RegExp(regexDef.source, flags);
4334
- const allSubsumed = literalIndices.every((i) => {
4335
- const litVal = getCoreLiteralValue(parsers[i]);
4336
- re.lastIndex = 0;
4337
- const m = re.exec(litVal);
4338
- return m !== null && m[0] === litVal;
4339
- });
4340
- if (allSubsumed) return { tag: "greedyClassify", superIndex };
4341
- }
4342
- if (parsers.length === literalIndices.length) {
4343
- const sortedIndices = [...literalIndices].sort(
4344
- (a, b) => getCoreLiteralValue(parsers[b]).length - getCoreLiteralValue(parsers[a]).length
4345
- );
4346
- return { tag: "literalsLongestFirst", sortedIndices };
4347
- }
4348
- const shared = detectSharedPrefix(parsers);
4349
- if (shared !== null) return shared;
4350
- return { tag: "firstMatch" };
4351
- }
4352
- function bareLeadingTermKey(term) {
4353
- const d = term._def;
4354
- if (d.tag === "literal" && !d.caseInsensitive) return `L:${d.value}`;
4355
- if (d.tag === "regex") return `R:${JSON.stringify([d.source, d.flags])}`;
4356
- return null;
4357
- }
4358
- function detectSharedPrefix(parsers) {
4359
- if (parsers.length < 2) return null;
4360
- let key = null;
4361
- let prefix = null;
4362
- const members = [];
4363
- for (let i = 0; i < parsers.length; i++) {
4364
- const term0 = leadingTermOfArm(parsers[i]);
4365
- if (term0 === null) return null;
4366
- const k = bareLeadingTermKey(term0);
4367
- if (k === null) return null;
4368
- if (key === null) {
4369
- key = k;
4370
- prefix = term0;
4371
- } else if (k !== key) return null;
4372
- members.push(i);
4373
- }
4374
- if (prefix === null || members.length < 2) return null;
4375
- return { tag: "sharedPrefix", prefix, members };
4376
- }
4377
- function leadingTermOfArm(arm) {
4242
+
4243
+ // src/compiler/value-usage.ts
4244
+ function markUnusedValues(root) {
4245
+ const seenConsumed = /* @__PURE__ */ new WeakSet();
4246
+ const seenUnconsumed = /* @__PURE__ */ new WeakSet();
4247
+ const mark = (def, consumed) => {
4248
+ if (consumed) def.valueUnused = false;
4249
+ else if (def.valueUnused !== false) def.valueUnused = true;
4250
+ };
4251
+ const visit = (c, consumed) => {
4252
+ const seen = consumed ? seenConsumed : seenUnconsumed;
4253
+ if (seen.has(c)) return;
4254
+ seen.add(c);
4255
+ const def = c._def;
4256
+ switch (def.tag) {
4257
+ case "many":
4258
+ case "oneOrMore":
4259
+ mark(def, consumed);
4260
+ visit(def.parser, consumed);
4261
+ return;
4262
+ case "optional":
4263
+ visit(def.parser, consumed);
4264
+ return;
4265
+ case "sequence":
4266
+ mark(def, consumed);
4267
+ for (const p of def.parsers) visit(p, consumed);
4268
+ return;
4269
+ case "choice":
4270
+ for (const p of def.parsers) visit(p, consumed);
4271
+ return;
4272
+ case "dispatch":
4273
+ visit(def.selector, consumed);
4274
+ for (const entry of def.cases) visit(entry.parser, consumed);
4275
+ if (def.matchers) for (const entry of def.matchers) visit(entry.parser, consumed);
4276
+ if (def.otherwise) visit(def.otherwise, consumed);
4277
+ return;
4278
+ case "node":
4279
+ visit(def.parser, false);
4280
+ return;
4281
+ case "transform":
4282
+ visit(def.parser, true);
4283
+ return;
4284
+ case "field":
4285
+ visit(def.parser, true);
4286
+ return;
4287
+ case "sepBy":
4288
+ visit(def.parser, true);
4289
+ visit(def.separator, false);
4290
+ return;
4291
+ case "not":
4292
+ case "peek":
4293
+ visit(def.parser, false);
4294
+ return;
4295
+ case "grammar":
4296
+ visit(def.parser, consumed);
4297
+ if (def.triviaParser) visit(def.triviaParser, false);
4298
+ return;
4299
+ case "recover":
4300
+ visit(def.parser, consumed);
4301
+ visit(def.sentinel, false);
4302
+ return;
4303
+ case "token":
4304
+ visit(def.parser, false);
4305
+ return;
4306
+ case "label":
4307
+ case "trivia":
4308
+ case "attempt":
4309
+ case "withCtx":
4310
+ case "expect":
4311
+ visit(def.parser, consumed);
4312
+ return;
4313
+ case "leaf":
4314
+ visit(def.parser, true);
4315
+ return;
4316
+ case "lazy":
4317
+ return;
4318
+ default:
4319
+ return;
4320
+ }
4321
+ };
4322
+ const resolveRoot = (c) => {
4323
+ const guard = /* @__PURE__ */ new Set();
4324
+ let cur = c;
4325
+ while (!guard.has(cur)) {
4326
+ const d = cur._def;
4327
+ if (d.tag === "grammar") {
4328
+ guard.add(cur);
4329
+ cur = d.parser;
4330
+ continue;
4331
+ }
4332
+ if (d.tag !== "lazy") return cur;
4333
+ guard.add(cur);
4334
+ try {
4335
+ cur = d.thunk();
4336
+ } catch {
4337
+ return c;
4338
+ }
4339
+ }
4340
+ return cur;
4341
+ };
4342
+ visit(resolveRoot(root), true);
4343
+ }
4344
+
4345
+ // src/cst/root-trivia-scope.ts
4346
+ var ROOT_TRIVIA_SCOPE_REFUSAL = "parser(): selected root trivia requires classifiedTrivia() for every local trivia scope, or rootCapture: 'opaque'.";
4347
+ function refuseUnclassifiedRootScope(strict) {
4348
+ if (strict === true) throw new TypeError(ROOT_TRIVIA_SCOPE_REFUSAL);
4349
+ }
4350
+
4351
+ // src/combinators/grammar.ts
4352
+ function annotateResultLines(result, index) {
4353
+ const annotated = { ...result, span: annotateSpan(result.span, index) };
4354
+ const errors = annotated.errors;
4355
+ if (errors) {
4356
+ ;
4357
+ annotated.errors = errors.map((error) => ({
4358
+ ...error,
4359
+ span: annotateSpan(error.span, index)
4360
+ }));
4361
+ }
4362
+ return annotated;
4363
+ }
4364
+ function createParseLineContext(input, pos) {
4365
+ const lineIndex = createLineIndex();
4366
+ if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
4367
+ return { lineIndex, lineScannedTo: pos };
4368
+ }
4369
+ var TRACK_LINES_ON = () => true;
4370
+ var TRACK_LINES_OFF = () => false;
4371
+ var TRACK_LINES_INHERIT = (ctx) => ctx?.trackLines === true;
4372
+ function parser(opts, root) {
4373
+ const clearTrivia = opts.trivia === null;
4374
+ const opaqueRootCapture = opts.rootCapture === "opaque";
4375
+ if (opaqueRootCapture && opts.trivia === void 0) {
4376
+ throw new TypeError("parser({ rootCapture: 'opaque' }) requires an explicit trivia scope.");
4377
+ }
4378
+ const scopeTrivia = clearTrivia ? void 0 : opts.trivia ?? void 0;
4379
+ const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
4380
+ const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
4381
+ const forceCaptureTrivia = opts.captureTrivia === true;
4382
+ const trackLinesPolicy = opts.trackLines === true ? "on" : opts.trackLines === false ? "off" : "inherit";
4383
+ const trackLinesOf = trackLinesPolicy === "on" ? TRACK_LINES_ON : trackLinesPolicy === "off" ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
4384
+ const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
4385
+ const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
4386
+ const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
4387
+ const rootScalar = scalarOf(root);
4388
+ const scalarEligible = opts.trackLines !== true && opts.recover !== true && !opaqueRootCapture && !forceCaptureTrivia && captureKinds === void 0;
4389
+ const parseScalar = scalarEligible ? (input, pos, ctx) => {
4390
+ const savedTrivia = ctx.trivia;
4391
+ const savedLabels = ctx.triviaKindLabels;
4392
+ if (clearTrivia) {
4393
+ ctx.trivia = void 0;
4394
+ ctx.triviaKindLabels = void 0;
4395
+ } else if (scopeTrivia !== void 0) {
4396
+ ctx.trivia = scopeTrivia;
4397
+ ctx.triviaKindLabels = scopeLabels;
4398
+ }
4399
+ const end = rootScalar(input, pos, ctx);
4400
+ ctx.trivia = savedTrivia;
4401
+ ctx.triviaKindLabels = savedLabels;
4402
+ return end;
4403
+ } : void 0;
4404
+ let publicScalar;
4405
+ const grammar = {
4406
+ _tag: "grammar",
4407
+ _meta: {
4408
+ ...root._meta,
4409
+ // Trivia classification describes this grammar's own active trivia
4410
+ // scope. A directly nested grammar may have classified trivia of its
4411
+ // own, but that must not advertise classification for this wrapper.
4412
+ triviaKindLabels: void 0,
4413
+ rootTriviaClassified: void 0,
4414
+ ...opts.trivia?._meta?.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {},
4415
+ ...opts.trivia?._meta?.rootTriviaClassified ? { rootTriviaClassified: true } : {}
4416
+ },
4417
+ _def: {
4418
+ tag: "grammar",
4419
+ parser: root,
4420
+ triviaParser: scopeTrivia,
4421
+ clearTrivia,
4422
+ ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
4423
+ ...opts.captureTrivia ? { captureTrivia: true } : {},
4424
+ trackLines: opts.trackLines ?? false,
4425
+ constructionTrackLines: trackLinesPolicy,
4426
+ ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
4427
+ },
4428
+ _parseScalar: parseScalar,
4429
+ parse(input, pos, _ctx) {
4430
+ if (pos === void 0 && _ctx === void 0) {
4431
+ publicScalar ??= scalarRootOf(grammar) ?? null;
4432
+ if (publicScalar) {
4433
+ const ctx2 = createParseContext();
4434
+ const end = publicScalar(input, 0, ctx2);
4435
+ if (end < 0) {
4436
+ const at = ~end;
4437
+ return { ok: false, expected: ctx2._fx ?? [], span: { start: at, end: at } };
4438
+ }
4439
+ return { ok: true, value: ctx2._sv, span: { start: 0, end } };
4440
+ }
4441
+ }
4442
+ if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
4443
+ const trackLines = trackLinesOf(_ctx);
4444
+ const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
4445
+ const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
4446
+ const ctx = _ctx === void 0 ? createParseContext() : { ..._ctx };
4447
+ ctx.trackLines = trackLines;
4448
+ if (lineIndex) ctx._lineIndex = lineIndex;
4449
+ if (lineContext) ctx._lineScannedTo = lineContext.lineScannedTo;
4450
+ if (clearTrivia) {
4451
+ ctx.trivia = void 0;
4452
+ ctx.triviaKindLabels = void 0;
4453
+ } else if (scopeTrivia !== void 0) {
4454
+ ctx.trivia = scopeTrivia;
4455
+ ctx.triviaKindLabels = scopeLabels;
4456
+ }
4457
+ if (forceCaptureTrivia || _ctx?.captureTrivia) ctx.captureTrivia = true;
4458
+ if (ownCaptureMask !== void 0) ctx._triviaCaptureMask = ownCaptureMask;
4459
+ else if (inheritCaptureMask) ctx._triviaCaptureMask = triviaKindMask(_ctx?.triviaKindLabels, captureKinds);
4460
+ if (opaqueRootCapture) ctx._rootTriviaCapture = false;
4461
+ const result = root.parse(input, pos ?? 0, ctx);
4462
+ if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
4463
+ _ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
4464
+ }
4465
+ return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
4466
+ }
4467
+ };
4468
+ return grammar;
4469
+ }
4470
+ function noTrivia(root) {
4471
+ return parser({ trivia: null }, root);
4472
+ }
4473
+ var _analyzed = /* @__PURE__ */ new WeakSet();
4474
+ function parse(combinator, input, opts = {}) {
4475
+ if (!_analyzed.has(combinator)) {
4476
+ _analyzed.add(combinator);
4477
+ markUnusedValues(combinator);
4478
+ }
4479
+ if (!opts.trackLines && !opts.recover && combinator._def.tag === "grammar" && combinator._meta.grammarScanSkip === void 0) {
4480
+ return combinator.parse(input);
4481
+ }
4482
+ const trackLines = opts.trackLines ?? combinator._meta.grammarTrackLines ?? false;
4483
+ const lineContext = trackLines ? createParseLineContext(input, 0) : void 0;
4484
+ const lineIndex = lineContext?.lineIndex;
4485
+ const _errors = opts.recover ? [] : void 0;
4486
+ const _probe = opts.recover ? { offset: input.length, best: null } : void 0;
4487
+ const grammarTrivia = combinator._meta.grammarTrivia;
4488
+ const grammarScanSkip = combinator._meta.grammarScanSkip;
4489
+ const ctx = createParseContext();
4490
+ ctx.trackLines = trackLines;
4491
+ if (lineIndex) ctx._lineIndex = lineIndex;
4492
+ if (lineContext) ctx._lineScannedTo = lineContext.lineScannedTo;
4493
+ if (grammarTrivia !== void 0) {
4494
+ ctx.trivia = grammarTrivia;
4495
+ if (grammarTrivia._meta.triviaKindLabels) ctx.triviaKindLabels = grammarTrivia._meta.triviaKindLabels;
4496
+ }
4497
+ if (grammarScanSkip !== void 0) ctx.scanSkip = grammarScanSkip;
4498
+ if (_errors !== void 0) ctx._errors = _errors;
4499
+ if (_probe !== void 0) ctx._probe = _probe;
4500
+ const result = combinator.parse(input, 0, ctx);
4501
+ if (!result.ok) return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
4502
+ const withErrors = _errors !== void 0 ? { ...result, errors: _errors, furthestFail: _probe?.best ?? null } : result;
4503
+ return lineIndex ? annotateResultLines(withErrors, normalizeLineIndex(lineIndex)) : withErrors;
4504
+ }
4505
+
4506
+ // src/combinators/choice.ts
4507
+ function choice(...args) {
4508
+ const parsers = args.map((a) => "gate" in a ? a.combinator : a);
4509
+ const gates = args.map((a) => "gate" in a ? a.gate : null);
4510
+ const hasGates = gates.some((g) => g !== null);
4511
+ const disjoint = areDisjoint(parsers.map((p) => p._meta.firstSet)) && parsers.every((p) => !matchesEmpty(p));
4512
+ let combined = { kind: "empty" };
4513
+ for (const p of parsers) combined = union(combined, p._meta.firstSet);
4514
+ const meta = {
4515
+ firstSet: combined,
4516
+ canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
4517
+ isTrivia: false,
4518
+ disjoint
4519
+ };
4520
+ const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
4521
+ const ordered = strategy?.tag === "firstMatch" || strategy?.tag === "sharedPrefix";
4522
+ const autoNot = !disjoint && !hasGates && ordered ? computeAutoNot(parsers) : parsers.map(() => null);
4523
+ let greedyLitMap = null;
4524
+ let sortedParsers = null;
4525
+ const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
4526
+ if (strategy?.tag === "greedyClassify") {
4527
+ greedyLitMap = /* @__PURE__ */ new Map();
4528
+ for (let i = 0; i < parsers.length; i++) {
4529
+ if (i === strategy.superIndex) continue;
4530
+ const litVal = getCoreLiteralValue(parsers[i]);
4531
+ if (litVal !== null) greedyLitMap.set(litVal, i);
4532
+ }
4533
+ } else if (strategy?.tag === "literalsLongestFirst") {
4534
+ sortedParsers = strategy.sortedIndices.map((i) => parsers[i]);
4535
+ }
4536
+ const scalarParsers = parsers.map(scalarOf);
4537
+ const scalarEligible = !hasGates && parsers.every((p) => p._parseScalar !== void 0) && (disjoint || ordered);
4538
+ const scalarExpected = parsers.flatMap(deriveExpected);
4539
+ const parseScalar = (input, pos, ctx) => {
4540
+ if (disjoint) {
4541
+ const code = pos < input.length ? input.codePointAt(pos) : -1;
4542
+ let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
4543
+ if (idx < 0 && code >= 0) {
4544
+ for (let i = 0; i < parsers.length; i++) {
4545
+ if (inFirstSet(code, parsers[i]._meta.firstSet)) {
4546
+ idx = i;
4547
+ break;
4548
+ }
4549
+ }
4550
+ }
4551
+ if (idx >= 0) {
4552
+ const gate = gates[idx];
4553
+ if (!gate || gate(ctx.state)) return scalarParsers[idx](input, pos, ctx);
4554
+ ctx._fx = deriveExpected(parsers[idx]);
4555
+ return ~pos;
4556
+ }
4557
+ } else {
4558
+ for (let i = 0; i < scalarParsers.length; i++) {
4559
+ if (gates[i] && !gates[i](ctx.state)) continue;
4560
+ const end = scalarParsers[i](input, pos, ctx);
4561
+ if (end >= 0 && (!autoNot[i] || !autoNotFires(input, end, autoNot[i]))) return end;
4562
+ }
4563
+ }
4564
+ ctx._fx = scalarExpected;
4565
+ return ~pos;
4566
+ };
4567
+ return {
4568
+ _tag: "choice",
4569
+ _meta: meta,
4570
+ _def: {
4571
+ tag: "choice",
4572
+ parsers,
4573
+ gates,
4574
+ disjoint,
4575
+ strategy: strategy ?? { tag: "firstMatch" },
4576
+ autoNot
4577
+ },
4578
+ _parseScalar: scalarEligible ? parseScalar : void 0,
4579
+ parse(input, pos, ctx) {
4580
+ const expected = [];
4581
+ let expectedAt = pos;
4582
+ if (disjoint) {
4583
+ const code = pos < input.length ? input.codePointAt(pos) : -1;
4584
+ let idx = code >= 0 && code < 128 ? asciiDispatch[code] : -1;
4585
+ if (idx < 0 && code >= 0) {
4586
+ for (let i = 0; i < parsers.length; i++) {
4587
+ if (inFirstSet(code, parsers[i]._meta.firstSet)) {
4588
+ idx = i;
4589
+ break;
4590
+ }
4591
+ }
4592
+ }
4593
+ if (idx >= 0) {
4594
+ const gate = gates[idx];
4595
+ if (gate && !gate(ctx.state)) {
4596
+ return { ok: false, expected: deriveExpected(parsers[idx]), span: { start: pos, end: pos } };
4597
+ }
4598
+ const result = parsers[idx].parse(input, pos, ctx);
4599
+ if (result.ok) return result;
4600
+ expected.push(...result.expected);
4601
+ if (result.committed) return { ok: false, expected, span: { start: pos, end: pos }, committed: true };
4602
+ return { ok: false, expected, span: { start: pos, end: pos } };
4603
+ }
4604
+ if (ctx._probe !== void 0 || ctx._tolerant) for (const p of parsers) p.parse(input, pos, ctx);
4605
+ return { ok: false, expected: [...scalarExpected], span: { start: pos, end: pos } };
4606
+ }
4607
+ if (strategy?.tag === "greedyClassify") {
4608
+ const superResult = parsers[strategy.superIndex].parse(input, pos, ctx);
4609
+ if (!superResult.ok) return superResult;
4610
+ const end = superResult.span.end;
4611
+ const litIdx = greedyLitMap.get(input.slice(pos, end));
4612
+ if (litIdx !== void 0) {
4613
+ const litVal = getCoreLiteralValue(parsers[litIdx]);
4614
+ const value = applyTransforms(parsers[litIdx], litVal, { start: pos, end });
4615
+ return { ok: true, value, span: { start: pos, end } };
4616
+ }
4617
+ return superResult;
4618
+ }
4619
+ if (strategy?.tag === "literalsLongestFirst") {
4620
+ for (const p of sortedParsers) {
4621
+ const r = p.parse(input, pos, ctx);
4622
+ if (r.ok) return r;
4623
+ expected.push(...r.expected);
4624
+ }
4625
+ return { ok: false, expected, span: { start: pos, end: pos } };
4626
+ }
4627
+ for (let i = 0; i < parsers.length; i++) {
4628
+ if (gates[i] && !gates[i](ctx.state)) continue;
4629
+ const mark = saveTriviaMark(ctx);
4630
+ const split = ctx._columnsSplit;
4631
+ const result = parsers[i].parse(input, pos, ctx);
4632
+ if (!result.ok) {
4633
+ rollbackTrivia(ctx, mark);
4634
+ ctx._columnsSplit = split;
4635
+ const at = result.span.start;
4636
+ if (at > expectedAt) {
4637
+ expectedAt = at;
4638
+ expected.length = 0;
4639
+ }
4640
+ if (at === expectedAt) expected.push(...result.expected);
4641
+ if (result.committed) return { ok: false, expected, span: result.span, committed: true };
4642
+ continue;
4643
+ }
4644
+ const checks = autoNot[i];
4645
+ if (checks && autoNotFires(input, result.span.end, checks)) {
4646
+ rollbackTrivia(ctx, mark);
4647
+ continue;
4648
+ }
4649
+ return result;
4650
+ }
4651
+ if (expected.length === 0) {
4652
+ for (const parser2 of parsers) expected.push(...deriveExpected(parser2));
4653
+ }
4654
+ return { ok: false, expected, span: { start: pos, end: pos } };
4655
+ }
4656
+ };
4657
+ }
4658
+ function detectStrategy(parsers) {
4659
+ const regexIndices = [];
4660
+ const literalIndices = [];
4661
+ for (let i = 0; i < parsers.length; i++) {
4662
+ if (getCoreRegexDef(parsers[i]) !== null) regexIndices.push(i);
4663
+ else if (getCoreLiteralValue(parsers[i]) !== null) literalIndices.push(i);
4664
+ }
4665
+ if (regexIndices.length === 1 && literalIndices.length === parsers.length - 1 && literalIndices.length > 0) {
4666
+ const superIndex = regexIndices[0];
4667
+ const regexDef = getCoreRegexDef(parsers[superIndex]);
4668
+ const flags = "y" + regexDef.flags.replace(/[gy]/g, "");
4669
+ const re = new RegExp(regexDef.source, flags);
4670
+ const allSubsumed = literalIndices.every((i) => {
4671
+ const litVal = getCoreLiteralValue(parsers[i]);
4672
+ re.lastIndex = 0;
4673
+ const m = re.exec(litVal);
4674
+ return m !== null && m[0] === litVal;
4675
+ });
4676
+ if (allSubsumed) return { tag: "greedyClassify", superIndex };
4677
+ }
4678
+ if (parsers.length === literalIndices.length) {
4679
+ const sortedIndices = [...literalIndices].sort(
4680
+ (a, b) => getCoreLiteralValue(parsers[b]).length - getCoreLiteralValue(parsers[a]).length
4681
+ );
4682
+ return { tag: "literalsLongestFirst", sortedIndices };
4683
+ }
4684
+ const shared = detectSharedPrefix(parsers);
4685
+ if (shared !== null) return shared;
4686
+ return { tag: "firstMatch" };
4687
+ }
4688
+ function bareLeadingTermKey(term) {
4689
+ const d = term._def;
4690
+ if (d.tag === "literal" && !d.caseInsensitive) return `L:${d.value}`;
4691
+ if (d.tag === "regex") return `R:${JSON.stringify([d.source, d.flags])}`;
4692
+ return null;
4693
+ }
4694
+ function detectSharedPrefix(parsers) {
4695
+ if (parsers.length < 2) return null;
4696
+ let key = null;
4697
+ let prefix = null;
4698
+ const members = [];
4699
+ for (let i = 0; i < parsers.length; i++) {
4700
+ const term0 = leadingTermOfArm(parsers[i]);
4701
+ if (term0 === null) return null;
4702
+ const k = bareLeadingTermKey(term0);
4703
+ if (k === null) return null;
4704
+ if (key === null) {
4705
+ key = k;
4706
+ prefix = term0;
4707
+ } else if (k !== key) return null;
4708
+ members.push(i);
4709
+ }
4710
+ if (prefix === null || members.length < 2) return null;
4711
+ return { tag: "sharedPrefix", prefix, members };
4712
+ }
4713
+ function leadingTermOfArm(arm) {
4378
4714
  let d = arm._def;
4379
4715
  for (; ; ) {
4380
4716
  if (d.tag === "node" || d.tag === "grammar" || d.tag === "transform" || d.tag === "label") {
@@ -6472,361 +6808,98 @@ function token(root) {
6472
6808
  parse(input, pos, ctx) {
6473
6809
  const savedTrivia = ctx.trivia;
6474
6810
  const savedKinds = ctx.triviaKindLabels;
6475
- const savedBuf = ctx._cstBuf;
6476
- const savedChildren = ctx._cstChildren;
6477
- const savedLeaves = ctx._cstLeaves;
6478
- const savedRaw = ctx._cstRawChildren;
6479
- const savedTriviaLog = ctx._cstTriviaLog;
6480
- const savedOuterTriviaLog = ctx._triviaLog;
6481
- const savedRootTriviaLog = ctx._rootTriviaLog;
6482
- const wasCapturing = cstCaptureActive(ctx);
6483
- ctx.trivia = void 0;
6484
- ctx.triviaKindLabels = void 0;
6485
- ctx._cstBuf = void 0;
6486
- ctx._cstChildren = void 0;
6487
- ctx._cstLeaves = void 0;
6488
- ctx._cstRawChildren = void 0;
6489
- ctx._cstTriviaLog = void 0;
6490
- ctx._triviaLog = void 0;
6491
- ctx._rootTriviaLog = void 0;
6492
- let result;
6493
- try {
6494
- result = root.parse(input, pos, ctx);
6495
- } finally {
6496
- ctx.trivia = savedTrivia;
6497
- ctx.triviaKindLabels = savedKinds;
6498
- ctx._cstBuf = savedBuf;
6499
- ctx._cstChildren = savedChildren;
6500
- ctx._cstLeaves = savedLeaves;
6501
- ctx._cstRawChildren = savedRaw;
6502
- ctx._cstTriviaLog = savedTriviaLog;
6503
- ctx._triviaLog = savedOuterTriviaLog;
6504
- ctx._rootTriviaLog = savedRootTriviaLog;
6505
- }
6506
- if (!result.ok) return result;
6507
- const span = result.span;
6508
- const value = input.slice(pos, span.end);
6509
- if (wasCapturing) pushCstLeaf(ctx, new PlainLeaf6(value, span));
6510
- return { ok: true, value, span };
6511
- }
6512
- };
6513
- }
6514
- function makeLeaf(root, fn, sourceCstValue) {
6515
- const cstValue = sourceCstValue ? sourceLeafValue : semanticLeafValue;
6516
- const meta = {
6517
- firstSet: root._meta.firstSet,
6518
- canMatchNewline: root._meta.canMatchNewline,
6519
- isTrivia: false
6520
- };
6521
- return {
6522
- _tag: "leaf",
6523
- _meta: meta,
6524
- _def: {
6525
- tag: "leaf",
6526
- parser: root,
6527
- fn,
6528
- ...sourceCstValue ? { cstValue: "source" } : {}
6529
- },
6530
- parse(input, pos, ctx) {
6531
- const savedBuf = ctx._cstBuf;
6532
- const savedChildren = ctx._cstChildren;
6533
- const savedLeaves = ctx._cstLeaves;
6534
- const savedRaw = ctx._cstRawChildren;
6535
- const savedTriviaLog = ctx._cstTriviaLog;
6536
- const savedOuterTriviaLog = ctx._triviaLog;
6537
- const wasCapturing = cstCaptureActive(ctx);
6538
- ctx._cstBuf = void 0;
6539
- ctx._cstChildren = void 0;
6540
- ctx._cstLeaves = void 0;
6541
- ctx._cstRawChildren = void 0;
6542
- ctx._cstTriviaLog = void 0;
6543
- ctx._triviaLog = void 0;
6544
- let result;
6545
- try {
6546
- result = root.parse(input, pos, ctx);
6547
- } finally {
6548
- ctx._cstBuf = savedBuf;
6549
- ctx._cstChildren = savedChildren;
6550
- ctx._cstLeaves = savedLeaves;
6551
- ctx._cstRawChildren = savedRaw;
6552
- ctx._cstTriviaLog = savedTriviaLog;
6553
- ctx._triviaLog = savedOuterTriviaLog;
6554
- }
6555
- if (!result.ok) return result;
6556
- const value = fn(result.value, result.span);
6557
- if (wasCapturing) pushCstLeaf(ctx, new PlainLeaf6(cstValue(ctx, input, pos, result.span.end, value), result.span));
6558
- return { ok: true, value, span: result.span };
6559
- }
6560
- };
6561
- }
6562
- function leaf(root, fn) {
6563
- return makeLeaf(root, fn, false);
6564
- }
6565
- function sourceLeaf(root, fn) {
6566
- return makeLeaf(root, fn, true);
6567
- }
6568
-
6569
- // src/compiler/value-usage.ts
6570
- function markUnusedValues(root) {
6571
- const seenConsumed = /* @__PURE__ */ new WeakSet();
6572
- const seenUnconsumed = /* @__PURE__ */ new WeakSet();
6573
- const mark = (def, consumed) => {
6574
- if (consumed) def.valueUnused = false;
6575
- else if (def.valueUnused !== false) def.valueUnused = true;
6576
- };
6577
- const visit = (c, consumed) => {
6578
- const seen = consumed ? seenConsumed : seenUnconsumed;
6579
- if (seen.has(c)) return;
6580
- seen.add(c);
6581
- const def = c._def;
6582
- switch (def.tag) {
6583
- case "many":
6584
- case "oneOrMore":
6585
- mark(def, consumed);
6586
- visit(def.parser, consumed);
6587
- return;
6588
- case "optional":
6589
- visit(def.parser, consumed);
6590
- return;
6591
- case "sequence":
6592
- mark(def, consumed);
6593
- for (const p of def.parsers) visit(p, consumed);
6594
- return;
6595
- case "choice":
6596
- for (const p of def.parsers) visit(p, consumed);
6597
- return;
6598
- case "dispatch":
6599
- visit(def.selector, consumed);
6600
- for (const entry of def.cases) visit(entry.parser, consumed);
6601
- if (def.matchers) for (const entry of def.matchers) visit(entry.parser, consumed);
6602
- if (def.otherwise) visit(def.otherwise, consumed);
6603
- return;
6604
- case "node":
6605
- visit(def.parser, false);
6606
- return;
6607
- case "transform":
6608
- visit(def.parser, true);
6609
- return;
6610
- case "field":
6611
- visit(def.parser, true);
6612
- return;
6613
- case "sepBy":
6614
- visit(def.parser, true);
6615
- visit(def.separator, false);
6616
- return;
6617
- case "not":
6618
- case "peek":
6619
- visit(def.parser, false);
6620
- return;
6621
- case "grammar":
6622
- visit(def.parser, consumed);
6623
- if (def.triviaParser) visit(def.triviaParser, false);
6624
- return;
6625
- case "recover":
6626
- visit(def.parser, consumed);
6627
- visit(def.sentinel, false);
6628
- return;
6629
- case "token":
6630
- visit(def.parser, false);
6631
- return;
6632
- case "label":
6633
- case "trivia":
6634
- case "attempt":
6635
- case "withCtx":
6636
- case "expect":
6637
- visit(def.parser, consumed);
6638
- return;
6639
- case "leaf":
6640
- visit(def.parser, true);
6641
- return;
6642
- case "lazy":
6643
- return;
6644
- default:
6645
- return;
6646
- }
6647
- };
6648
- const resolveRoot = (c) => {
6649
- const guard = /* @__PURE__ */ new Set();
6650
- let cur = c;
6651
- while (!guard.has(cur)) {
6652
- const d = cur._def;
6653
- if (d.tag === "grammar") {
6654
- guard.add(cur);
6655
- cur = d.parser;
6656
- continue;
6657
- }
6658
- if (d.tag !== "lazy") return cur;
6659
- guard.add(cur);
6660
- try {
6661
- cur = d.thunk();
6662
- } catch {
6663
- return c;
6664
- }
6665
- }
6666
- return cur;
6667
- };
6668
- visit(resolveRoot(root), true);
6669
- }
6670
-
6671
- // src/cst/root-trivia-scope.ts
6672
- var ROOT_TRIVIA_SCOPE_REFUSAL = "parser(): selected root trivia requires classifiedTrivia() for every local trivia scope, or rootCapture: 'opaque'.";
6673
- function refuseUnclassifiedRootScope(strict) {
6674
- if (strict === true) throw new TypeError(ROOT_TRIVIA_SCOPE_REFUSAL);
6675
- }
6676
-
6677
- // src/combinators/grammar.ts
6678
- function annotateResultLines(result, index) {
6679
- const annotated = { ...result, span: annotateSpan(result.span, index) };
6680
- const errors = annotated.errors;
6681
- if (errors) {
6682
- ;
6683
- annotated.errors = errors.map((error) => ({
6684
- ...error,
6685
- span: annotateSpan(error.span, index)
6686
- }));
6687
- }
6688
- return annotated;
6689
- }
6690
- function createParseLineContext(input, pos) {
6691
- const lineIndex = createLineIndex();
6692
- if (pos > 0) recordLineRange(lineIndex, input, 0, pos);
6693
- return { lineIndex, lineScannedTo: pos };
6694
- }
6695
- var TRACK_LINES_ON = () => true;
6696
- var TRACK_LINES_OFF = () => false;
6697
- var TRACK_LINES_INHERIT = (ctx) => ctx?.trackLines === true;
6698
- function parser(opts, root) {
6699
- const clearTrivia = opts.trivia === null;
6700
- const opaqueRootCapture = opts.rootCapture === "opaque";
6701
- if (opaqueRootCapture && opts.trivia === void 0) {
6702
- throw new TypeError("parser({ rootCapture: 'opaque' }) requires an explicit trivia scope.");
6703
- }
6704
- const scopeTrivia = clearTrivia ? void 0 : opts.trivia ?? void 0;
6705
- const scopeLabels = scopeTrivia?._meta?.triviaKindLabels;
6706
- const refuseUnclassified = scopeTrivia !== void 0 && !scopeTrivia._meta?.rootTriviaClassified && !opaqueRootCapture;
6707
- const forceCaptureTrivia = opts.captureTrivia === true;
6708
- const trackLinesPolicy = opts.trackLines === true ? "on" : opts.trackLines === false ? "off" : "inherit";
6709
- const trackLinesOf = trackLinesPolicy === "on" ? TRACK_LINES_ON : trackLinesPolicy === "off" ? TRACK_LINES_OFF : TRACK_LINES_INHERIT;
6710
- const captureKinds = clearTrivia ? void 0 : opts.captureTriviaKinds;
6711
- const ownCaptureMask = captureKinds === void 0 ? void 0 : scopeLabels !== void 0 ? triviaKindMask(scopeLabels, captureKinds) : void 0;
6712
- const inheritCaptureMask = captureKinds !== void 0 && scopeLabels === void 0;
6713
- const rootScalar = scalarOf(root);
6714
- const scalarEligible = opts.trackLines !== true && opts.recover !== true && !opaqueRootCapture && !forceCaptureTrivia && captureKinds === void 0;
6715
- const parseScalar = scalarEligible ? (input, pos, ctx) => {
6716
- const savedTrivia = ctx.trivia;
6717
- const savedLabels = ctx.triviaKindLabels;
6718
- if (clearTrivia) {
6811
+ const savedBuf = ctx._cstBuf;
6812
+ const savedChildren = ctx._cstChildren;
6813
+ const savedLeaves = ctx._cstLeaves;
6814
+ const savedRaw = ctx._cstRawChildren;
6815
+ const savedTriviaLog = ctx._cstTriviaLog;
6816
+ const savedOuterTriviaLog = ctx._triviaLog;
6817
+ const savedRootTriviaLog = ctx._rootTriviaLog;
6818
+ const wasCapturing = cstCaptureActive(ctx);
6719
6819
  ctx.trivia = void 0;
6720
6820
  ctx.triviaKindLabels = void 0;
6721
- } else if (scopeTrivia !== void 0) {
6722
- ctx.trivia = scopeTrivia;
6723
- ctx.triviaKindLabels = scopeLabels;
6821
+ ctx._cstBuf = void 0;
6822
+ ctx._cstChildren = void 0;
6823
+ ctx._cstLeaves = void 0;
6824
+ ctx._cstRawChildren = void 0;
6825
+ ctx._cstTriviaLog = void 0;
6826
+ ctx._triviaLog = void 0;
6827
+ ctx._rootTriviaLog = void 0;
6828
+ let result;
6829
+ try {
6830
+ result = root.parse(input, pos, ctx);
6831
+ } finally {
6832
+ ctx.trivia = savedTrivia;
6833
+ ctx.triviaKindLabels = savedKinds;
6834
+ ctx._cstBuf = savedBuf;
6835
+ ctx._cstChildren = savedChildren;
6836
+ ctx._cstLeaves = savedLeaves;
6837
+ ctx._cstRawChildren = savedRaw;
6838
+ ctx._cstTriviaLog = savedTriviaLog;
6839
+ ctx._triviaLog = savedOuterTriviaLog;
6840
+ ctx._rootTriviaLog = savedRootTriviaLog;
6841
+ }
6842
+ if (!result.ok) return result;
6843
+ const span = result.span;
6844
+ const value = input.slice(pos, span.end);
6845
+ if (wasCapturing) pushCstLeaf(ctx, new PlainLeaf6(value, span));
6846
+ return { ok: true, value, span };
6724
6847
  }
6725
- const end = rootScalar(input, pos, ctx);
6726
- ctx.trivia = savedTrivia;
6727
- ctx.triviaKindLabels = savedLabels;
6728
- return end;
6729
- } : void 0;
6730
- let publicScalar;
6731
- const grammar = {
6732
- _tag: "grammar",
6733
- _meta: {
6734
- ...root._meta,
6735
- // Trivia classification describes this grammar's own active trivia
6736
- // scope. A directly nested grammar may have classified trivia of its
6737
- // own, but that must not advertise classification for this wrapper.
6738
- triviaKindLabels: void 0,
6739
- rootTriviaClassified: void 0,
6740
- ...opts.trivia?._meta?.triviaKindLabels ? { triviaKindLabels: opts.trivia._meta.triviaKindLabels } : {},
6741
- ...opts.trivia?._meta?.rootTriviaClassified ? { rootTriviaClassified: true } : {}
6742
- },
6848
+ };
6849
+ }
6850
+ function makeLeaf(root, fn, sourceCstValue) {
6851
+ const cstValue = sourceCstValue ? sourceLeafValue : semanticLeafValue;
6852
+ const meta = {
6853
+ firstSet: root._meta.firstSet,
6854
+ canMatchNewline: root._meta.canMatchNewline,
6855
+ isTrivia: false
6856
+ };
6857
+ return {
6858
+ _tag: "leaf",
6859
+ _meta: meta,
6743
6860
  _def: {
6744
- tag: "grammar",
6861
+ tag: "leaf",
6745
6862
  parser: root,
6746
- triviaParser: scopeTrivia,
6747
- clearTrivia,
6748
- ...opaqueRootCapture ? { rootCapture: "opaque" } : {},
6749
- ...opts.captureTrivia ? { captureTrivia: true } : {},
6750
- trackLines: opts.trackLines ?? false,
6751
- constructionTrackLines: trackLinesPolicy,
6752
- ...captureKinds === void 0 ? {} : { constructionCaptureTriviaKinds: captureKinds }
6863
+ fn,
6864
+ ...sourceCstValue ? { cstValue: "source" } : {}
6753
6865
  },
6754
- _parseScalar: parseScalar,
6755
- parse(input, pos, _ctx) {
6756
- if (pos === void 0 && _ctx === void 0) {
6757
- publicScalar ??= scalarRootOf(grammar) ?? null;
6758
- if (publicScalar) {
6759
- const ctx2 = createParseContext();
6760
- const end = publicScalar(input, 0, ctx2);
6761
- if (end < 0) {
6762
- const at = ~end;
6763
- return { ok: false, expected: ctx2._fx ?? [], span: { start: at, end: at } };
6764
- }
6765
- return { ok: true, value: ctx2._sv, span: { start: 0, end } };
6766
- }
6767
- }
6768
- if (refuseUnclassified) refuseUnclassifiedRootScope(_ctx?._rootTriviaStrictScopes);
6769
- const trackLines = trackLinesOf(_ctx);
6770
- const lineContext = trackLines && _ctx?._lineIndex === void 0 && _ctx?._lineStarts === void 0 ? createParseLineContext(input, pos ?? 0) : void 0;
6771
- const lineIndex = trackLines ? _ctx?._lineIndex ?? (_ctx?._lineStarts ? { lineStarts: _ctx._lineStarts } : lineContext.lineIndex) : void 0;
6772
- const ctx = _ctx === void 0 ? createParseContext() : { ..._ctx };
6773
- ctx.trackLines = trackLines;
6774
- if (lineIndex) ctx._lineIndex = lineIndex;
6775
- if (lineContext) ctx._lineScannedTo = lineContext.lineScannedTo;
6776
- if (clearTrivia) {
6777
- ctx.trivia = void 0;
6778
- ctx.triviaKindLabels = void 0;
6779
- } else if (scopeTrivia !== void 0) {
6780
- ctx.trivia = scopeTrivia;
6781
- if (scopeLabels) ctx.triviaKindLabels = scopeLabels;
6782
- }
6783
- if (forceCaptureTrivia || _ctx?.captureTrivia) ctx.captureTrivia = true;
6784
- if (ownCaptureMask !== void 0) ctx._triviaCaptureMask = ownCaptureMask;
6785
- else if (inheritCaptureMask) ctx._triviaCaptureMask = triviaKindMask(_ctx?.triviaKindLabels, captureKinds);
6786
- if (opaqueRootCapture) ctx._rootTriviaCapture = false;
6787
- const result = root.parse(input, pos ?? 0, ctx);
6788
- if (trackLines && _ctx && ctx._lineScannedTo !== void 0) {
6789
- _ctx._lineScannedTo = Math.max(_ctx._lineScannedTo ?? 0, ctx._lineScannedTo);
6866
+ parse(input, pos, ctx) {
6867
+ const savedBuf = ctx._cstBuf;
6868
+ const savedChildren = ctx._cstChildren;
6869
+ const savedLeaves = ctx._cstLeaves;
6870
+ const savedRaw = ctx._cstRawChildren;
6871
+ const savedTriviaLog = ctx._cstTriviaLog;
6872
+ const savedOuterTriviaLog = ctx._triviaLog;
6873
+ const wasCapturing = cstCaptureActive(ctx);
6874
+ ctx._cstBuf = void 0;
6875
+ ctx._cstChildren = void 0;
6876
+ ctx._cstLeaves = void 0;
6877
+ ctx._cstRawChildren = void 0;
6878
+ ctx._cstTriviaLog = void 0;
6879
+ ctx._triviaLog = void 0;
6880
+ let result;
6881
+ try {
6882
+ result = root.parse(input, pos, ctx);
6883
+ } finally {
6884
+ ctx._cstBuf = savedBuf;
6885
+ ctx._cstChildren = savedChildren;
6886
+ ctx._cstLeaves = savedLeaves;
6887
+ ctx._cstRawChildren = savedRaw;
6888
+ ctx._cstTriviaLog = savedTriviaLog;
6889
+ ctx._triviaLog = savedOuterTriviaLog;
6790
6890
  }
6791
- return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
6891
+ if (!result.ok) return result;
6892
+ const value = fn(result.value, result.span);
6893
+ if (wasCapturing) pushCstLeaf(ctx, new PlainLeaf6(cstValue(ctx, input, pos, result.span.end, value), result.span));
6894
+ return { ok: true, value, span: result.span };
6792
6895
  }
6793
6896
  };
6794
- return grammar;
6795
6897
  }
6796
- function noTrivia(root) {
6797
- return parser({ trivia: null }, root);
6898
+ function leaf(root, fn) {
6899
+ return makeLeaf(root, fn, false);
6798
6900
  }
6799
- var _analyzed = /* @__PURE__ */ new WeakSet();
6800
- function parse(combinator, input, opts = {}) {
6801
- if (!_analyzed.has(combinator)) {
6802
- _analyzed.add(combinator);
6803
- markUnusedValues(combinator);
6804
- }
6805
- if (!opts.trackLines && !opts.recover && combinator._def.tag === "grammar" && combinator._meta.grammarScanSkip === void 0) {
6806
- return combinator.parse(input);
6807
- }
6808
- const trackLines = opts.trackLines ?? combinator._meta.grammarTrackLines ?? false;
6809
- const lineContext = trackLines ? createParseLineContext(input, 0) : void 0;
6810
- const lineIndex = lineContext?.lineIndex;
6811
- const _errors = opts.recover ? [] : void 0;
6812
- const _probe = opts.recover ? { offset: input.length, best: null } : void 0;
6813
- const grammarTrivia = combinator._meta.grammarTrivia;
6814
- const grammarScanSkip = combinator._meta.grammarScanSkip;
6815
- const ctx = createParseContext();
6816
- ctx.trackLines = trackLines;
6817
- if (lineIndex) ctx._lineIndex = lineIndex;
6818
- if (lineContext) ctx._lineScannedTo = lineContext.lineScannedTo;
6819
- if (grammarTrivia !== void 0) {
6820
- ctx.trivia = grammarTrivia;
6821
- if (grammarTrivia._meta.triviaKindLabels) ctx.triviaKindLabels = grammarTrivia._meta.triviaKindLabels;
6822
- }
6823
- if (grammarScanSkip !== void 0) ctx.scanSkip = grammarScanSkip;
6824
- if (_errors !== void 0) ctx._errors = _errors;
6825
- if (_probe !== void 0) ctx._probe = _probe;
6826
- const result = combinator.parse(input, 0, ctx);
6827
- if (!result.ok) return lineIndex ? annotateResultLines(result, normalizeLineIndex(lineIndex)) : result;
6828
- const withErrors = _errors !== void 0 ? { ...result, errors: _errors, furthestFail: _probe?.best ?? null } : result;
6829
- return lineIndex ? annotateResultLines(withErrors, normalizeLineIndex(lineIndex)) : withErrors;
6901
+ function sourceLeaf(root, fn) {
6902
+ return makeLeaf(root, fn, true);
6830
6903
  }
6831
6904
 
6832
6905
  // src/combinators/attempt.ts
@@ -7110,6 +7183,7 @@ var OP_LIT_CI = 27;
7110
7183
  var OP_LIT_CI_TRACK = 28;
7111
7184
  var OP_TOKEN = 29;
7112
7185
  var OP_SCOPE_CAP = 30;
7186
+ var SCOPE_INHERIT = -2;
7113
7187
  var OP_WITHCTX = 31;
7114
7188
  var OP_GUARD = 32;
7115
7189
  var OP_ADJ = 33;
@@ -8909,7 +8983,7 @@ var Encoder = class {
8909
8983
  this.triviaKnown = savedKnown;
8910
8984
  if (d.clearTrivia === true) return this.emit(op, -1, bodyIp, flags);
8911
8985
  if (d.triviaParser === void 0) {
8912
- return cap || flags !== 0 ? this.emit(op, -1, bodyIp, flags) : bodyIp;
8986
+ return cap ? this.emit(op, SCOPE_INHERIT, bodyIp, flags) : bodyIp;
8913
8987
  }
8914
8988
  return this.emit(op, this.triviaSlot(d.triviaParser), bodyIp, flags);
8915
8989
  }
@@ -10301,7 +10375,7 @@ function transfer(code, ip, at, hostCst) {
10301
10375
  const op = code[ip];
10302
10376
  if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
10303
10377
  const ki = code[ip + 1];
10304
- const tri = ki < 0 ? TRI_NONE : ki;
10378
+ const tri = ki === SCOPE_INHERIT ? at.tri : ki < 0 ? TRI_NONE : ki;
10305
10379
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
10306
10380
  if (tri === at.tri && cap === at.cap) return at;
10307
10381
  return { tri, buf: at.buf, raw: at.raw, cap };
@@ -10375,7 +10449,7 @@ function scanHandoffNeeded(code, ip, labels) {
10375
10449
  if (l.tri === TRI_UNKNOWN) return true;
10376
10450
  const op = code[at];
10377
10451
  if (op === OP_SCAN) return true;
10378
- if (op === OP_TOKEN || op === OP_SCOPE_CAP) continue;
10452
+ if (op === OP_TOKEN || op === OP_SCOPE_CAP && code[at + 1] !== SCOPE_INHERIT) continue;
10379
10453
  if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE) && !(code[at + 1] >= 0 && l.tri === code[at + 1] && (op === OP_SCOPE_PLAIN || code[at + 3] === 0))) continue;
10380
10454
  kids.length = 0;
10381
10455
  if (!childSlots(code, at, kids)) return true;
@@ -11670,6 +11744,15 @@ return r.value
11670
11744
  const cap = op === OP_SCOPE_CAP;
11671
11745
  const flags = op === OP_SCOPE_PLAIN ? 0 : code[ip + 3];
11672
11746
  const child = link(code[ip + 2]);
11747
+ if (ki === SCOPE_INHERIT) {
11748
+ return `${head}
11749
+ const sC=ctx.captureTrivia
11750
+ ctx.captureTrivia=true
11751
+ const v=${child}(input,pos,ctx)
11752
+ ctx.captureTrivia=sC
11753
+ return v
11754
+ }`;
11755
+ }
11673
11756
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
11674
11757
  const tri = ki < 0 ? "undefined" : hoist("tv", `TRIVIA[${ki}]`);
11675
11758
  const lab = ki < 0 ? "undefined" : hoist("tl", `TRIVIA[${ki}]._meta.triviaKindLabels`);
@@ -13029,73 +13112,6 @@ function literal(value, opts = {}) {
13029
13112
  };
13030
13113
  }
13031
13114
 
13032
- // src/combinators/ref.ts
13033
- function withRuleTrivia(trivia2, ctx, run) {
13034
- const savedLabels = ctx.triviaKindLabels;
13035
- ctx.trivia = trivia2;
13036
- ctx.triviaKindLabels = trivia2._meta.triviaKindLabels;
13037
- try {
13038
- return run();
13039
- } finally {
13040
- ctx.trivia = void 0;
13041
- ctx.triviaKindLabels = savedLabels;
13042
- }
13043
- }
13044
- var UNDEFINED_REF = new Error("ref<T>() used before .define() was called");
13045
- function ref() {
13046
- let resolved = null;
13047
- let resolvedScalar = null;
13048
- let ownBoundary = false;
13049
- const meta = {
13050
- firstSet: any(),
13051
- canMatchNewline: true,
13052
- isTrivia: false
13053
- };
13054
- const slot = {
13055
- _tag: "lazy",
13056
- _meta: meta,
13057
- _def: {
13058
- tag: "lazy",
13059
- thunk: () => {
13060
- if (!resolved) throw UNDEFINED_REF;
13061
- return resolved;
13062
- }
13063
- },
13064
- _parseScalar(input, pos, ctx) {
13065
- const scalar = resolvedScalar;
13066
- if (!scalar) throw new Error("ref<T>() used before .define() was called");
13067
- const gt = meta.grammarTrivia;
13068
- if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
13069
- return withRuleTrivia(gt, ctx, () => scalar(input, pos, ctx));
13070
- }
13071
- return scalar(input, pos, ctx);
13072
- },
13073
- parse(input, pos, ctx) {
13074
- const parser2 = resolved;
13075
- if (!parser2) throw new Error("ref<T>() used before .define() was called");
13076
- const gt = meta.grammarTrivia;
13077
- if (gt !== void 0 && ownBoundary && ctx.trivia === void 0) {
13078
- return withRuleTrivia(gt, ctx, () => parser2.parse(input, pos, ctx));
13079
- }
13080
- return parser2.parse(input, pos, ctx);
13081
- },
13082
- define(p) {
13083
- if (resolved) throw new Error("ref<T>() already defined");
13084
- resolved = p;
13085
- resolvedScalar = scalarOf(p);
13086
- ownBoundary = hasOwnTriviaBoundary(p);
13087
- meta.firstSet = p._meta.firstSet;
13088
- meta.canMatchNewline = p._meta.canMatchNewline;
13089
- meta.isTrivia = p._meta.isTrivia;
13090
- if (p._meta.triviaKindLabels !== void 0) meta.triviaKindLabels = p._meta.triviaKindLabels;
13091
- else delete meta.triviaKindLabels;
13092
- if (p._meta.disjoint !== void 0) meta.disjoint = p._meta.disjoint;
13093
- else delete meta.disjoint;
13094
- }
13095
- };
13096
- return slot;
13097
- }
13098
-
13099
13115
  // src/combinators/scanTo.ts
13100
13116
  import { PlainLeaf as PlainLeaf8, PlainSpan as PlainSpan9 } from "../cst/plain.js";
13101
13117
  function resolveScanSkip(explicitSkip, raw, ctx) {
@@ -13415,7 +13431,7 @@ function clearOf(ranges, input, from, to) {
13415
13431
  }
13416
13432
 
13417
13433
  // src/version.ts
13418
- var PARSEMAN_VERSION = "0.60.4";
13434
+ var PARSEMAN_VERSION = "0.60.6";
13419
13435
 
13420
13436
  // src/table/assemble.ts
13421
13437
  import { PlainBuf as PlainBuf2, PlainField, PlainLeaf as PlainLeaf9, PlainNode as PlainNode2, PlainSpan as PlainSpan10 } from "../cst/plain.js";
@@ -14928,6 +14944,16 @@ function assemble(t2, prog, cfg) {
14928
14944
  case OP_SCOPE_CAP:
14929
14945
  case OP_SCOPE_PLAIN: {
14930
14946
  const ki = code[ip + 1];
14947
+ if (ki === SCOPE_INHERIT) {
14948
+ const body = link(code[ip + 2]);
14949
+ return (input, pos, ctx) => {
14950
+ const savedCap = ctx.captureTrivia;
14951
+ ctx.captureTrivia = true;
14952
+ const v = body(input, pos, ctx);
14953
+ ctx.captureTrivia = savedCap;
14954
+ return v;
14955
+ };
14956
+ }
14931
14957
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
14932
14958
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
14933
14959
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? triviaScan[ki] : null;