parseman 0.28.1 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAwBA,OAAO,WAAW,MAAM,cAAc,CAAA;AAkBtC,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;8CAC0C;IAC1C,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAA;;;AAgSD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IAC3C,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AA0CD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,aAAa,cAA6B,EAC1C,kBAAkB,UAAQ,EAC1B,QAAQ,UAAQ,EAChB,eAAe,UAAQ,GACtB,oBAAoB,GAAG,IAAI,CA27B7B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAwBA,OAAO,WAAW,MAAM,cAAc,CAAA;AAkBtC,MAAM,MAAM,uBAAuB,GAAG;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;8CAC0C;IAC1C,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAA;;;AAgSD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;IAC3C,kFAAkF;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AA0CD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,aAAa,cAA6B,EAC1C,kBAAkB,UAAQ,EAC1B,QAAQ,UAAQ,EAChB,eAAe,UAAQ,GACtB,oBAAoB,GAAG,IAAI,CAi8B7B"}
@@ -4116,6 +4116,61 @@ function tryInlineDestructureTransform(src, valueVars) {
4116
4116
  }
4117
4117
 
4118
4118
  // src/compiler/codegen.ts
4119
+ function leadingFirstSetRecipe(p, seen = /* @__PURE__ */ new Set()) {
4120
+ if (seen.has(p)) return { concrete: empty(), refs: [] };
4121
+ seen.add(p);
4122
+ const d = p._def;
4123
+ const rec = (c) => leadingFirstSetRecipe(c, seen);
4124
+ const merge = (a, b) => ({ concrete: union(a.concrete, b.concrete), refs: [...a.refs, ...b.refs] });
4125
+ switch (d.tag) {
4126
+ case "lazy": {
4127
+ const name = p._ruleName;
4128
+ if (name !== void 0) return { concrete: empty(), refs: [name] };
4129
+ try {
4130
+ return rec(d.thunk());
4131
+ } catch {
4132
+ return { concrete: any(), refs: [] };
4133
+ }
4134
+ }
4135
+ case "literal":
4136
+ case "regex":
4137
+ case "keywords":
4138
+ return { concrete: p._meta.firstSet, refs: [] };
4139
+ case "choice": {
4140
+ let out = { concrete: empty(), refs: [] };
4141
+ for (const arm of d.parsers) out = merge(out, rec(arm));
4142
+ return out;
4143
+ }
4144
+ case "sequence": {
4145
+ let out = { concrete: empty(), refs: [] };
4146
+ for (const term of d.parsers) {
4147
+ out = merge(out, rec(term));
4148
+ if (!matchesEmpty(term)) return out;
4149
+ }
4150
+ return out;
4151
+ }
4152
+ case "oneOrMore":
4153
+ case "many":
4154
+ case "optional":
4155
+ case "transform":
4156
+ case "label":
4157
+ case "field":
4158
+ case "trivia":
4159
+ case "token":
4160
+ case "leaf":
4161
+ case "node":
4162
+ case "grammar":
4163
+ case "expect":
4164
+ return rec(d.parser);
4165
+ case "sepBy":
4166
+ return rec(d.parser);
4167
+ case "skip":
4168
+ return rec(d.main);
4169
+ // not / scanTo / guard / withCtx / recover / unknown → shallow set (safe).
4170
+ default:
4171
+ return { concrete: p._meta.firstSet, refs: [] };
4172
+ }
4173
+ }
4119
4174
  var HOST_READS_DECL = "const _hostReads = (b, n) => { if (b === undefined) return false; let s; try { s = Function.prototype.toString.call(b) } catch (e) { return true } if (/\\barguments\\b/.test(s)) return true; const m = /^[^(]*\\(([\\s\\S]*?)\\)/.exec(s); if (m && /\\.\\.\\.|=/.test(m[1])) return true; return b.length > n }";
4120
4175
  var _loweringSink = null;
4121
4176
  function beginLoweringCapture() {
@@ -5170,6 +5225,13 @@ function emitMany(def, ctx, pos) {
5170
5225
  itemPos = npV;
5171
5226
  }
5172
5227
  }
5228
+ if (!ctx.recovery && !ctx.coverage && !failsAtStart(def.parser) && needsFirstSetGuard(def.parser)) {
5229
+ const lcV = v(ctx, "_lc");
5230
+ stmts.push(
5231
+ `${ind(ctx)}const ${lcV} = ${itemPos} < input.length ? (input.codePointAt(${itemPos}) ?? -1) : -1`,
5232
+ `${ind(ctx)}if (!(${firstSetCond(lcV, def.parser._meta.firstSet)})) { ${rollback}break }`
5233
+ );
5234
+ }
5173
5235
  const { stmts: iterStmts, okVar: iterOk, valVar: iterVal, endVar: iterEnd } = emitFallible(def.parser, ctx, itemPos, true);
5174
5236
  stmts.push(...iterStmts);
5175
5237
  if (ctx.recovery) {
@@ -5220,8 +5282,19 @@ function emitAttempt(p, def, ctx, pos) {
5220
5282
  const rollback = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${leaves}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${raw}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${trivia2}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${log}; if (_ctx._fields) _ctx._fields.length = ${fields}; if (_ctx._errors) _ctx._errors.length = ${errors}`;
5221
5283
  const traceId = ctx.coverage?.plan.attempts.get(p);
5222
5284
  const traceRollback = traceId === void 0 ? "" : ` _ctx._grammarTrace?.write({ id: ${JSON.stringify(traceId)}, phase: 'rollback', offset: ${pos} });`;
5285
+ const preGuard = [];
5286
+ if (!ctx.recovery && !ctx.coverage && needsFirstSetGuard(def.parser)) {
5287
+ const gcV = v(ctx, "_agc");
5288
+ const gExp = armStaticExpected(ctx, def.parser);
5289
+ const gFail = ctx.failLabel ? `{ _ctx._fe = ${pos};${ctx.recordFail ? ` _ctx._fx = ${gExp};` : ""} break ${ctx.failLabel} }` : `{ _ctx._fe = ${pos}; ${failReturnArr(gExp, pos)} }`;
5290
+ preGuard.push(
5291
+ `${ind(ctx)}const ${gcV} = ${pos} < input.length ? (input.codePointAt(${pos}) ?? -1) : -1`,
5292
+ `${ind(ctx)}if (!(${firstSetCond(gcV, def.parser._meta.firstSet)})) ${gFail}`
5293
+ );
5294
+ }
5223
5295
  return {
5224
5296
  stmts: [
5297
+ ...preGuard,
5225
5298
  `${ind(ctx)}const ${leaves} = _ctx._cstLeaves?.length ?? 0, ${raw} = _ctx._cstRawChildren?.length ?? 0, ${trivia2} = _ctx._cstTriviaLog?.length ?? 0, ${log} = _ctx._triviaLog?.length ?? 0, ${fields} = _ctx._fields?.length ?? 0, ${errors} = _ctx._errors?.length ?? 0`,
5226
5299
  ...inner.stmts,
5227
5300
  ...emitIfFail(ctx, `!${inner.okVar}`, `{ ${rollback};${traceRollback} _ctx._fe = ${pos}; ${propagateFailBody(ctx)} }`)
@@ -5601,7 +5674,18 @@ ${i}const ${chV} = ${profileRecognizer} ? undefined : [], ${rawV} = ${profileRec
5601
5674
  const saveTrivia = needsTriviaFrame ? `, ${st} = _ctx.captureTrivia, ${stl} = _ctx._cstTriviaLog${smk ? `, ${smk} = _ctx._triviaCaptureMask` : ""}` : "";
5602
5675
  const installTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${capTLv ?? "false"}; _ctx._cstTriviaLog = ${innerTl}${smk ? `; _ctx._triviaCaptureMask = ${capTLv} && _ctx.build !== undefined && _ctx.build._parsemanTriviaKinds !== undefined ? _ctx.build._parsemanTriviaKinds(${JSON.stringify(def.type)}) : ${smk}` : ""}` : "";
5603
5676
  const restoreTrivia = needsTriviaFrame ? `; _ctx.captureTrivia = ${st}; _ctx._cstTriviaLog = ${stl}${smk ? `; _ctx._triviaCaptureMask = ${smk}` : ""}` : "";
5677
+ const preGuard = [];
5678
+ if (!ctx.recovery && !ctx.coverage && (capturesChildren || structural) && needsFirstSetGuard(def.parser)) {
5679
+ const gcV = v(ctx, "_ngc");
5680
+ const gExp = armStaticExpected(ctx, def.parser);
5681
+ const gFail = ctx.failLabel ? ctx.recordFail ? `{ _ctx._fe = ${pos}; _ctx._fx = ${gExp}; break ${ctx.failLabel} }` : `break ${ctx.failLabel}` : failReturnArr(gExp, pos);
5682
+ preGuard.push(
5683
+ `${i}const ${gcV} = ${pos} < input.length ? (input.codePointAt(${pos}) ?? -1) : -1`,
5684
+ `${i}if (!(${firstSetCond(gcV, def.parser._meta.firstSet)})) ${gFail}`
5685
+ );
5686
+ }
5604
5687
  const stmts = [
5688
+ ...preGuard,
5605
5689
  profHoist,
5606
5690
  allocStmt,
5607
5691
  `${i}const ${sc} = _ctx._cstChildren, ${sl} = _ctx._cstLeaves, ${sr} = _ctx._cstRawChildren${saveTrivia}${sf ? `, ${sf} = _ctx._fields` : ""}`,
@@ -6628,6 +6712,7 @@ function compileLinkable(ruleMapArg, ns, opts) {
6628
6712
  ].join("\n")));
6629
6713
  }
6630
6714
  const firstSets = /* @__PURE__ */ new Map();
6715
+ const firstSetRecipes = /* @__PURE__ */ new Map();
6631
6716
  for (const [key, rule] of ruleMap) {
6632
6717
  let resolved = rule;
6633
6718
  const d = rule._def;
@@ -6639,6 +6724,7 @@ function compileLinkable(ruleMapArg, ns, opts) {
6639
6724
  }
6640
6725
  }
6641
6726
  firstSets.set(key, canMatchEmptyAtStart(resolved) ? { kind: "any" } : resolved._meta.firstSet);
6727
+ firstSetRecipes.set(key, canMatchEmptyAtStart(resolved) ? { concrete: any(), refs: [] } : leadingFirstSetRecipe(resolved));
6642
6728
  }
6643
6729
  return {
6644
6730
  ns,
@@ -6647,6 +6733,7 @@ function compileLinkable(ruleMapArg, ns, opts) {
6647
6733
  ruleFns,
6648
6734
  wrappers,
6649
6735
  firstSets,
6736
+ firstSetRecipes,
6650
6737
  deps: ruleDependencies(ruleMap),
6651
6738
  needsEmptyTl: !!ctx.needsEmptyTl,
6652
6739
  needsHostReads: !!ctx.needsHostReads,
@@ -7293,10 +7380,30 @@ function fusedBody(pieces) {
7293
7380
  ];
7294
7381
  const wrapperEntries = [...winner].map(([k, p]) => `${JSON.stringify(k)}: ${p.wrappers.get(k)}`);
7295
7382
  const rawBody = [...lines, "return {", wrapperEntries.join(",\n"), "}"].join("\n");
7296
- const finalFS = /* @__PURE__ */ new Map();
7383
+ const ANY2 = { kind: "any" };
7384
+ const recipes = /* @__PURE__ */ new Map();
7385
+ const shallow = /* @__PURE__ */ new Map();
7297
7386
  for (const [k, p] of winner) {
7387
+ const r = p.firstSetRecipes?.get(k);
7388
+ if (r) recipes.set(k, r);
7298
7389
  const fs2 = p.firstSets?.get(k);
7299
- if (fs2) finalFS.set(k, fs2);
7390
+ if (fs2) shallow.set(k, fs2);
7391
+ }
7392
+ const finalFS = /* @__PURE__ */ new Map();
7393
+ for (const [k] of winner) finalFS.set(k, recipes.get(k)?.concrete ?? shallow.get(k) ?? ANY2);
7394
+ for (let iter = 0; iter <= recipes.size; iter++) {
7395
+ let changed = false;
7396
+ for (const [k, r] of recipes) {
7397
+ let fs2 = r.concrete;
7398
+ for (const ref2 of r.refs) {
7399
+ fs2 = union(fs2, recipes.has(ref2) || shallow.has(ref2) ? finalFS.get(ref2) ?? ANY2 : ANY2);
7400
+ }
7401
+ if (JSON.stringify(finalFS.get(k)) !== JSON.stringify(fs2)) {
7402
+ finalFS.set(k, fs2);
7403
+ changed = true;
7404
+ }
7405
+ }
7406
+ if (!changed) break;
7300
7407
  }
7301
7408
  const body = rawBody.replace(
7302
7409
  // Rule name + code-point var are both JS identifiers (rule names are validated
@@ -8467,7 +8574,7 @@ function transformMacro(code, id, moduleAliases = /* @__PURE__ */ new Set([PARSE
8467
8574
  const mapLit = (m, stripVals = false) => `new Map([${[...m].map(
8468
8575
  ([k, v2]) => `[${JSON.stringify(k)}, ${JSON.stringify(stripVals && typeof v2 === "string" ? stripIndent(v2) : v2)}]`
8469
8576
  ).join(", ")}])`;
8470
- return `{ ns: ${JSON.stringify(p.ns)}, keys: ${JSON.stringify(p.keys)}, prelude: ${JSON.stringify(p.prelude.map(stripIndent))}, ruleFns: ${mapLit(p.ruleFns, true)}, wrappers: ${mapLit(p.wrappers, true)}, firstSets: ${mapLit(p.firstSets)}, deps: ${mapLit(p.deps)}, needsEmptyTl: ${p.needsEmptyTl}, needsHostReads: ${p.needsHostReads}, hasDirectBuilders: ${p.hasDirectBuilders === true}, isRecognitionOnly: ${p.isRecognitionOnly === true}, mfFns: [], buildFns: [] }`;
8577
+ return `{ ns: ${JSON.stringify(p.ns)}, keys: ${JSON.stringify(p.keys)}, prelude: ${JSON.stringify(p.prelude.map(stripIndent))}, ruleFns: ${mapLit(p.ruleFns, true)}, wrappers: ${mapLit(p.wrappers, true)}, firstSets: ${mapLit(p.firstSets)}, firstSetRecipes: ${p.firstSetRecipes ? mapLit(p.firstSetRecipes) : "new Map()"}, deps: ${mapLit(p.deps)}, needsEmptyTl: ${p.needsEmptyTl}, needsHostReads: ${p.needsHostReads}, hasDirectBuilders: ${p.hasDirectBuilders === true}, isRecognitionOnly: ${p.isRecognitionOnly === true}, mfFns: [], buildFns: [] }`;
8471
8578
  };
8472
8579
  const isSpread = (it) => "__spreadLocal" in it;
8473
8580
  const isIR = (it) => "ir" in it && !("ruleFns" in it);