parseman 0.34.0 → 0.36.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.
@@ -380,28 +380,28 @@ function rollbackBufList(b, keyMulti, keySingle, len) {
380
380
  else if (len === 1) {
381
381
  b[keySingle] = arr[0];
382
382
  b[keyMulti] = void 0;
383
- } else arr.length = len;
383
+ } else if (arr.length !== len) arr.length = len;
384
384
  return;
385
385
  }
386
386
  if (len === 0) b[keySingle] = void 0;
387
387
  }
388
388
  function rollbackCstCapture(ctx, mark) {
389
- if (ctx._errors && mark.errors !== void 0) ctx._errors.length = mark.errors;
389
+ if (ctx._errors && mark.errors !== void 0 && ctx._errors.length !== mark.errors) ctx._errors.length = mark.errors;
390
390
  const b = ctx._cstBuf;
391
391
  if (b) {
392
392
  rollbackBufList(b, "raw", "rawSingle", mark.raw);
393
393
  rollbackBufList(b, "ch", "single", mark.leaves);
394
394
  if (b.tl) {
395
395
  if (mark.tlog === 0) b.tl = void 0;
396
- else b.tl.length = mark.tlog;
396
+ else if (b.tl.length !== mark.tlog) b.tl.length = mark.tlog;
397
397
  }
398
- if (ctx._fields) ctx._fields.length = mark.fields;
398
+ if (ctx._fields && ctx._fields.length !== mark.fields) ctx._fields.length = mark.fields;
399
399
  return;
400
400
  }
401
- if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
402
- if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
403
- if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
404
- if (ctx._fields) ctx._fields.length = mark.fields;
401
+ if (ctx._cstRawChildren && ctx._cstRawChildren.length !== mark.raw) ctx._cstRawChildren.length = mark.raw;
402
+ if (ctx._cstTriviaLog && ctx._cstTriviaLog.length !== mark.tlog) ctx._cstTriviaLog.length = mark.tlog;
403
+ if (ctx._cstLeaves && ctx._cstLeaves.length !== mark.leaves) ctx._cstLeaves.length = mark.leaves;
404
+ if (ctx._fields && ctx._fields.length !== mark.fields) ctx._fields.length = mark.fields;
405
405
  }
406
406
  function pushCstTriviaEntry(ctx, start, end, kindIndex) {
407
407
  const insertIdx = cstRawLen(ctx);
@@ -1090,6 +1090,10 @@ function captureError(ctx, error) {
1090
1090
 
1091
1091
  // src/combinators/expect.ts
1092
1092
  function deriveExpected(c) {
1093
+ return [...new Set(derive(c, /* @__PURE__ */ new Set()))];
1094
+ }
1095
+ function derive(c, seen) {
1096
+ const deriveExpected2 = (p) => derive(p, seen);
1093
1097
  const def = c._def;
1094
1098
  switch (def.tag) {
1095
1099
  case "literal":
@@ -1101,20 +1105,32 @@ function deriveExpected(c) {
1101
1105
  case "label":
1102
1106
  return [def.label];
1103
1107
  case "choice":
1104
- return def.parsers.flatMap(deriveExpected);
1105
- case "sequence":
1106
- return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
1108
+ return def.parsers.flatMap(deriveExpected2);
1109
+ // Union through the NULLABLE prefix, mirroring `sequenceFirstSet`. A leading
1110
+ // `optional(…)`/`many(…)` can match nothing, so the term after it is equally
1111
+ // able to fail first — deriving from term 0 alone named a token the parse
1112
+ // never actually required. A leading `not(…)` is zero-width and contributes
1113
+ // nothing (its own expectation is about what must NOT be here), but it is
1114
+ // nullable, so keep scanning past it. Stop at the first term that must match.
1115
+ case "sequence": {
1116
+ const out = [];
1117
+ for (const term of def.parsers) {
1118
+ if (!isZeroWidthAssertion(term)) out.push(...deriveExpected2(term));
1119
+ if (!matchesEmpty(term)) break;
1120
+ }
1121
+ return out;
1122
+ }
1107
1123
  case "attempt":
1108
- return deriveExpected(def.parser);
1124
+ return deriveExpected2(def.parser);
1109
1125
  // Delegating wrappers whose first-token failure is their inner parser's — must
1110
1126
  // pass through so a start-failure (and the first-set-miss fast-path in attempt/
1111
1127
  // node, which reads this) names the real expected token, not the wrapper tag.
1112
1128
  case "field":
1113
1129
  case "withCtx":
1114
1130
  case "recover":
1115
- return deriveExpected(def.parser);
1131
+ return deriveExpected2(def.parser);
1116
1132
  case "skip":
1117
- return deriveExpected(def.main);
1133
+ return deriveExpected2(def.main);
1118
1134
  case "expect":
1119
1135
  return def.expected;
1120
1136
  case "node":
@@ -1128,13 +1144,17 @@ function deriveExpected(c) {
1128
1144
  case "transform":
1129
1145
  case "not":
1130
1146
  case "peek":
1131
- return deriveExpected(def.parser);
1147
+ return deriveExpected2(def.parser);
1132
1148
  case "lazy": {
1133
1149
  const name = c._ruleName;
1150
+ if (seen.has(c)) return name ? [name] : [];
1151
+ seen.add(c);
1134
1152
  try {
1135
- return deriveExpected(def.thunk());
1153
+ return deriveExpected2(def.thunk());
1136
1154
  } catch {
1137
1155
  return name ? [name] : [];
1156
+ } finally {
1157
+ seen.delete(c);
1138
1158
  }
1139
1159
  }
1140
1160
  default:
@@ -1262,14 +1282,14 @@ function choice(...args) {
1262
1282
  const result = parsers[i].parse(input, pos, ctx);
1263
1283
  if (!result.ok) {
1264
1284
  rollbackCstCapture(ctx, mark);
1265
- if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
1285
+ if (logLen !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== logLen) ctx._triviaLog.length = logLen;
1266
1286
  expected.push(...result.expected);
1267
1287
  continue;
1268
1288
  }
1269
1289
  const checks = autoNot[i];
1270
1290
  if (checks && autoNotFires(input, result.span.end, checks)) {
1271
1291
  rollbackCstCapture(ctx, mark);
1272
- if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
1292
+ if (logLen !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== logLen) ctx._triviaLog.length = logLen;
1273
1293
  continue;
1274
1294
  }
1275
1295
  return result;
@@ -1596,7 +1616,7 @@ function saveTriviaMark(ctx) {
1596
1616
  }
1597
1617
  function rollbackTrivia(ctx, mark) {
1598
1618
  rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields, errors: mark.errors });
1599
- if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
1619
+ if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
1600
1620
  }
1601
1621
  function saveLookaheadMark(ctx) {
1602
1622
  return { ...saveTriviaMark(ctx), probeBest: ctx._probe ? ctx._probe.best : null };
@@ -1964,7 +1984,7 @@ function attempt(parser2) {
1964
1984
  const result = parser2.parse(input, pos, ctx);
1965
1985
  if (result.ok) return result;
1966
1986
  rollbackCstCapture(ctx, mark);
1967
- if (log !== void 0 && ctx._triviaLog) ctx._triviaLog.length = log;
1987
+ if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
1968
1988
  return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
1969
1989
  }
1970
1990
  };
@@ -2974,7 +2994,7 @@ function leaf(root, fn) {
2974
2994
  }
2975
2995
 
2976
2996
  // src/version.ts
2977
- var PARSEMAN_VERSION = "0.34.0";
2997
+ var PARSEMAN_VERSION = "0.36.0";
2978
2998
 
2979
2999
  // src/analysis/gating.ts
2980
3000
  var isAny = (fs2) => fs2.kind === "any";
@@ -5173,9 +5193,9 @@ function planDisjointDispatch(parsers) {
5173
5193
  return total >= SWITCH_MIN_CASES ? { kind: "switch", cases } : { kind: "if" };
5174
5194
  }
5175
5195
  function captureRestoreBody(mL, mR, mTl, mLg, mF = null) {
5176
- const fieldRestore = mF ? `; if (_ctx._fields) _ctx._fields.length = ${mF}` : "";
5177
- const base = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}${fieldRestore}`;
5178
- return mLg ? `${base}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mLg}` : base;
5196
+ const fieldRestore = mF ? `; if (_ctx._fields && _ctx._fields.length !== ${mF}) _ctx._fields.length = ${mF}` : "";
5197
+ const base = `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${mL}) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${mR}) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${mTl}) _ctx._cstTriviaLog.length = ${mTl}${fieldRestore}`;
5198
+ return mLg ? `${base}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${mLg}) _ctx._triviaLog.length = ${mLg}` : base;
5179
5199
  }
5180
5200
  function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
5181
5201
  if (seen.has(p)) return false;
@@ -5537,7 +5557,7 @@ function emitSeqValues(def, ctx, pos) {
5537
5557
  const endAfterV = v(ctx, "_sea");
5538
5558
  stmts.push(
5539
5559
  `${ind(ctx)}const ${endAfterV} = ${r2.endVar}`,
5540
- `${ind(ctx)}if (${endAfterV} > ${scanEndV}) { ${curV} = ${endAfterV} } else { if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; }`
5560
+ `${ind(ctx)}if (${endAfterV} > ${scanEndV}) { ${curV} = ${endAfterV} } else { if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markV}) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${markTl}) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}; }`
5541
5561
  );
5542
5562
  valueVars.push(r2.valueVar);
5543
5563
  continue;
@@ -6024,7 +6044,7 @@ function emitMany(def, ctx, pos) {
6024
6044
  `${ind(ctx)}const ${npV} = ${capFn}(input, ${curV}, _ctx, 1)`
6025
6045
  );
6026
6046
  itemPos = npV;
6027
- rollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; `;
6047
+ rollback = `if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markV}) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${markTl}) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}; `;
6028
6048
  } else {
6029
6049
  const trivFn = ensureTriviaFn(ctx);
6030
6050
  const npV = v(ctx, "_np");
@@ -6087,7 +6107,7 @@ function emitAttempt(p, def, ctx, pos) {
6087
6107
  const log = v(ctx, "_atg");
6088
6108
  const fields = v(ctx, "_atf");
6089
6109
  const errors = v(ctx, "_ate");
6090
- 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}`;
6110
+ const rollback = `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${leaves}) _ctx._cstLeaves.length = ${leaves}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${raw}) _ctx._cstRawChildren.length = ${raw}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${trivia2}) _ctx._cstTriviaLog.length = ${trivia2}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${log}) _ctx._triviaLog.length = ${log}; if (_ctx._fields && _ctx._fields.length !== ${fields}) _ctx._fields.length = ${fields}; if (_ctx._errors && _ctx._errors.length !== ${errors}) _ctx._errors.length = ${errors}`;
6091
6111
  const traceId = ctx.coverage?.plan.attempts.get(p);
6092
6112
  const traceRollback = traceId === void 0 ? "" : ` _ctx._grammarTrace?.write({ id: ${JSON.stringify(traceId)}, phase: 'rollback', offset: ${pos} });`;
6093
6113
  const preGuard = [];
@@ -6150,7 +6170,7 @@ function emitSepBy(_p, def, ctx, pos) {
6150
6170
  `${ind(ctx)}const ${tl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
6151
6171
  `${ind(ctx)}const ${lg} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`
6152
6172
  ],
6153
- rb: `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${lv}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${rw}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${tl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${lg}; `
6173
+ rb: `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${lv}) _ctx._cstLeaves.length = ${lv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${rw}) _ctx._cstRawChildren.length = ${rw}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${tl}) _ctx._cstTriviaLog.length = ${tl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${lg}) _ctx._triviaLog.length = ${lg}; `
6154
6174
  };
6155
6175
  };
6156
6176
  if (rec) {
@@ -6196,7 +6216,7 @@ function emitSepBy(_p, def, ctx, pos) {
6196
6216
  `${ind(ctx)}const ${spV} = ${capFn}(input, ${curV}, _ctx, 1)`
6197
6217
  );
6198
6218
  sepAtPos = spV;
6199
- const rollbackToSep = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; `;
6219
+ const rollbackToSep = `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markV}) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${markTl}) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${markLog}) _ctx._triviaLog.length = ${markLog}; `;
6200
6220
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
6201
6221
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollbackToSep}break }`);
6202
6222
  const post = postSepMarks();
@@ -6238,7 +6258,7 @@ function emitSepBy(_p, def, ctx, pos) {
6238
6258
  }
6239
6259
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
6240
6260
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
6241
- const nextRb = markLv ? `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markRw}; ` : "";
6261
+ const nextRb = markLv ? `if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${markLv}) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${markRw}) _ctx._cstRawChildren.length = ${markRw}; ` : "";
6242
6262
  const post = postSepMarks();
6243
6263
  stmts.push(...post.decl);
6244
6264
  const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd, true);
@@ -6323,7 +6343,7 @@ function emitNot(def, ctx, pos) {
6323
6343
  ] : [],
6324
6344
  ...stmts,
6325
6345
  ...sinksLive ? [
6326
- `${ind(ctx)}if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${leaves}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${raw}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${tl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${log}; if (_ctx._fields) _ctx._fields.length = ${fields}; if (_ctx._errors) _ctx._errors.length = ${errors}`
6346
+ `${ind(ctx)}if (_ctx._cstLeaves && _ctx._cstLeaves.length !== ${leaves}) _ctx._cstLeaves.length = ${leaves}; if (_ctx._cstRawChildren && _ctx._cstRawChildren.length !== ${raw}) _ctx._cstRawChildren.length = ${raw}; if (_ctx._cstTriviaLog && _ctx._cstTriviaLog.length !== ${tl}) _ctx._cstTriviaLog.length = ${tl}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${log}) _ctx._triviaLog.length = ${log}; if (_ctx._fields && _ctx._fields.length !== ${fields}) _ctx._fields.length = ${fields}; if (_ctx._errors && _ctx._errors.length !== ${errors}) _ctx._errors.length = ${errors}`
6327
6347
  ] : [],
6328
6348
  ...emitIfFail(ctx, okVar, failBody(ctx, label2, pos))
6329
6349
  ],