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
@@ -87,6 +87,13 @@ function empty() {
87
87
  function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve3) {
88
88
  if (seen.has(p)) return true;
89
89
  seen.add(p);
90
+ try {
91
+ return matchesEmptyBody(p, seen, resolve3);
92
+ } finally {
93
+ seen.delete(p);
94
+ }
95
+ }
96
+ function matchesEmptyBody(p, seen, resolve3) {
90
97
  const me = (c) => matchesEmpty(c, seen, resolve3);
91
98
  const d = p._def;
92
99
  switch (d.tag) {
@@ -188,6 +195,13 @@ function sequenceFirstSet(parsers) {
188
195
  function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve3) {
189
196
  if (seen.has(p)) return any();
190
197
  seen.add(p);
198
+ try {
199
+ return firstSetBody(p, seen, resolve3);
200
+ } finally {
201
+ seen.delete(p);
202
+ }
203
+ }
204
+ function firstSetBody(p, seen, resolve3) {
191
205
  const fs3 = (c) => firstSetOf(c, seen, resolve3);
192
206
  const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve3);
193
207
  const d = p._def;
@@ -2143,6 +2157,23 @@ function rollbackTrivia(ctx, mark) {
2143
2157
  if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
2144
2158
  if (ctx._rootTriviaLog && ctx._rootTriviaLog.length !== mark.rootLog) ctx._rootTriviaLog.length = mark.rootLog;
2145
2159
  }
2160
+ function removeNumberRange(values, start, end) {
2161
+ if (values === void 0 || end <= start) return;
2162
+ if (values.length > end) values.copyWithin(start, end);
2163
+ values.length -= end - start;
2164
+ }
2165
+ function rollbackScannedTriviaAt(ctx, tlogStart, tlogEnd, logStart, logEnd, rootLogStart, rootLogEnd) {
2166
+ const b = ctx._cstBuf;
2167
+ if (b !== void 0) {
2168
+ const tlog = b.tl;
2169
+ removeNumberRange(tlog, tlogStart, tlogEnd);
2170
+ if (tlog !== void 0 && tlog.length === 0) b.tl = void 0;
2171
+ } else {
2172
+ removeNumberRange(ctx._cstTriviaLog, tlogStart, tlogEnd);
2173
+ }
2174
+ removeNumberRange(ctx._triviaLog, logStart, logEnd);
2175
+ removeNumberRange(ctx._rootTriviaLog, rootLogStart, rootLogEnd);
2176
+ }
2146
2177
  function parseTriviaNoCapture(triviaP, input, cur, ctx) {
2147
2178
  const probeCtx = createDetachedParseContext(ctx.trackLines, ctx.state);
2148
2179
  probeCtx._lineIndex = ctx._lineIndex;
@@ -2846,7 +2877,9 @@ function sequence(...parsers) {
2846
2877
  continue;
2847
2878
  }
2848
2879
  if (ctx.trivia && i > 0) {
2849
- const mark = saveTriviaMark(ctx);
2880
+ const mTlog = cstTlLen(ctx);
2881
+ const mLog = ctx._triviaLog?.length ?? 0;
2882
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2850
2883
  let scanEnd;
2851
2884
  if (needsDeferredTriviaCommit(ctx)) {
2852
2885
  const scan = scanTrivia(input, cur, ctx);
@@ -2855,10 +2888,13 @@ function sequence(...parsers) {
2855
2888
  } else {
2856
2889
  scanEnd = advanceTrivia(input, cur, ctx);
2857
2890
  }
2891
+ const scanTlog = cstTlLen(ctx);
2892
+ const scanLog = ctx._triviaLog?.length ?? 0;
2893
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2858
2894
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2859
2895
  if (!result2.ok) return result2;
2860
2896
  if (result2.span.end > scanEnd) cur = result2.span.end;
2861
- else rollbackTrivia(ctx, mark);
2897
+ else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2862
2898
  if (values !== void 0) values.push(result2.value);
2863
2899
  continue;
2864
2900
  }
@@ -2889,7 +2925,9 @@ function sequence(...parsers) {
2889
2925
  }
2890
2926
  if (ctx.trivia && i > 0) {
2891
2927
  let scanEnd;
2892
- const mark = saveTriviaMark(ctx);
2928
+ const mTlog = cstTlLen(ctx);
2929
+ const mLog = ctx._triviaLog?.length ?? 0;
2930
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2893
2931
  if (needsDeferredTriviaCommit(ctx)) {
2894
2932
  const scan = scanTrivia(input, cur, ctx);
2895
2933
  scan.commit();
@@ -2897,10 +2935,13 @@ function sequence(...parsers) {
2897
2935
  } else {
2898
2936
  scanEnd = advanceTrivia(input, cur, ctx);
2899
2937
  }
2938
+ const scanTlog = cstTlLen(ctx);
2939
+ const scanLog = ctx._triviaLog?.length ?? 0;
2940
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2900
2941
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2901
2942
  if (!result2.ok) return result2;
2902
2943
  if (result2.span.end > scanEnd) cur = result2.span.end;
2903
- else rollbackTrivia(ctx, mark);
2944
+ else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2904
2945
  if (values !== void 0) values.push(result2.value);
2905
2946
  continue;
2906
2947
  }
@@ -2928,7 +2969,9 @@ function sequence(...parsers) {
2928
2969
  for (let i = 0; i < parsers.length; i++) {
2929
2970
  if (ctx.trivia && i > 0) {
2930
2971
  let scanEnd;
2931
- let mark = saveTriviaMark(ctx);
2972
+ const mTlog = cstTlLen(ctx);
2973
+ const mLog = ctx._triviaLog?.length ?? 0;
2974
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2932
2975
  if (needsDeferredTriviaCommit(ctx)) {
2933
2976
  const scan = scanTrivia(input, cur, ctx);
2934
2977
  scan.commit();
@@ -2936,12 +2979,15 @@ function sequence(...parsers) {
2936
2979
  } else {
2937
2980
  scanEnd = advanceTrivia(input, cur, ctx);
2938
2981
  }
2982
+ const scanTlog = cstTlLen(ctx);
2983
+ const scanLog = ctx._triviaLog?.length ?? 0;
2984
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2939
2985
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2940
2986
  if (!result2.ok) return result2;
2941
2987
  if (result2.span.end > scanEnd) {
2942
2988
  cur = result2.span.end;
2943
2989
  } else {
2944
- rollbackTrivia(ctx, mark);
2990
+ rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2945
2991
  }
2946
2992
  if (values !== void 0) values.push(result2.value);
2947
2993
  continue;
@@ -4665,6 +4711,7 @@ var OP_LIVE = 37;
4665
4711
  var OP_ATTEMPT = 38;
4666
4712
  var OP_LABEL = 39;
4667
4713
  var OP_COV = 40;
4714
+ var OP_SCOPE_PLAIN = 41;
4668
4715
  var OP_DISPATCH = 25;
4669
4716
  var OP_ROUTED = 26;
4670
4717
  var OP_NAMES = {
@@ -4707,7 +4754,8 @@ var OP_NAMES = {
4707
4754
  [OP_LIVE]: "LIVE",
4708
4755
  [OP_ATTEMPT]: "ATTEMPT",
4709
4756
  [OP_LABEL]: "LABEL",
4710
- [OP_COV]: "COV"
4757
+ [OP_COV]: "COV",
4758
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
4711
4759
  };
4712
4760
 
4713
4761
  // src/table/program.ts
@@ -4765,6 +4813,15 @@ function expandCompact(p) {
4765
4813
  ...p.a === void 0 ? {} : { asm: p.a }
4766
4814
  });
4767
4815
  }
4816
+ function validateDispatchSpec(spec, arity, fallbackRouted) {
4817
+ const invalid = (arms) => {
4818
+ for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
4819
+ return false;
4820
+ };
4821
+ 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]]))) {
4822
+ throw new TypeError("table: malformed dispatch");
4823
+ }
4824
+ }
4768
4825
  var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
4769
4826
  function ownTableProgram(prog, resolved) {
4770
4827
  return { ...prog, [TABLE_RUNTIME]: { resolved } };
@@ -5323,7 +5380,7 @@ var Encoder = class {
5323
5380
  this.carryTriviaMeta(amb);
5324
5381
  this.carryTriviaMeta(p);
5325
5382
  if (p._def.tag === "grammar") this.carryTriviaMeta(p._def.triviaParser);
5326
- this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE, this.triviaSlot(amb), body);
5383
+ this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), body);
5327
5384
  }
5328
5385
  /**
5329
5386
  * The row a cross-rule `g.X` reference jumps to — the target's body, RE-WRAPPED
@@ -5366,7 +5423,7 @@ var Encoder = class {
5366
5423
  const amb = p._meta.grammarTrivia ?? target._meta.grammarTrivia;
5367
5424
  if (amb === void 0 || this.activeTrivia !== void 0) return ip;
5368
5425
  if (!hasOwnTriviaBoundary(target)) return ip;
5369
- return this.emit(OP_SCOPE, this.triviaSlot(amb), ip);
5426
+ return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
5370
5427
  }
5371
5428
  node(p) {
5372
5429
  const lazyRef = p._def.tag === "lazy";
@@ -5771,6 +5828,7 @@ var Encoder = class {
5771
5828
  return [ip + 1];
5772
5829
  case OP_SCOPE:
5773
5830
  case OP_SCOPE_CAP:
5831
+ case OP_SCOPE_PLAIN:
5774
5832
  case OP_WITHCTX:
5775
5833
  case OP_XFORM:
5776
5834
  case OP_LEAF:
@@ -6961,6 +7019,7 @@ function childSlots(code, ip, out) {
6961
7019
  case OP_GATE:
6962
7020
  case OP_SCOPE:
6963
7021
  case OP_SCOPE_CAP:
7022
+ case OP_SCOPE_PLAIN:
6964
7023
  case OP_WITHCTX:
6965
7024
  case OP_XFORM:
6966
7025
  case OP_NODE:
@@ -7049,7 +7108,7 @@ function reachableSites(code, roots) {
7049
7108
  }
7050
7109
  function transfer(code, ip, at, hostCst) {
7051
7110
  const op = code[ip];
7052
- if (op === OP_SCOPE || op === OP_SCOPE_CAP) {
7111
+ if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
7053
7112
  const ki = code[ip + 1];
7054
7113
  const tri = ki < 0 ? TRI_NONE : ki;
7055
7114
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
@@ -7130,6 +7189,7 @@ var EMITTED_PARAMS = [
7130
7189
  "pushCstLeaf",
7131
7190
  "pushCstChild",
7132
7191
  "rollbackTriviaAt",
7192
+ "rollbackScannedTriviaAt",
7133
7193
  "failAt",
7134
7194
  "classHas",
7135
7195
  "consumeTrivia",
@@ -7273,19 +7333,24 @@ if(ctx._errors!==undefined&&ctx._errors.length!==${t}er)ctx._errors.length=${t}e
7273
7333
  if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,0,undefined,${t}lg,${t}rt)`;
7274
7334
  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)}`;
7275
7335
  }
7276
- function emitTerm(callee, dst, t, l, skip, s) {
7336
+ function emitTerm(callee, dst, t, l, skip) {
7277
7337
  const fast = `const ${t}v=${callee}(input,cur,ctx)
7278
7338
  if(${t}v===FAIL)return FAIL
7279
7339
  ${dst}=${t}v
7280
7340
  cur=EC.e`;
7281
7341
  if (l.tri === TRI_NONE) return fast;
7282
- const scanned = `${emitMark(t, l.buf, s)}
7342
+ const scanned = `const ${t}tl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
7343
+ const ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
7344
+ const ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7283
7345
  const ${t}s=${skip}(input,cur,ctx)
7346
+ const ${t}stl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
7347
+ const ${t}slg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
7348
+ const ${t}srt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7284
7349
  const ${t}v=${callee}(input,${t}s,ctx)
7285
7350
  if(${t}v===FAIL)return FAIL
7286
7351
  ${dst}=${t}v
7287
7352
  if(EC.e>${t}s)cur=EC.e
7288
- else{${emitRollback(t, l.buf, s)}}`;
7353
+ else{rollbackScannedTriviaAt(ctx,${t}tl,${t}stl,${t}lg,${t}slg,${t}rt,${t}srt)}`;
7289
7354
  if (l.tri !== TRI_UNKNOWN) return scanned;
7290
7355
  return `if(ctx.trivia===undefined){
7291
7356
  ${fast}
@@ -7448,7 +7513,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7448
7513
  const op = code[ip];
7449
7514
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
7450
7515
  if (op === OP_RULE) return code[ip + 1];
7451
- if (op === OP_SCOPE && code[ip + 3] === 0 && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
7516
+ if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
7452
7517
  return code[ip + 2];
7453
7518
  }
7454
7519
  return void 0;
@@ -7616,10 +7681,11 @@ return r.value
7616
7681
  }`;
7617
7682
  }
7618
7683
  case OP_SCOPE:
7619
- case OP_SCOPE_CAP: {
7684
+ case OP_SCOPE_CAP:
7685
+ case OP_SCOPE_PLAIN: {
7620
7686
  const ki = code[ip + 1];
7621
7687
  const cap = op === OP_SCOPE_CAP;
7622
- const flags = code[ip + 3];
7688
+ const flags = op === OP_SCOPE_PLAIN ? 0 : code[ip + 3];
7623
7689
  const child = link(code[ip + 2]);
7624
7690
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
7625
7691
  const tri = ki < 0 ? "undefined" : hoist("tv", `TRIVIA[${ki}]`);
@@ -7773,7 +7839,7 @@ return v
7773
7839
  const vn = `v${i}`;
7774
7840
  parts.push(`let ${vn}`);
7775
7841
  if (REC2) parts.push(pub(i));
7776
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L), sinks));
7842
+ parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
7777
7843
  names.push(vn);
7778
7844
  }
7779
7845
  parts.push("EC.e=cur");
@@ -7874,11 +7940,11 @@ return FAIL
7874
7940
  const other = otherIp >= 0 ? link(otherIp) : void 0;
7875
7941
  const otherRouted = code[ip + 4] === 1;
7876
7942
  const n = code[ip + 5];
7943
+ validateDispatchSpec(spec, n, code[ip + 4]);
7877
7944
  const armBase = ip + 6;
7878
7945
  const arms = [];
7879
7946
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
7880
7947
  const bk = hoist("bk", `DSP[${di}].byKey`);
7881
- const rt = hoist("rt", `DSP[${di}].routed`);
7882
7948
  const dx = hoist("dx", `DSP[${di}].expected`);
7883
7949
  const claims = (m) => {
7884
7950
  switch (m[0]) {
@@ -7902,6 +7968,15 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
7902
7968
  ` : "";
7903
7969
  const m1 = tmp();
7904
7970
  const m2 = tmp();
7971
+ const routedCall = (target) => `{const savedRouted=ctx._routed
7972
+ ${emitRollback(m1, L.buf, sinks)}
7973
+ ${emitMark(m2, L.buf, sinks, false)}
7974
+ ctx._routed={value:key,span:{start:pos,end:selEnd}}
7975
+ try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
7976
+ break}`;
7977
+ const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
7978
+ const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
7979
+ const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
7905
7980
  return `${head}
7906
7981
  ${emitMark(m1, L.buf, sinks)}
7907
7982
  const sv=${selector}(input,pos,ctx)
@@ -7909,24 +7984,16 @@ if(sv===FAIL)return FAIL
7909
7984
  const selEnd=EC.e
7910
7985
  const key=sv
7911
7986
  let arm=${bk}.get(key)
7912
- ${fold}${chain}let ur
7987
+ ${fold}${chain}
7913
7988
  if(arm===undefined){
7914
- ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : `ur=${String(otherRouted)}`}
7915
- }else ur=${rt}[arm]===1
7916
- const savedRouted=ctx._routed
7917
- ${emitMark(m2, L.buf, sinks)}
7918
- if(ur){
7919
- ${emitRollback(m1, L.buf, sinks)}
7920
- ${emitMark(m2, L.buf, sinks, false)}
7921
- ctx._routed={value:key,span:{start:pos,end:selEnd}}
7989
+ ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
7922
7990
  }
7923
- const at=ur?pos:selEnd
7991
+ ${emitMark(m2, L.buf, sinks)}
7924
7992
  let v
7925
7993
  switch(arm){
7926
- ${arms.map((a, i) => `case ${i}:v=${a}(input,at,ctx);break`).join("\n")}
7927
- ${other === void 0 ? "" : `default:v=${other}(input,at,ctx)`}
7994
+ ${armCases}
7995
+ ${fallbackCase}
7928
7996
  }
7929
- if(ur)ctx._routed=savedRouted
7930
7997
  if(v===FAIL){
7931
7998
  ${emitRollback(m2, L.buf, sinks)}
7932
7999
  ctx._fc=true
@@ -8389,7 +8456,7 @@ function committed(c) {
8389
8456
  }
8390
8457
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
8391
8458
  const triviaOfRule = (ip) => {
8392
- if (prog.code[ip] !== OP_SCOPE) return void 0;
8459
+ if (prog.code[ip] !== OP_SCOPE_PLAIN && prog.code[ip] !== OP_SCOPE) return void 0;
8393
8460
  const slot = prog.code[ip + 1];
8394
8461
  return slot < 0 ? void 0 : resolved.trivia[slot];
8395
8462
  };
@@ -8603,20 +8670,19 @@ function assemble(t, prog, cfg) {
8603
8670
  TERMV = v2;
8604
8671
  return EC.e > scanEnd2 ? EC.e : cur;
8605
8672
  }
8606
- const need = markCst(ctx);
8607
- const mRaw = MRAW;
8608
- const mTl = MTL;
8609
- const mLv = MLV;
8610
- const mFl = need ? ctx._fields?.length ?? 0 : 0;
8611
- const mEr = need ? ctx._errors?.length ?? 0 : 0;
8673
+ const need = rollbackNeeded(ctx);
8674
+ const mTl = need ? cstTlLen(ctx) : 0;
8612
8675
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
8613
8676
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
8614
8677
  const scanEnd = skipTrivia(input, cur, ctx);
8678
+ const scanTl = need ? cstTlLen(ctx) : 0;
8679
+ const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
8680
+ const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
8615
8681
  const v = child(input, scanEnd, ctx);
8616
8682
  if (v === FAIL) return -1;
8617
8683
  TERMV = v;
8618
8684
  if (EC.e > scanEnd) return EC.e;
8619
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
8685
+ if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
8620
8686
  return cur;
8621
8687
  }
8622
8688
  function committed2(c) {
@@ -9030,7 +9096,8 @@ function assemble(t, prog, cfg) {
9030
9096
  };
9031
9097
  }
9032
9098
  case OP_SCOPE:
9033
- case OP_SCOPE_CAP: {
9099
+ case OP_SCOPE_CAP:
9100
+ case OP_SCOPE_PLAIN: {
9034
9101
  const ki = code[ip + 1];
9035
9102
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
9036
9103
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
@@ -9064,7 +9131,7 @@ function assemble(t, prog, cfg) {
9064
9131
  SCAN = savedScan;
9065
9132
  return v;
9066
9133
  };
9067
- return scopeRootPolicy(scopePiece, code[ip + 3]);
9134
+ return scopeRootPolicy(scopePiece, code[ip] === OP_SCOPE_PLAIN ? 0 : code[ip + 3]);
9068
9135
  }
9069
9136
  case OP_ROUTED: {
9070
9137
  const fb = code[ip + 1];
@@ -9980,15 +10047,21 @@ function assemble(t, prog, cfg) {
9980
10047
  target = arms[arm];
9981
10048
  usesRouted = routed2[arm] === 1;
9982
10049
  }
9983
- const savedRouted = ctx._routed;
9984
10050
  let mark = saveTriviaMark(ctx);
10051
+ let v;
9985
10052
  if (usesRouted) {
10053
+ const savedRouted = ctx._routed;
9986
10054
  rollbackTrivia(ctx, selectorMark);
9987
10055
  mark = saveTriviaMark(ctx);
9988
10056
  ctx._routed = { value: key, span: { start: pos, end: selEnd } };
10057
+ try {
10058
+ v = target(input, pos, ctx);
10059
+ } finally {
10060
+ ctx._routed = savedRouted;
10061
+ }
10062
+ } else {
10063
+ v = target(input, selEnd, ctx);
9989
10064
  }
9990
- const v = target(input, usesRouted ? pos : selEnd, ctx);
9991
- if (usesRouted) ctx._routed = savedRouted;
9992
10065
  if (v === FAIL) {
9993
10066
  rollbackTrivia(ctx, mark);
9994
10067
  ctx._fc = true;
@@ -10134,6 +10207,11 @@ function assemble(t, prog, cfg) {
10134
10207
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10135
10208
  }
10136
10209
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
10210
+ const validationRoots = [...Object.values(prog.rules), ...extraIps];
10211
+ for (const ip of reachableSites(code, validationRoots)) {
10212
+ if (code[ip] !== OP_DISPATCH) continue;
10213
+ validateDispatchSpec(dsp[code[ip + 2]], code[ip + 5], code[ip + 4]);
10214
+ }
10137
10215
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10138
10216
  if (pre !== void 0) {
10139
10217
  const pools = rebuildPools(t.cc, t.fx, pre.plan);
@@ -10160,6 +10238,7 @@ function assemble(t, prog, cfg) {
10160
10238
  pushCstLeaf,
10161
10239
  pushCstChild,
10162
10240
  rollbackTriviaAt,
10241
+ rollbackScannedTriviaAt,
10163
10242
  failAt,
10164
10243
  classHas,
10165
10244
  consumeTrivia,
@@ -10230,6 +10309,7 @@ function assemble(t, prog, cfg) {
10230
10309
  pushCstLeaf,
10231
10310
  pushCstChild,
10232
10311
  rollbackTriviaAt,
10312
+ rollbackScannedTriviaAt,
10233
10313
  failAt,
10234
10314
  classHas,
10235
10315
  consumeTrivia,
@@ -10462,6 +10542,14 @@ function tableRules(source, artifactMetadata = {}) {
10462
10542
  function jsString(s) {
10463
10543
  return JSON.stringify(s);
10464
10544
  }
10545
+ function emitClassPool(classes) {
10546
+ const array = `[${classes.map(jsString).join(",")}]`;
10547
+ if (classes.length < 2) return array;
10548
+ const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
10549
+ if (delimiter === void 0) return array;
10550
+ const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
10551
+ return split.length < array.length ? split : array;
10552
+ }
10465
10553
  function emitConst(v) {
10466
10554
  if (v instanceof RegExp) return `/${v.source}/${v.flags}`;
10467
10555
  if (typeof v === "string") return jsString(v);
@@ -10540,7 +10628,7 @@ function programFields(prog, fns, opts = {}) {
10540
10628
  ...emitAssemblies(prog, opts.assemblies ?? []),
10541
10629
  `c:[${prog.code.join(",")}],`,
10542
10630
  `k:[${prog.k.map(emitConst).join(",")}],`,
10543
- `x:[${prog.cc.map(jsString).join(",")}],`,
10631
+ `x:${emitClassPool(prog.cc)},`,
10544
10632
  `e:[${prog.fx.map((f) => `[${f.map(jsString).join(",")}]`).join(",")}],`,
10545
10633
  `d:[${prog.disp.map((a) => `[${a.join(",")}]`).join(",")}],`,
10546
10634
  `r:${JSON.stringify(prog.rules)},`,
@@ -12892,7 +12980,7 @@ function compileRuleMap(ruleMap, opts = {}) {
12892
12980
  }
12893
12981
 
12894
12982
  // src/version.ts
12895
- var PARSEMAN_VERSION = "0.47.0";
12983
+ var PARSEMAN_VERSION = "0.47.1";
12896
12984
 
12897
12985
  // src/compiler/compile-linkable-table.ts
12898
12986
  function isLocal(rule) {