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
@@ -52,6 +52,13 @@ function empty() {
52
52
  function matchesEmpty(p, seen = /* @__PURE__ */ new Set(), resolve3) {
53
53
  if (seen.has(p)) return true;
54
54
  seen.add(p);
55
+ try {
56
+ return matchesEmptyBody(p, seen, resolve3);
57
+ } finally {
58
+ seen.delete(p);
59
+ }
60
+ }
61
+ function matchesEmptyBody(p, seen, resolve3) {
55
62
  const me = (c) => matchesEmpty(c, seen, resolve3);
56
63
  const d = p._def;
57
64
  switch (d.tag) {
@@ -153,6 +160,13 @@ function sequenceFirstSet(parsers) {
153
160
  function firstSetOf(p, seen = /* @__PURE__ */ new Set(), resolve3) {
154
161
  if (seen.has(p)) return any();
155
162
  seen.add(p);
163
+ try {
164
+ return firstSetBody(p, seen, resolve3);
165
+ } finally {
166
+ seen.delete(p);
167
+ }
168
+ }
169
+ function firstSetBody(p, seen, resolve3) {
156
170
  const fs3 = (c) => firstSetOf(c, seen, resolve3);
157
171
  const empties = (c) => matchesEmpty(c, /* @__PURE__ */ new Set(), resolve3);
158
172
  const d = p._def;
@@ -2108,6 +2122,23 @@ function rollbackTrivia(ctx, mark) {
2108
2122
  if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
2109
2123
  if (ctx._rootTriviaLog && ctx._rootTriviaLog.length !== mark.rootLog) ctx._rootTriviaLog.length = mark.rootLog;
2110
2124
  }
2125
+ function removeNumberRange(values, start, end) {
2126
+ if (values === void 0 || end <= start) return;
2127
+ if (values.length > end) values.copyWithin(start, end);
2128
+ values.length -= end - start;
2129
+ }
2130
+ function rollbackScannedTriviaAt(ctx, tlogStart, tlogEnd, logStart, logEnd, rootLogStart, rootLogEnd) {
2131
+ const b = ctx._cstBuf;
2132
+ if (b !== void 0) {
2133
+ const tlog = b.tl;
2134
+ removeNumberRange(tlog, tlogStart, tlogEnd);
2135
+ if (tlog !== void 0 && tlog.length === 0) b.tl = void 0;
2136
+ } else {
2137
+ removeNumberRange(ctx._cstTriviaLog, tlogStart, tlogEnd);
2138
+ }
2139
+ removeNumberRange(ctx._triviaLog, logStart, logEnd);
2140
+ removeNumberRange(ctx._rootTriviaLog, rootLogStart, rootLogEnd);
2141
+ }
2111
2142
  function parseTriviaNoCapture(triviaP, input, cur, ctx) {
2112
2143
  const probeCtx = createDetachedParseContext(ctx.trackLines, ctx.state);
2113
2144
  probeCtx._lineIndex = ctx._lineIndex;
@@ -2811,7 +2842,9 @@ function sequence(...parsers) {
2811
2842
  continue;
2812
2843
  }
2813
2844
  if (ctx.trivia && i > 0) {
2814
- const mark = saveTriviaMark(ctx);
2845
+ const mTlog = cstTlLen(ctx);
2846
+ const mLog = ctx._triviaLog?.length ?? 0;
2847
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2815
2848
  let scanEnd;
2816
2849
  if (needsDeferredTriviaCommit(ctx)) {
2817
2850
  const scan = scanTrivia(input, cur, ctx);
@@ -2820,10 +2853,13 @@ function sequence(...parsers) {
2820
2853
  } else {
2821
2854
  scanEnd = advanceTrivia(input, cur, ctx);
2822
2855
  }
2856
+ const scanTlog = cstTlLen(ctx);
2857
+ const scanLog = ctx._triviaLog?.length ?? 0;
2858
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2823
2859
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2824
2860
  if (!result2.ok) return result2;
2825
2861
  if (result2.span.end > scanEnd) cur = result2.span.end;
2826
- else rollbackTrivia(ctx, mark);
2862
+ else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2827
2863
  if (values !== void 0) values.push(result2.value);
2828
2864
  continue;
2829
2865
  }
@@ -2854,7 +2890,9 @@ function sequence(...parsers) {
2854
2890
  }
2855
2891
  if (ctx.trivia && i > 0) {
2856
2892
  let scanEnd;
2857
- const mark = saveTriviaMark(ctx);
2893
+ const mTlog = cstTlLen(ctx);
2894
+ const mLog = ctx._triviaLog?.length ?? 0;
2895
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2858
2896
  if (needsDeferredTriviaCommit(ctx)) {
2859
2897
  const scan = scanTrivia(input, cur, ctx);
2860
2898
  scan.commit();
@@ -2862,10 +2900,13 @@ function sequence(...parsers) {
2862
2900
  } else {
2863
2901
  scanEnd = advanceTrivia(input, cur, ctx);
2864
2902
  }
2903
+ const scanTlog = cstTlLen(ctx);
2904
+ const scanLog = ctx._triviaLog?.length ?? 0;
2905
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2865
2906
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2866
2907
  if (!result2.ok) return result2;
2867
2908
  if (result2.span.end > scanEnd) cur = result2.span.end;
2868
- else rollbackTrivia(ctx, mark);
2909
+ else rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2869
2910
  if (values !== void 0) values.push(result2.value);
2870
2911
  continue;
2871
2912
  }
@@ -2893,7 +2934,9 @@ function sequence(...parsers) {
2893
2934
  for (let i = 0; i < parsers.length; i++) {
2894
2935
  if (ctx.trivia && i > 0) {
2895
2936
  let scanEnd;
2896
- let mark = saveTriviaMark(ctx);
2937
+ const mTlog = cstTlLen(ctx);
2938
+ const mLog = ctx._triviaLog?.length ?? 0;
2939
+ const mRootLog = ctx._rootTriviaLog?.length ?? 0;
2897
2940
  if (needsDeferredTriviaCommit(ctx)) {
2898
2941
  const scan = scanTrivia(input, cur, ctx);
2899
2942
  scan.commit();
@@ -2901,12 +2944,15 @@ function sequence(...parsers) {
2901
2944
  } else {
2902
2945
  scanEnd = advanceTrivia(input, cur, ctx);
2903
2946
  }
2947
+ const scanTlog = cstTlLen(ctx);
2948
+ const scanLog = ctx._triviaLog?.length ?? 0;
2949
+ const scanRootLog = ctx._rootTriviaLog?.length ?? 0;
2904
2950
  const result2 = parsers[i].parse(input, scanEnd, ctx);
2905
2951
  if (!result2.ok) return result2;
2906
2952
  if (result2.span.end > scanEnd) {
2907
2953
  cur = result2.span.end;
2908
2954
  } else {
2909
- rollbackTrivia(ctx, mark);
2955
+ rollbackScannedTriviaAt(ctx, mTlog, scanTlog, mLog, scanLog, mRootLog, scanRootLog);
2910
2956
  }
2911
2957
  if (values !== void 0) values.push(result2.value);
2912
2958
  continue;
@@ -4630,6 +4676,7 @@ var OP_LIVE = 37;
4630
4676
  var OP_ATTEMPT = 38;
4631
4677
  var OP_LABEL = 39;
4632
4678
  var OP_COV = 40;
4679
+ var OP_SCOPE_PLAIN = 41;
4633
4680
  var OP_DISPATCH = 25;
4634
4681
  var OP_ROUTED = 26;
4635
4682
  var OP_NAMES = {
@@ -4672,7 +4719,8 @@ var OP_NAMES = {
4672
4719
  [OP_LIVE]: "LIVE",
4673
4720
  [OP_ATTEMPT]: "ATTEMPT",
4674
4721
  [OP_LABEL]: "LABEL",
4675
- [OP_COV]: "COV"
4722
+ [OP_COV]: "COV",
4723
+ [OP_SCOPE_PLAIN]: "SCOPE_PLAIN"
4676
4724
  };
4677
4725
 
4678
4726
  // src/table/program.ts
@@ -4730,6 +4778,15 @@ function expandCompact(p) {
4730
4778
  ...p.a === void 0 ? {} : { asm: p.a }
4731
4779
  });
4732
4780
  }
4781
+ function validateDispatchSpec(spec, arity, fallbackRouted) {
4782
+ const invalid = (arms) => {
4783
+ for (const arm of arms) if (!Number.isInteger(arm) || arm < 0 || arm >= arity) return true;
4784
+ return false;
4785
+ };
4786
+ 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]]))) {
4787
+ throw new TypeError("table: malformed dispatch");
4788
+ }
4789
+ }
4733
4790
  var TABLE_RUNTIME = /* @__PURE__ */ Symbol("parseman.tableRuntime");
4734
4791
  function ownTableProgram(prog, resolved) {
4735
4792
  return { ...prog, [TABLE_RUNTIME]: { resolved } };
@@ -5288,7 +5345,7 @@ var Encoder = class {
5288
5345
  this.carryTriviaMeta(amb);
5289
5346
  this.carryTriviaMeta(p);
5290
5347
  if (p._def.tag === "grammar") this.carryTriviaMeta(p._def.triviaParser);
5291
- this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE, this.triviaSlot(amb), body);
5348
+ this.rules[name] = amb === void 0 ? body : this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), body);
5292
5349
  }
5293
5350
  /**
5294
5351
  * The row a cross-rule `g.X` reference jumps to — the target's body, RE-WRAPPED
@@ -5331,7 +5388,7 @@ var Encoder = class {
5331
5388
  const amb = p._meta.grammarTrivia ?? target._meta.grammarTrivia;
5332
5389
  if (amb === void 0 || this.activeTrivia !== void 0) return ip;
5333
5390
  if (!hasOwnTriviaBoundary(target)) return ip;
5334
- return this.emit(OP_SCOPE, this.triviaSlot(amb), ip);
5391
+ return this.emit(OP_SCOPE_PLAIN, this.triviaSlot(amb), ip);
5335
5392
  }
5336
5393
  node(p) {
5337
5394
  const lazyRef = p._def.tag === "lazy";
@@ -5736,6 +5793,7 @@ var Encoder = class {
5736
5793
  return [ip + 1];
5737
5794
  case OP_SCOPE:
5738
5795
  case OP_SCOPE_CAP:
5796
+ case OP_SCOPE_PLAIN:
5739
5797
  case OP_WITHCTX:
5740
5798
  case OP_XFORM:
5741
5799
  case OP_LEAF:
@@ -6926,6 +6984,7 @@ function childSlots(code, ip, out) {
6926
6984
  case OP_GATE:
6927
6985
  case OP_SCOPE:
6928
6986
  case OP_SCOPE_CAP:
6987
+ case OP_SCOPE_PLAIN:
6929
6988
  case OP_WITHCTX:
6930
6989
  case OP_XFORM:
6931
6990
  case OP_NODE:
@@ -7014,7 +7073,7 @@ function reachableSites(code, roots) {
7014
7073
  }
7015
7074
  function transfer(code, ip, at, hostCst) {
7016
7075
  const op = code[ip];
7017
- if (op === OP_SCOPE || op === OP_SCOPE_CAP) {
7076
+ if (op === OP_SCOPE || op === OP_SCOPE_CAP || op === OP_SCOPE_PLAIN) {
7018
7077
  const ki = code[ip + 1];
7019
7078
  const tri = ki < 0 ? TRI_NONE : ki;
7020
7079
  const cap = op === OP_SCOPE_CAP ? CAP_ON : at.cap;
@@ -7095,6 +7154,7 @@ var EMITTED_PARAMS = [
7095
7154
  "pushCstLeaf",
7096
7155
  "pushCstChild",
7097
7156
  "rollbackTriviaAt",
7157
+ "rollbackScannedTriviaAt",
7098
7158
  "failAt",
7099
7159
  "classHas",
7100
7160
  "consumeTrivia",
@@ -7238,19 +7298,24 @@ if(ctx._errors!==undefined&&ctx._errors.length!==${t}er)ctx._errors.length=${t}e
7238
7298
  if (!s.fd && !s.er) return `if(${t}n)rollbackTriviaAt(ctx,${t}raw,${t}tl,${t}lv,0,undefined,${t}lg,${t}rt)`;
7239
7299
  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)}`;
7240
7300
  }
7241
- function emitTerm(callee, dst, t, l, skip, s) {
7301
+ function emitTerm(callee, dst, t, l, skip) {
7242
7302
  const fast = `const ${t}v=${callee}(input,cur,ctx)
7243
7303
  if(${t}v===FAIL)return FAIL
7244
7304
  ${dst}=${t}v
7245
7305
  cur=EC.e`;
7246
7306
  if (l.tri === TRI_NONE) return fast;
7247
- const scanned = `${emitMark(t, l.buf, s)}
7307
+ const scanned = `const ${t}tl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
7308
+ const ${t}lg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
7309
+ const ${t}rt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7248
7310
  const ${t}s=${skip}(input,cur,ctx)
7311
+ const ${t}stl=ctx._cstBuf!==undefined?(ctx._cstBuf.tl!==undefined?ctx._cstBuf.tl.length:0):(ctx._cstTriviaLog!==undefined?ctx._cstTriviaLog.length:0)
7312
+ const ${t}slg=ctx._triviaLog!==undefined?ctx._triviaLog.length:0
7313
+ const ${t}srt=ctx._rootTriviaLog!==undefined?ctx._rootTriviaLog.length:0
7249
7314
  const ${t}v=${callee}(input,${t}s,ctx)
7250
7315
  if(${t}v===FAIL)return FAIL
7251
7316
  ${dst}=${t}v
7252
7317
  if(EC.e>${t}s)cur=EC.e
7253
- else{${emitRollback(t, l.buf, s)}}`;
7318
+ else{rollbackScannedTriviaAt(ctx,${t}tl,${t}stl,${t}lg,${t}slg,${t}rt,${t}srt)}`;
7254
7319
  if (l.tri !== TRI_UNKNOWN) return scanned;
7255
7320
  return `if(ctx.trivia===undefined){
7256
7321
  ${fast}
@@ -7413,7 +7478,7 @@ ${cfg.probe ? `failAt(ctx,${xf},pos)
7413
7478
  const op = code[ip];
7414
7479
  if (op === OP_GATE && (cfg.tolerant || cfg.probe)) return code[ip + 2];
7415
7480
  if (op === OP_RULE) return code[ip + 1];
7416
- if (op === OP_SCOPE && code[ip + 3] === 0 && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
7481
+ if ((op === OP_SCOPE_PLAIN || op === OP_SCOPE && code[ip + 3] === 0) && code[ip + 1] >= 0 && labels.at(ip).tri === code[ip + 1]) {
7417
7482
  return code[ip + 2];
7418
7483
  }
7419
7484
  return void 0;
@@ -7581,10 +7646,11 @@ return r.value
7581
7646
  }`;
7582
7647
  }
7583
7648
  case OP_SCOPE:
7584
- case OP_SCOPE_CAP: {
7649
+ case OP_SCOPE_CAP:
7650
+ case OP_SCOPE_PLAIN: {
7585
7651
  const ki = code[ip + 1];
7586
7652
  const cap = op === OP_SCOPE_CAP;
7587
- const flags = code[ip + 3];
7653
+ const flags = op === OP_SCOPE_PLAIN ? 0 : code[ip + 3];
7588
7654
  const child = link(code[ip + 2]);
7589
7655
  const scanFor = swapLegal && ki >= 0 && !triviaLabelled[ki] ? hoist("ts", `TRIVIASCAN[${ki}]`) : "null";
7590
7656
  const tri = ki < 0 ? "undefined" : hoist("tv", `TRIVIA[${ki}]`);
@@ -7738,7 +7804,7 @@ return v
7738
7804
  const vn = `v${i}`;
7739
7805
  parts.push(`let ${vn}`);
7740
7806
  if (REC2) parts.push(pub(i));
7741
- parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L), sinks));
7807
+ parts.push(emitTerm(kids[i], vn, tmp(), L, skipFor(L)));
7742
7808
  names.push(vn);
7743
7809
  }
7744
7810
  parts.push("EC.e=cur");
@@ -7839,11 +7905,11 @@ return FAIL
7839
7905
  const other = otherIp >= 0 ? link(otherIp) : void 0;
7840
7906
  const otherRouted = code[ip + 4] === 1;
7841
7907
  const n = code[ip + 5];
7908
+ validateDispatchSpec(spec, n, code[ip + 4]);
7842
7909
  const armBase = ip + 6;
7843
7910
  const arms = [];
7844
7911
  for (let i = 0; i < n; i++) arms.push(link(code[armBase + i]));
7845
7912
  const bk = hoist("bk", `DSP[${di}].byKey`);
7846
- const rt = hoist("rt", `DSP[${di}].routed`);
7847
7913
  const dx = hoist("dx", `DSP[${di}].expected`);
7848
7914
  const claims = (m) => {
7849
7915
  switch (m[0]) {
@@ -7867,6 +7933,15 @@ ${spec.match.map((m, i) => `${i === 0 ? "" : "else "}if(${claims(m)})arm=${m[3]}
7867
7933
  ` : "";
7868
7934
  const m1 = tmp();
7869
7935
  const m2 = tmp();
7936
+ const routedCall = (target) => `{const savedRouted=ctx._routed
7937
+ ${emitRollback(m1, L.buf, sinks)}
7938
+ ${emitMark(m2, L.buf, sinks, false)}
7939
+ ctx._routed={value:key,span:{start:pos,end:selEnd}}
7940
+ try{v=${target}(input,pos,ctx)}finally{ctx._routed=savedRouted}
7941
+ break}`;
7942
+ const plainCall = (target) => `v=${target}(input,selEnd,ctx);break`;
7943
+ const armCases = arms.map((target, i) => `case ${i}:${spec.routed[i] === 1 ? routedCall(target) : plainCall(target)}`).join("\n");
7944
+ const fallbackCase = other === void 0 ? "" : `default:${otherRouted ? routedCall(other) : plainCall(other)}`;
7870
7945
  return `${head}
7871
7946
  ${emitMark(m1, L.buf, sinks)}
7872
7947
  const sv=${selector}(input,pos,ctx)
@@ -7874,24 +7949,16 @@ if(sv===FAIL)return FAIL
7874
7949
  const selEnd=EC.e
7875
7950
  const key=sv
7876
7951
  let arm=${bk}.get(key)
7877
- ${fold}${chain}let ur
7952
+ ${fold}${chain}
7878
7953
  if(arm===undefined){
7879
- ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : `ur=${String(otherRouted)}`}
7880
- }else ur=${rt}[arm]===1
7881
- const savedRouted=ctx._routed
7882
- ${emitMark(m2, L.buf, sinks)}
7883
- if(ur){
7884
- ${emitRollback(m1, L.buf, sinks)}
7885
- ${emitMark(m2, L.buf, sinks, false)}
7886
- ctx._routed={value:key,span:{start:pos,end:selEnd}}
7954
+ ${other === void 0 ? `ctx._fe=selEnd;ctx._fx=${dx};return FAIL` : ""}
7887
7955
  }
7888
- const at=ur?pos:selEnd
7956
+ ${emitMark(m2, L.buf, sinks)}
7889
7957
  let v
7890
7958
  switch(arm){
7891
- ${arms.map((a, i) => `case ${i}:v=${a}(input,at,ctx);break`).join("\n")}
7892
- ${other === void 0 ? "" : `default:v=${other}(input,at,ctx)`}
7959
+ ${armCases}
7960
+ ${fallbackCase}
7893
7961
  }
7894
- if(ur)ctx._routed=savedRouted
7895
7962
  if(v===FAIL){
7896
7963
  ${emitRollback(m2, L.buf, sinks)}
7897
7964
  ctx._fc=true
@@ -8354,7 +8421,7 @@ function committed(c) {
8354
8421
  }
8355
8422
  function stampRuleMap(prog, d, artifactMetadata = {}, resolved = resolveTable(prog)) {
8356
8423
  const triviaOfRule = (ip) => {
8357
- if (prog.code[ip] !== OP_SCOPE) return void 0;
8424
+ if (prog.code[ip] !== OP_SCOPE_PLAIN && prog.code[ip] !== OP_SCOPE) return void 0;
8358
8425
  const slot = prog.code[ip + 1];
8359
8426
  return slot < 0 ? void 0 : resolved.trivia[slot];
8360
8427
  };
@@ -8568,20 +8635,19 @@ function assemble(t, prog, cfg) {
8568
8635
  TERMV = v2;
8569
8636
  return EC.e > scanEnd2 ? EC.e : cur;
8570
8637
  }
8571
- const need = markCst(ctx);
8572
- const mRaw = MRAW;
8573
- const mTl = MTL;
8574
- const mLv = MLV;
8575
- const mFl = need ? ctx._fields?.length ?? 0 : 0;
8576
- const mEr = need ? ctx._errors?.length ?? 0 : 0;
8638
+ const need = rollbackNeeded(ctx);
8639
+ const mTl = need ? cstTlLen(ctx) : 0;
8577
8640
  const mLog = need ? ctx._triviaLog?.length ?? 0 : 0;
8578
8641
  const mRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
8579
8642
  const scanEnd = skipTrivia(input, cur, ctx);
8643
+ const scanTl = need ? cstTlLen(ctx) : 0;
8644
+ const scanLog = need ? ctx._triviaLog?.length ?? 0 : 0;
8645
+ const scanRoot = need ? ctx._rootTriviaLog?.length ?? 0 : 0;
8580
8646
  const v = child(input, scanEnd, ctx);
8581
8647
  if (v === FAIL) return -1;
8582
8648
  TERMV = v;
8583
8649
  if (EC.e > scanEnd) return EC.e;
8584
- if (need) rollbackTriviaAt(ctx, mRaw, mTl, mLv, mFl, mEr, mLog, mRoot);
8650
+ if (need) rollbackScannedTriviaAt(ctx, mTl, scanTl, mLog, scanLog, mRoot, scanRoot);
8585
8651
  return cur;
8586
8652
  }
8587
8653
  function committed2(c) {
@@ -8995,7 +9061,8 @@ function assemble(t, prog, cfg) {
8995
9061
  };
8996
9062
  }
8997
9063
  case OP_SCOPE:
8998
- case OP_SCOPE_CAP: {
9064
+ case OP_SCOPE_CAP:
9065
+ case OP_SCOPE_PLAIN: {
8999
9066
  const ki = code[ip + 1];
9000
9067
  const scopeTrivia = ki < 0 ? void 0 : trivia2[ki];
9001
9068
  const scopeLabels = scopeTrivia?._meta.triviaKindLabels;
@@ -9029,7 +9096,7 @@ function assemble(t, prog, cfg) {
9029
9096
  SCAN = savedScan;
9030
9097
  return v;
9031
9098
  };
9032
- return scopeRootPolicy(scopePiece, code[ip + 3]);
9099
+ return scopeRootPolicy(scopePiece, code[ip] === OP_SCOPE_PLAIN ? 0 : code[ip + 3]);
9033
9100
  }
9034
9101
  case OP_ROUTED: {
9035
9102
  const fb = code[ip + 1];
@@ -9945,15 +10012,21 @@ function assemble(t, prog, cfg) {
9945
10012
  target = arms[arm];
9946
10013
  usesRouted = routed2[arm] === 1;
9947
10014
  }
9948
- const savedRouted = ctx._routed;
9949
10015
  let mark = saveTriviaMark(ctx);
10016
+ let v;
9950
10017
  if (usesRouted) {
10018
+ const savedRouted = ctx._routed;
9951
10019
  rollbackTrivia(ctx, selectorMark);
9952
10020
  mark = saveTriviaMark(ctx);
9953
10021
  ctx._routed = { value: key, span: { start: pos, end: selEnd } };
10022
+ try {
10023
+ v = target(input, pos, ctx);
10024
+ } finally {
10025
+ ctx._routed = savedRouted;
10026
+ }
10027
+ } else {
10028
+ v = target(input, selEnd, ctx);
9954
10029
  }
9955
- const v = target(input, usesRouted ? pos : selEnd, ctx);
9956
- if (usesRouted) ctx._routed = savedRouted;
9957
10030
  if (v === FAIL) {
9958
10031
  rollbackTrivia(ctx, mark);
9959
10032
  ctx._fc = true;
@@ -10099,6 +10172,11 @@ function assemble(t, prog, cfg) {
10099
10172
  if (s.sentinel !== void 0) extraIps.push(s.sentinel[0]);
10100
10173
  }
10101
10174
  for (const set of prog.scanSkip ?? []) for (const r of set) extraIps.push(r[0]);
10175
+ const validationRoots = [...Object.values(prog.rules), ...extraIps];
10176
+ for (const ip of reachableSites(code, validationRoots)) {
10177
+ if (code[ip] !== OP_DISPATCH) continue;
10178
+ validateDispatchSpec(dsp[code[ip + 2]], code[ip + 5], code[ip + 4]);
10179
+ }
10102
10180
  const pre = cfg.hostCaptureTrivia === void 0 ? prog.asm?.find((a) => a.key === cfgKey(cfg)) : void 0;
10103
10181
  if (pre !== void 0) {
10104
10182
  const pools = rebuildPools(t.cc, t.fx, pre.plan);
@@ -10125,6 +10203,7 @@ function assemble(t, prog, cfg) {
10125
10203
  pushCstLeaf,
10126
10204
  pushCstChild,
10127
10205
  rollbackTriviaAt,
10206
+ rollbackScannedTriviaAt,
10128
10207
  failAt,
10129
10208
  classHas,
10130
10209
  consumeTrivia,
@@ -10195,6 +10274,7 @@ function assemble(t, prog, cfg) {
10195
10274
  pushCstLeaf,
10196
10275
  pushCstChild,
10197
10276
  rollbackTriviaAt,
10277
+ rollbackScannedTriviaAt,
10198
10278
  failAt,
10199
10279
  classHas,
10200
10280
  consumeTrivia,
@@ -10427,6 +10507,14 @@ function tableRules(source, artifactMetadata = {}) {
10427
10507
  function jsString(s) {
10428
10508
  return JSON.stringify(s);
10429
10509
  }
10510
+ function emitClassPool(classes) {
10511
+ const array = `[${classes.map(jsString).join(",")}]`;
10512
+ if (classes.length < 2) return array;
10513
+ const delimiter = "|/~?^`".split("").find((ch2) => classes.every((spec) => !spec.includes(ch2)));
10514
+ if (delimiter === void 0) return array;
10515
+ const split = `${jsString(classes.join(delimiter))}.split(${jsString(delimiter)})`;
10516
+ return split.length < array.length ? split : array;
10517
+ }
10430
10518
  function emitConst(v) {
10431
10519
  if (v instanceof RegExp) return `/${v.source}/${v.flags}`;
10432
10520
  if (typeof v === "string") return jsString(v);
@@ -10505,7 +10593,7 @@ function programFields(prog, fns, opts = {}) {
10505
10593
  ...emitAssemblies(prog, opts.assemblies ?? []),
10506
10594
  `c:[${prog.code.join(",")}],`,
10507
10595
  `k:[${prog.k.map(emitConst).join(",")}],`,
10508
- `x:[${prog.cc.map(jsString).join(",")}],`,
10596
+ `x:${emitClassPool(prog.cc)},`,
10509
10597
  `e:[${prog.fx.map((f) => `[${f.map(jsString).join(",")}]`).join(",")}],`,
10510
10598
  `d:[${prog.disp.map((a) => `[${a.join(",")}]`).join(",")}],`,
10511
10599
  `r:${JSON.stringify(prog.rules)},`,
@@ -12857,7 +12945,7 @@ function compileRuleMap(ruleMap, opts = {}) {
12857
12945
  }
12858
12946
 
12859
12947
  // src/version.ts
12860
- var PARSEMAN_VERSION = "0.47.0";
12948
+ var PARSEMAN_VERSION = "0.47.1";
12861
12949
 
12862
12950
  // src/compiler/compile-linkable-table.ts
12863
12951
  function isLocal(rule) {