parseman 0.47.0 → 0.47.1

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 (57) hide show
  1. package/dist/analysis/diagnostics.cjs +133 -45
  2. package/dist/analysis/diagnostics.cjs.map +2 -2
  3. package/dist/analysis/diagnostics.js +133 -45
  4. package/dist/analysis/diagnostics.js.map +2 -2
  5. package/dist/cli/index.cjs +133 -45
  6. package/dist/cli/index.cjs.map +2 -2
  7. package/dist/cli/index.js +133 -45
  8. package/dist/cli/index.js.map +2 -2
  9. package/dist/combinators/first-set.d.ts.map +1 -1
  10. package/dist/combinators/sequence.d.ts.map +1 -1
  11. package/dist/combinators/trivia-skip.d.ts +5 -0
  12. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  13. package/dist/index.cjs +134 -46
  14. package/dist/index.cjs.map +2 -2
  15. package/dist/index.js +134 -46
  16. package/dist/index.js.map +2 -2
  17. package/dist/language-service/index.cjs +3 -1
  18. package/dist/language-service/index.cjs.map +1 -1
  19. package/dist/language-service/index.js +3 -1
  20. package/dist/language-service/index.js.map +1 -1
  21. package/dist/plugin/index.cjs +134 -46
  22. package/dist/plugin/index.cjs.map +2 -2
  23. package/dist/plugin/index.js +134 -46
  24. package/dist/plugin/index.js.map +2 -2
  25. package/dist/spec/index.cjs +55 -7
  26. package/dist/spec/index.cjs.map +1 -1
  27. package/dist/spec/index.js +55 -7
  28. package/dist/spec/index.js.map +1 -1
  29. package/dist/table/assemble.d.ts.map +1 -1
  30. package/dist/table/emit-assembly.d.ts +2 -2
  31. package/dist/table/emit-assembly.d.ts.map +1 -1
  32. package/dist/table/emit.d.ts.map +1 -1
  33. package/dist/table/exec.d.ts.map +1 -1
  34. package/dist/table/index.cjs +1566 -1478
  35. package/dist/table/index.cjs.map +3 -3
  36. package/dist/table/index.js +1566 -1478
  37. package/dist/table/index.js.map +3 -3
  38. package/dist/table/ops.d.ts +8 -1
  39. package/dist/table/ops.d.ts.map +1 -1
  40. package/dist/table/program.d.ts +4 -1
  41. package/dist/table/program.d.ts.map +1 -1
  42. package/dist/version.d.ts +1 -1
  43. package/package.json +2 -1
  44. package/src/combinators/first-set.ts +29 -3
  45. package/src/combinators/sequence.ts +23 -7
  46. package/src/combinators/trivia-skip.ts +31 -0
  47. package/src/table/assemble.ts +30 -18
  48. package/src/table/child-slots.ts +2 -2
  49. package/src/table/emit-assembly.ts +36 -25
  50. package/src/table/emit.ts +12 -1
  51. package/src/table/encode.ts +4 -4
  52. package/src/table/exec.ts +20 -12
  53. package/src/table/ops.ts +9 -1
  54. package/src/table/program.ts +22 -1
  55. package/src/table/site-labels.ts +2 -2
  56. package/src/table/stamp.ts +2 -2
  57. package/src/version.ts +1 -1
package/dist/index.js CHANGED
@@ -44,6 +44,13 @@ function empty() {
44
44
  function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve) {
45
45
  if (seen.has(p)) return true;
46
46
  seen.add(p);
47
+ try {
48
+ return matchesEmptyBody(p, seen, resolve);
49
+ } finally {
50
+ seen.delete(p);
51
+ }
52
+ }
53
+ function matchesEmptyBody(p, seen, resolve) {
47
54
  const me = (c) => matchesEmpty(c, seen, resolve);
48
55
  const d = p._def;
49
56
  switch (d.tag) {
@@ -145,6 +152,13 @@ function sequenceFirstSet(parsers) {
145
152
  function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve) {
146
153
  if (seen.has(p)) return any();
147
154
  seen.add(p);
155
+ try {
156
+ return firstSetBody(p, seen, resolve);
157
+ } finally {
158
+ seen.delete(p);
159
+ }
160
+ }
161
+ function firstSetBody(p, seen, resolve) {
148
162
  const fs = (c) => firstSetOf(c, seen, resolve);
149
163
  const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve);
150
164
  const d = p._def;
@@ -1636,6 +1650,23 @@ function rollbackTrivia(ctx, mark) {
1636
1650
  if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
1637
1651
  if (ctx._rootTriviaLog && ctx._rootTriviaLog.length !== mark.rootLog) ctx._rootTriviaLog.length = mark.rootLog;
1638
1652
  }
1653
+ function removeNumberRange(values, start, end) {
1654
+ if (values === void 0 || end <= start) return;
1655
+ if (values.length > end) values.copyWithin(start, end);
1656
+ values.length -= end - start;
1657
+ }
1658
+ function rollbackScannedTriviaAt(ctx, tlogStart, tlogEnd, logStart, logEnd, rootLogStart, rootLogEnd) {
1659
+ const b = ctx._cstBuf;
1660
+ if (b !== void 0) {
1661
+ const tlog = b.tl;
1662
+ removeNumberRange(tlog, tlogStart, tlogEnd);
1663
+ if (tlog !== void 0 && tlog.length === 0) b.tl = void 0;
1664
+ } else {
1665
+ removeNumberRange(ctx._cstTriviaLog, tlogStart, tlogEnd);
1666
+ }
1667
+ removeNumberRange(ctx._triviaLog, logStart, logEnd);
1668
+ removeNumberRange(ctx._rootTriviaLog, rootLogStart, rootLogEnd);
1669
+ }
1639
1670
  function parseTriviaNoCapture(triviaP, input, cur, ctx) {
1640
1671
  const probeCtx = createDetachedParseContext(ctx.trackLines, ctx.state);
1641
1672
  probeCtx._lineIndex = ctx._lineIndex;
@@ -2340,7 +2371,9 @@ function sequence(...parsers) {
2340
2371
  continue;
2341
2372
  }
2342
2373
  if (ctx.trivia && i > 0) {
2343
- const mark = saveTriviaMark(ctx);
2374
+ const mTlog = cstTlLen(ctx);
2375
+ const mLog = ctx._triviaLog?.length ?? 0;
2376
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2344
2377
  let scanEnd;
2345
2378
  if (needsDeferredTriviaCommit(ctx)) {
2346
2379
  const scan = scanTrivia(input, cur, ctx);
@@ -2349,10 +2382,13 @@ function sequence(...parsers) {
2349
2382
  } else {
2350
2383
  scanEnd = advanceTrivia(input, cur, ctx);
2351
2384
  }
2385
+ const scanTlog = cstTlLen(ctx);
2386
+ const scanLog = ctx._triviaLog?.length ?? 0;
2387
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2352
2388
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2353
2389
  if (!result2.ok) return result2;
2354
2390
  if (result2.span.end > scanEnd) cur = result2.span.end;
2355
- else rollbackTrivia(ctx, mark);
2391
+ else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2356
2392
  if (values !== void 0) values.push(result2.value);
2357
2393
  continue;
2358
2394
  }
@@ -2383,7 +2419,9 @@ function sequence(...parsers) {
2383
2419
  }
2384
2420
  if (ctx.trivia && i > 0) {
2385
2421
  let scanEnd;
2386
- const mark = saveTriviaMark(ctx);
2422
+ const mTlog = cstTlLen(ctx);
2423
+ const mLog = ctx._triviaLog?.length ?? 0;
2424
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2387
2425
  if (needsDeferredTriviaCommit(ctx)) {
2388
2426
  const scan = scanTrivia(input, cur, ctx);
2389
2427
  scan.commit();
@@ -2391,10 +2429,13 @@ function sequence(...parsers) {
2391
2429
  } else {
2392
2430
  scanEnd = advanceTrivia(input, cur, ctx);
2393
2431
  }
2432
+ const scanTlog = cstTlLen(ctx);
2433
+ const scanLog = ctx._triviaLog?.length ?? 0;
2434
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2394
2435
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2395
2436
  if (!result2.ok) return result2;
2396
2437
  if (result2.span.end > scanEnd) cur = result2.span.end;
2397
- else rollbackTrivia(ctx, mark);
2438
+ else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2398
2439
  if (values !== void 0) values.push(result2.value);
2399
2440
  continue;
2400
2441
  }
@@ -2422,7 +2463,9 @@ function sequence(...parsers) {
2422
2463
  for (let i = 0; i < parsers.length; i++) {
2423
2464
  if (ctx.trivia && i > 0) {
2424
2465
  let scanEnd;
2425
- let mark = saveTriviaMark(ctx);
2466
+ const mTlog = cstTlLen(ctx);
2467
+ const mLog = ctx._triviaLog?.length ?? 0;
2468
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2426
2469
  if (needsDeferredTriviaCommit(ctx)) {
2427
2470
  const scan = scanTrivia(input, cur, ctx);
2428
2471
  scan.commit();
@@ -2430,12 +2473,15 @@ function sequence(...parsers) {
2430
2473
  } else {
2431
2474
  scanEnd = advanceTrivia(input, cur, ctx);
2432
2475
  }
2476
+ const scanTlog = cstTlLen(ctx);
2477
+ const scanLog = ctx._triviaLog?.length ?? 0;
2478
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2433
2479
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2434
2480
  if (!result2.ok) return result2;
2435
2481
  if (result2.span.end > scanEnd) {
2436
2482
  cur = result2.span.end;
2437
2483
  } else {
2438
- rollbackTrivia(ctx, mark);
2484
+ rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2439
2485
  }
2440
2486
  if (values !== void 0) values.push(result2.value);
2441
2487
  continue;
@@ -5057,6 +5103,7 @@ var OP_LIVE = 37;
5057
5103
  var OP_ATTEMPT = 38;
5058
5104
  var OP_LABEL = 39;
5059
5105
  var OP_COV = 40;
5106
+ var OP_SCOPE_PLAIN = 41;
5060
5107
  var OP_DISPATCH = 25;
5061
5108
  var OP_ROUTED = 26;
5062
5109
  var OP_NAMES = {
@@ -5099,7 +5146,8 @@ var OP_NAMES = {
5099
5146
  [OP_LIVE]: "LIVE",
5100
5147
  [OP_ATTEMPT]: "ATTEMPT",
5101
5148
  [OP_LABEL]: "LABEL",
5102
- [OP_COV]: "COV"
5149
+ [OP_COV]: "COV",
5150
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
5103
5151
  };
5104
5152
 
5105
5153
  // src/table/program.ts
@@ -5157,6 +5205,15 @@ function expandCompact(p) {
5157
5205
  ...p.a === void 0 ? {} : { asm: p.a }
5158
5206
  });
5159
5207
  }
5208
+ function validateDispatchSpec(spec, arity, fallbackRouted) {
5209
+ const invalid = (arms) => {
5210
+ for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
5211
+ return false;
5212
+ };
5213
+ if (spec === void 0 || !Number.isInteger(arity) || arity < 0 || fallbackRouted !== 0 && fallbackRouted !== 1 || spec.routed.length !== arity || spec.routed.some((value) => value !== 0 && value !== 1) || invalid(spec.byKey.values()) || invalid(spec.byFold.values()) || spec.match.some((matcher) => invalid([matcher[3]]))) {
5214
+ throw new TypeError("table: malformed dispatch");
5215
+ }
5216
+ }
5160
5217
  var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
5161
5218
  function ownTableProgram(prog, resolved) {
5162
5219
  return { ...prog, [TABLE_RUNTIME]: { resolved } };
@@ -5715,7 +5772,7 @@ var Encoder = class {
5715
5772
  this.carryTriviaMeta(amb);
5716
5773
  this.carryTriviaMeta(p);
5717
5774
  if (p._def.tag === "grammar") this.carryTriviaMeta(p._def.triviaParser);
5718
- this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE, this.triviaSlot(amb), body);
5775
+ this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), body);
5719
5776
  }
5720
5777
  /**
5721
5778
  * The row a cross-rule `g.X` reference jumps to — the target's body, RE-WRAPPED
@@ -5758,7 +5815,7 @@ var Encoder = class {
5758
5815
  const amb = p._meta.grammarTrivia ?? target._meta.grammarTrivia;
5759
5816
  if (amb === void 0 || this.activeTrivia !== void 0) return ip;
5760
5817
  if (!hasOwnTriviaBoundary(target)) return ip;
5761
- return this.emit(OP_SCOPE, this.triviaSlot(amb), ip);
5818
+ return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
5762
5819
  }
5763
5820
  node(p) {
5764
5821
  const lazyRef = p._def.tag === "lazy";
@@ -6163,6 +6220,7 @@ var Encoder = class {
6163
6220
  return [ip + 1];
6164
6221
  case OP_SCOPE:
6165
6222
  case OP_SCOPE_CAP:
6223
+ case OP_SCOPE_PLAIN:
6166
6224
  case OP_WITHCTX:
6167
6225
  case OP_XFORM:
6168
6226
  case OP_LEAF:
@@ -7356,6 +7414,7 @@ function childSlots(code, ip, out) {
7356
7414
  case OP_GATE:
7357
7415
  case OP_SCOPE:
7358
7416
  case OP_SCOPE_CAP:
7417
+ case OP_SCOPE_PLAIN:
7359
7418
  case OP_WITHCTX:
7360
7419
  case OP_XFORM:
7361
7420
  case OP_NODE:
@@ -7444,7 +7503,7 @@ function reachableSites(code, roots) {
7444
7503
  }
7445
7504
  function transfer(code, ip, at, hostCst) {
7446
7505
  const op = code[ip];
7447
- if (op === OP_SCOPE || op === OP_SCOPE_CAP) {
7506
+ if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
7448
7507
  const ki = code[ip + 1];
7449
7508
  const tri = ki < 0 ? TRI_NONE : ki;
7450
7509
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
@@ -7525,6 +7584,7 @@ var EMITTED_PARAMS = [
7525
7584
  "pushCstLeaf",
7526
7585
  "pushCstChild",
7527
7586
  "rollbackTriviaAt",
7587
+ "rollbackScannedTriviaAt",
7528
7588
  "failAt",
7529
7589
  "classHas",
7530
7590
  "consumeTrivia",
@@ -7668,19 +7728,24 @@ if(ctx._errors!==undefined&&ctx._errors.length!==${t}er)ctx._errors.length=${t}e
7668
7728
  if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,0,undefined,${t}lg,${t}rt)`;
7669
7729
  return `if(${t}n){rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,${s.fd ? `${t}fd` : "0"},${s.er ? `${t}er` : "undefined"},${t}lg,${t}rt)}`;
7670
7730
  }
7671
- function emitTerm(callee, dst, t, l, skip, s) {
7731
+ function emitTerm(callee, dst, t, l, skip) {
7672
7732
  const fast = `const ${t}v=${callee}(input,cur,ctx)
7673
7733
  if(${t}v===FAIL)return FAIL
7674
7734
  ${dst}=${t}v
7675
7735
  cur=EC.e`;
7676
7736
  if (l.tri === TRI_NONE) return fast;
7677
- const scanned = `${emitMark(t, l.buf, s)}
7737
+ const scanned = `const ${t}tl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
7738
+ const ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
7739
+ const ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7678
7740
  const ${t}s=${skip}(input,cur,ctx)
7741
+ const ${t}stl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
7742
+ const ${t}slg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
7743
+ const ${t}srt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7679
7744
  const ${t}v=${callee}(input,${t}s,ctx)
7680
7745
  if(${t}v===FAIL)return FAIL
7681
7746
  ${dst}=${t}v
7682
7747
  if(EC.e>${t}s)cur=EC.e
7683
- else{${emitRollback(t, l.buf, s)}}`;
7748
+ else{rollbackScannedTriviaAt(ctx,${t}tl,${t}stl,${t}lg,${t}slg,${t}rt,${t}srt)}`;
7684
7749
  if (l.tri !== TRI_UNKNOWN) return scanned;
7685
7750
  return `if(ctx.trivia===undefined){
7686
7751
  ${fast}
@@ -7843,7 +7908,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7843
7908
  const op = code[ip];
7844
7909
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
7845
7910
  if (op === OP_RULE) return code[ip + 1];
7846
- if (op === OP_SCOPE && code[ip + 3] === 0 && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
7911
+ if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
7847
7912
  return code[ip + 2];
7848
7913
  }
7849
7914
  return void 0;
@@ -8011,10 +8076,11 @@ return r.value
8011
8076
  }`;
8012
8077
  }
8013
8078
  case OP_SCOPE:
8014
- case OP_SCOPE_CAP: {
8079
+ case OP_SCOPE_CAP:
8080
+ case OP_SCOPE_PLAIN: {
8015
8081
  const ki = code[ip + 1];
8016
8082
  const cap = op === OP_SCOPE_CAP;
8017
- const flags = code[ip + 3];
8083
+ const flags = op === OP_SCOPE_PLAIN ? 0 : code[ip + 3];
8018
8084
  const child = link(code[ip + 2]);
8019
8085
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
8020
8086
  const tri = ki < 0 ? "undefined" : hoist("tv", `TRIVIA[${ki}]`);
@@ -8168,7 +8234,7 @@ return v
8168
8234
  const vn = `v${i}`;
8169
8235
  parts.push(`let ${vn}`);
8170
8236
  if (REC2) parts.push(pub(i));
8171
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L), sinks));
8237
+ parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
8172
8238
  names.push(vn);
8173
8239
  }
8174
8240
  parts.push("EC.e=cur");
@@ -8269,11 +8335,11 @@ return FAIL
8269
8335
  const other = otherIp >= 0 ? link(otherIp) : void 0;
8270
8336
  const otherRouted = code[ip + 4] === 1;
8271
8337
  const n = code[ip + 5];
8338
+ validateDispatchSpec(spec, n, code[ip + 4]);
8272
8339
  const armBase = ip + 6;
8273
8340
  const arms = [];
8274
8341
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
8275
8342
  const bk = hoist("bk", `DSP[${di}].byKey`);
8276
- const rt = hoist("rt", `DSP[${di}].routed`);
8277
8343
  const dx = hoist("dx", `DSP[${di}].expected`);
8278
8344
  const claims = (m) => {
8279
8345
  switch (m[0]) {
@@ -8297,6 +8363,15 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
8297
8363
  ` : "";
8298
8364
  const m1 = tmp();
8299
8365
  const m2 = tmp();
8366
+ const routedCall = (target) => `{const savedRouted=ctx._routed
8367
+ ${emitRollback(m1, L.buf, sinks)}
8368
+ ${emitMark(m2, L.buf, sinks, false)}
8369
+ ctx._routed={value:key,span:{start:pos,end:selEnd}}
8370
+ try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
8371
+ break}`;
8372
+ const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
8373
+ const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
8374
+ const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
8300
8375
  return `${head}
8301
8376
  ${emitMark(m1, L.buf, sinks)}
8302
8377
  const sv=${selector}(input,pos,ctx)
@@ -8304,24 +8379,16 @@ if(sv===FAIL)return FAIL
8304
8379
  const selEnd=EC.e
8305
8380
  const key=sv
8306
8381
  let arm=${bk}.get(key)
8307
- ${fold}${chain}let ur
8382
+ ${fold}${chain}
8308
8383
  if(arm===undefined){
8309
- ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : `ur=${String(otherRouted)}`}
8310
- }else ur=${rt}[arm]===1
8311
- const savedRouted=ctx._routed
8312
- ${emitMark(m2, L.buf, sinks)}
8313
- if(ur){
8314
- ${emitRollback(m1, L.buf, sinks)}
8315
- ${emitMark(m2, L.buf, sinks, false)}
8316
- ctx._routed={value:key,span:{start:pos,end:selEnd}}
8384
+ ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
8317
8385
  }
8318
- const at=ur?pos:selEnd
8386
+ ${emitMark(m2, L.buf, sinks)}
8319
8387
  let v
8320
8388
  switch(arm){
8321
- ${arms.map((a, i) => `case ${i}:v=${a}(input,at,ctx);break`).join("\n")}
8322
- ${other === void 0 ? "" : `default:v=${other}(input,at,ctx)`}
8389
+ ${armCases}
8390
+ ${fallbackCase}
8323
8391
  }
8324
- if(ur)ctx._routed=savedRouted
8325
8392
  if(v===FAIL){
8326
8393
  ${emitRollback(m2, L.buf, sinks)}
8327
8394
  ctx._fc=true
@@ -8797,7 +8864,7 @@ function committed(c) {
8797
8864
  }
8798
8865
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
8799
8866
  const triviaOfRule = (ip) => {
8800
- if (prog.code[ip] !== OP_SCOPE) return void 0;
8867
+ if (prog.code[ip] !== OP_SCOPE_PLAIN && prog.code[ip] !== OP_SCOPE) return void 0;
8801
8868
  const slot = prog.code[ip + 1];
8802
8869
  return slot < 0 ? void 0 : resolved.trivia[slot];
8803
8870
  };
@@ -9011,20 +9078,19 @@ function assemble(t, prog, cfg) {
9011
9078
  TERMV = v2;
9012
9079
  return EC.e > scanEnd2 ? EC.e : cur;
9013
9080
  }
9014
- const need = markCst(ctx);
9015
- const mRaw = MRAW;
9016
- const mTl = MTL;
9017
- const mLv = MLV;
9018
- const mFl = need ? ctx._fields?.length ?? 0 : 0;
9019
- const mEr = need ? ctx._errors?.length ?? 0 : 0;
9081
+ const need = rollbackNeeded(ctx);
9082
+ const mTl = need ? cstTlLen(ctx) : 0;
9020
9083
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9021
9084
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9022
9085
  const scanEnd = skipTrivia(input, cur, ctx);
9086
+ const scanTl = need ? cstTlLen(ctx) : 0;
9087
+ const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
9088
+ const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
9023
9089
  const v = child(input, scanEnd, ctx);
9024
9090
  if (v === FAIL) return -1;
9025
9091
  TERMV = v;
9026
9092
  if (EC.e > scanEnd) return EC.e;
9027
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
9093
+ if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
9028
9094
  return cur;
9029
9095
  }
9030
9096
  function committed2(c) {
@@ -9438,7 +9504,8 @@ function assemble(t, prog, cfg) {
9438
9504
  };
9439
9505
  }
9440
9506
  case OP_SCOPE:
9441
- case OP_SCOPE_CAP: {
9507
+ case OP_SCOPE_CAP:
9508
+ case OP_SCOPE_PLAIN: {
9442
9509
  const ki = code[ip + 1];
9443
9510
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
9444
9511
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
@@ -9472,7 +9539,7 @@ function assemble(t, prog, cfg) {
9472
9539
  SCAN = savedScan;
9473
9540
  return v;
9474
9541
  };
9475
- return scopeRootPolicy(scopePiece, code[ip + 3]);
9542
+ return scopeRootPolicy(scopePiece, code[ip] === OP_SCOPE_PLAIN ? 0 : code[ip + 3]);
9476
9543
  }
9477
9544
  case OP_ROUTED: {
9478
9545
  const fb = code[ip + 1];
@@ -10388,15 +10455,21 @@ function assemble(t, prog, cfg) {
10388
10455
  target = arms[arm];
10389
10456
  usesRouted = routed2[arm] === 1;
10390
10457
  }
10391
- const savedRouted = ctx._routed;
10392
10458
  let mark = saveTriviaMark(ctx);
10459
+ let v;
10393
10460
  if (usesRouted) {
10461
+ const savedRouted = ctx._routed;
10394
10462
  rollbackTrivia(ctx, selectorMark);
10395
10463
  mark = saveTriviaMark(ctx);
10396
10464
  ctx._routed = { value: key, span: { start: pos, end: selEnd } };
10465
+ try {
10466
+ v = target(input, pos, ctx);
10467
+ } finally {
10468
+ ctx._routed = savedRouted;
10469
+ }
10470
+ } else {
10471
+ v = target(input, selEnd, ctx);
10397
10472
  }
10398
- const v = target(input, usesRouted ? pos : selEnd, ctx);
10399
- if (usesRouted) ctx._routed = savedRouted;
10400
10473
  if (v === FAIL) {
10401
10474
  rollbackTrivia(ctx, mark);
10402
10475
  ctx._fc = true;
@@ -10542,6 +10615,11 @@ function assemble(t, prog, cfg) {
10542
10615
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10543
10616
  }
10544
10617
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
10618
+ const validationRoots = [...Object.values(prog.rules), ...extraIps];
10619
+ for (const ip of reachableSites(code, validationRoots)) {
10620
+ if (code[ip] !== OP_DISPATCH) continue;
10621
+ validateDispatchSpec(dsp[code[ip + 2]], code[ip + 5], code[ip + 4]);
10622
+ }
10545
10623
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10546
10624
  if (pre !== void 0) {
10547
10625
  const pools = rebuildPools(t.cc, t.fx, pre.plan);
@@ -10568,6 +10646,7 @@ function assemble(t, prog, cfg) {
10568
10646
  pushCstLeaf,
10569
10647
  pushCstChild,
10570
10648
  rollbackTriviaAt,
10649
+ rollbackScannedTriviaAt,
10571
10650
  failAt,
10572
10651
  classHas,
10573
10652
  consumeTrivia,
@@ -10638,6 +10717,7 @@ function assemble(t, prog, cfg) {
10638
10717
  pushCstLeaf,
10639
10718
  pushCstChild,
10640
10719
  rollbackTriviaAt,
10720
+ rollbackScannedTriviaAt,
10641
10721
  failAt,
10642
10722
  classHas,
10643
10723
  consumeTrivia,
@@ -10870,6 +10950,14 @@ function tableRules(source, artifactMetadata = {}) {
10870
10950
  function jsString(s) {
10871
10951
  return JSON.stringify(s);
10872
10952
  }
10953
+ function emitClassPool(classes) {
10954
+ const array = `[${classes.map(jsString).join(",")}]`;
10955
+ if (classes.length < 2) return array;
10956
+ const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
10957
+ if (delimiter === void 0) return array;
10958
+ const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
10959
+ return split.length < array.length ? split : array;
10960
+ }
10873
10961
  function emitConst(v) {
10874
10962
  if (v instanceof RegExp) return `/${v.source}/${v.flags}`;
10875
10963
  if (typeof v === "string") return jsString(v);
@@ -10948,7 +11036,7 @@ function programFields(prog, fns, opts = {}) {
10948
11036
  ...emitAssemblies(prog, opts.assemblies ?? []),
10949
11037
  `c:[${prog.code.join(",")}],`,
10950
11038
  `k:[${prog.k.map(emitConst).join(",")}],`,
10951
- `x:[${prog.cc.map(jsString).join(",")}],`,
11039
+ `x:${emitClassPool(prog.cc)},`,
10952
11040
  `e:[${prog.fx.map((f) => `[${f.map(jsString).join(",")}]`).join(",")}],`,
10953
11041
  `d:[${prog.disp.map((a) => `[${a.join(",")}]`).join(",")}],`,
10954
11042
  `r:${JSON.stringify(prog.rules)},`,
@@ -13300,7 +13388,7 @@ function compileRuleMap(ruleMap, opts = {}) {
13300
13388
  }
13301
13389
 
13302
13390
  // src/version.ts
13303
- var PARSEMAN_VERSION = "0.47.0";
13391
+ var PARSEMAN_VERSION = "0.47.1";
13304
13392
 
13305
13393
  // src/compiler/compile-linkable-table.ts
13306
13394
  function isLocal(rule) {