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.
@@ -415,28 +415,28 @@ function rollbackBufList(b, keyMulti, keySingle, len) {
415
415
  else if (len === 1) {
416
416
  b[keySingle] = arr[0];
417
417
  b[keyMulti] = void 0;
418
- } else arr.length = len;
418
+ } else if (arr.length !== len) arr.length = len;
419
419
  return;
420
420
  }
421
421
  if (len === 0) b[keySingle] = void 0;
422
422
  }
423
423
  function rollbackCstCapture(ctx, mark) {
424
- if (ctx._errors && mark.errors !== void 0) ctx._errors.length = mark.errors;
424
+ if (ctx._errors && mark.errors !== void 0 && ctx._errors.length !== mark.errors) ctx._errors.length = mark.errors;
425
425
  const b = ctx._cstBuf;
426
426
  if (b) {
427
427
  rollbackBufList(b, "raw", "rawSingle", mark.raw);
428
428
  rollbackBufList(b, "ch", "single", mark.leaves);
429
429
  if (b.tl) {
430
430
  if (mark.tlog === 0) b.tl = void 0;
431
- else b.tl.length = mark.tlog;
431
+ else if (b.tl.length !== mark.tlog) b.tl.length = mark.tlog;
432
432
  }
433
- if (ctx._fields) ctx._fields.length = mark.fields;
433
+ if (ctx._fields && ctx._fields.length !== mark.fields) ctx._fields.length = mark.fields;
434
434
  return;
435
435
  }
436
- if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
437
- if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
438
- if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
439
- if (ctx._fields) ctx._fields.length = mark.fields;
436
+ if (ctx._cstRawChildren && ctx._cstRawChildren.length !== mark.raw) ctx._cstRawChildren.length = mark.raw;
437
+ if (ctx._cstTriviaLog && ctx._cstTriviaLog.length !== mark.tlog) ctx._cstTriviaLog.length = mark.tlog;
438
+ if (ctx._cstLeaves && ctx._cstLeaves.length !== mark.leaves) ctx._cstLeaves.length = mark.leaves;
439
+ if (ctx._fields && ctx._fields.length !== mark.fields) ctx._fields.length = mark.fields;
440
440
  }
441
441
  function pushCstTriviaEntry(ctx, start, end, kindIndex) {
442
442
  const insertIdx = cstRawLen(ctx);
@@ -1125,6 +1125,10 @@ function captureError(ctx, error) {
1125
1125
 
1126
1126
  // src/combinators/expect.ts
1127
1127
  function deriveExpected(c) {
1128
+ return [...new Set(derive(c, /* @__PURE__ */ new Set()))];
1129
+ }
1130
+ function derive(c, seen) {
1131
+ const deriveExpected2 = (p) => derive(p, seen);
1128
1132
  const def = c._def;
1129
1133
  switch (def.tag) {
1130
1134
  case "literal":
@@ -1136,20 +1140,32 @@ function deriveExpected(c) {
1136
1140
  case "label":
1137
1141
  return [def.label];
1138
1142
  case "choice":
1139
- return def.parsers.flatMap(deriveExpected);
1140
- case "sequence":
1141
- return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
1143
+ return def.parsers.flatMap(deriveExpected2);
1144
+ // Union through the NULLABLE prefix, mirroring `sequenceFirstSet`. A leading
1145
+ // `optional(…)`/`many(…)` can match nothing, so the term after it is equally
1146
+ // able to fail first — deriving from term 0 alone named a token the parse
1147
+ // never actually required. A leading `not(…)` is zero-width and contributes
1148
+ // nothing (its own expectation is about what must NOT be here), but it is
1149
+ // nullable, so keep scanning past it. Stop at the first term that must match.
1150
+ case "sequence": {
1151
+ const out = [];
1152
+ for (const term of def.parsers) {
1153
+ if (!isZeroWidthAssertion(term)) out.push(...deriveExpected2(term));
1154
+ if (!matchesEmpty(term)) break;
1155
+ }
1156
+ return out;
1157
+ }
1142
1158
  case "attempt":
1143
- return deriveExpected(def.parser);
1159
+ return deriveExpected2(def.parser);
1144
1160
  // Delegating wrappers whose first-token failure is their inner parser's — must
1145
1161
  // pass through so a start-failure (and the first-set-miss fast-path in attempt/
1146
1162
  // node, which reads this) names the real expected token, not the wrapper tag.
1147
1163
  case "field":
1148
1164
  case "withCtx":
1149
1165
  case "recover":
1150
- return deriveExpected(def.parser);
1166
+ return deriveExpected2(def.parser);
1151
1167
  case "skip":
1152
- return deriveExpected(def.main);
1168
+ return deriveExpected2(def.main);
1153
1169
  case "expect":
1154
1170
  return def.expected;
1155
1171
  case "node":
@@ -1163,13 +1179,17 @@ function deriveExpected(c) {
1163
1179
  case "transform":
1164
1180
  case "not":
1165
1181
  case "peek":
1166
- return deriveExpected(def.parser);
1182
+ return deriveExpected2(def.parser);
1167
1183
  case "lazy": {
1168
1184
  const name = c._ruleName;
1185
+ if (seen.has(c)) return name ? [name] : [];
1186
+ seen.add(c);
1169
1187
  try {
1170
- return deriveExpected(def.thunk());
1188
+ return deriveExpected2(def.thunk());
1171
1189
  } catch {
1172
1190
  return name ? [name] : [];
1191
+ } finally {
1192
+ seen.delete(c);
1173
1193
  }
1174
1194
  }
1175
1195
  default:
@@ -1297,14 +1317,14 @@ function choice(...args) {
1297
1317
  const result = parsers[i].parse(input, pos, ctx);
1298
1318
  if (!result.ok) {
1299
1319
  rollbackCstCapture(ctx, mark);
1300
- if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
1320
+ if (logLen !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== logLen) ctx._triviaLog.length = logLen;
1301
1321
  expected.push(...result.expected);
1302
1322
  continue;
1303
1323
  }
1304
1324
  const checks = autoNot[i];
1305
1325
  if (checks && autoNotFires(input, result.span.end, checks)) {
1306
1326
  rollbackCstCapture(ctx, mark);
1307
- if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
1327
+ if (logLen !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== logLen) ctx._triviaLog.length = logLen;
1308
1328
  continue;
1309
1329
  }
1310
1330
  return result;
@@ -1631,7 +1651,7 @@ function saveTriviaMark(ctx) {
1631
1651
  }
1632
1652
  function rollbackTrivia(ctx, mark) {
1633
1653
  rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields, errors: mark.errors });
1634
- if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
1654
+ if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
1635
1655
  }
1636
1656
  function saveLookaheadMark(ctx) {
1637
1657
  return { ...saveTriviaMark(ctx), probeBest: ctx._probe ? ctx._probe.best : null };
@@ -1999,7 +2019,7 @@ function attempt(parser2) {
1999
2019
  const result = parser2.parse(input, pos, ctx);
2000
2020
  if (result.ok) return result;
2001
2021
  rollbackCstCapture(ctx, mark);
2002
- if (log !== void 0 && ctx._triviaLog) ctx._triviaLog.length = log;
2022
+ if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
2003
2023
  return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
2004
2024
  }
2005
2025
  };
@@ -3009,7 +3029,7 @@ function leaf(root, fn) {
3009
3029
  }
3010
3030
 
3011
3031
  // src/version.ts
3012
- var PARSEMAN_VERSION = "0.34.0";
3032
+ var PARSEMAN_VERSION = "0.36.0";
3013
3033
 
3014
3034
  // src/analysis/gating.ts
3015
3035
  var isAny = (fs2) => fs2.kind === "any";
@@ -5208,9 +5228,9 @@ function planDisjointDispatch(parsers) {
5208
5228
  return total >= SWITCH_MIN_CASES ? { kind: "switch", cases } : { kind: "if" };
5209
5229
  }
5210
5230
  function captureRestoreBody(mL, mR, mTl, mLg, mF = null) {
5211
- const fieldRestore = mF ? `; if (_ctx._fields) _ctx._fields.length = ${mF}` : "";
5212
- const base = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}${fieldRestore}`;
5213
- return mLg ? `${base}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mLg}` : base;
5231
+ const fieldRestore = mF ? `; if (_ctx._fields && _ctx._fields.length !== ${mF}) _ctx._fields.length = ${mF}` : "";
5232
+ 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}`;
5233
+ return mLg ? `${base}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${mLg}) _ctx._triviaLog.length = ${mLg}` : base;
5214
5234
  }
5215
5235
  function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
5216
5236
  if (seen.has(p)) return false;
@@ -5572,7 +5592,7 @@ function emitSeqValues(def, ctx, pos) {
5572
5592
  const endAfterV = v(ctx, "_sea");
5573
5593
  stmts.push(
5574
5594
  `${ind(ctx)}const ${endAfterV} = ${r2.endVar}`,
5575
- `${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}; }`
5595
+ `${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}; }`
5576
5596
  );
5577
5597
  valueVars.push(r2.valueVar);
5578
5598
  continue;
@@ -6059,7 +6079,7 @@ function emitMany(def, ctx, pos) {
6059
6079
  `${ind(ctx)}const ${npV} = ${capFn}(input, ${curV}, _ctx, 1)`
6060
6080
  );
6061
6081
  itemPos = npV;
6062
- rollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; `;
6082
+ 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}; `;
6063
6083
  } else {
6064
6084
  const trivFn = ensureTriviaFn(ctx);
6065
6085
  const npV = v(ctx, "_np");
@@ -6122,7 +6142,7 @@ function emitAttempt(p, def, ctx, pos) {
6122
6142
  const log = v(ctx, "_atg");
6123
6143
  const fields = v(ctx, "_atf");
6124
6144
  const errors = v(ctx, "_ate");
6125
- 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}`;
6145
+ 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}`;
6126
6146
  const traceId = ctx.coverage?.plan.attempts.get(p);
6127
6147
  const traceRollback = traceId === void 0 ? "" : ` _ctx._grammarTrace?.write({ id: ${JSON.stringify(traceId)}, phase: 'rollback', offset: ${pos} });`;
6128
6148
  const preGuard = [];
@@ -6185,7 +6205,7 @@ function emitSepBy(_p, def, ctx, pos) {
6185
6205
  `${ind(ctx)}const ${tl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
6186
6206
  `${ind(ctx)}const ${lg} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`
6187
6207
  ],
6188
- 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}; `
6208
+ 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}; `
6189
6209
  };
6190
6210
  };
6191
6211
  if (rec) {
@@ -6231,7 +6251,7 @@ function emitSepBy(_p, def, ctx, pos) {
6231
6251
  `${ind(ctx)}const ${spV} = ${capFn}(input, ${curV}, _ctx, 1)`
6232
6252
  );
6233
6253
  sepAtPos = spV;
6234
- 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}; `;
6254
+ 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}; `;
6235
6255
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
6236
6256
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollbackToSep}break }`);
6237
6257
  const post = postSepMarks();
@@ -6273,7 +6293,7 @@ function emitSepBy(_p, def, ctx, pos) {
6273
6293
  }
6274
6294
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
6275
6295
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
6276
- const nextRb = markLv ? `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markRw}; ` : "";
6296
+ 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}; ` : "";
6277
6297
  const post = postSepMarks();
6278
6298
  stmts.push(...post.decl);
6279
6299
  const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd, true);
@@ -6358,7 +6378,7 @@ function emitNot(def, ctx, pos) {
6358
6378
  ] : [],
6359
6379
  ...stmts,
6360
6380
  ...sinksLive ? [
6361
- `${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}`
6381
+ `${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}`
6362
6382
  ] : [],
6363
6383
  ...emitIfFail(ctx, okVar, failBody(ctx, label2, pos))
6364
6384
  ],