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.
package/dist/index.js CHANGED
@@ -335,28 +335,28 @@ function rollbackBufList(b, keyMulti, keySingle, len) {
335
335
  else if (len === 1) {
336
336
  b[keySingle] = arr[0];
337
337
  b[keyMulti] = void 0;
338
- } else arr.length = len;
338
+ } else if (arr.length !== len) arr.length = len;
339
339
  return;
340
340
  }
341
341
  if (len === 0) b[keySingle] = void 0;
342
342
  }
343
343
  function rollbackCstCapture(ctx, mark) {
344
- if (ctx._errors && mark.errors !== void 0) ctx._errors.length = mark.errors;
344
+ if (ctx._errors && mark.errors !== void 0 && ctx._errors.length !== mark.errors) ctx._errors.length = mark.errors;
345
345
  const b = ctx._cstBuf;
346
346
  if (b) {
347
347
  rollbackBufList(b, "raw", "rawSingle", mark.raw);
348
348
  rollbackBufList(b, "ch", "single", mark.leaves);
349
349
  if (b.tl) {
350
350
  if (mark.tlog === 0) b.tl = void 0;
351
- else b.tl.length = mark.tlog;
351
+ else if (b.tl.length !== mark.tlog) b.tl.length = mark.tlog;
352
352
  }
353
- if (ctx._fields) ctx._fields.length = mark.fields;
353
+ if (ctx._fields && ctx._fields.length !== mark.fields) ctx._fields.length = mark.fields;
354
354
  return;
355
355
  }
356
- if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
357
- if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
358
- if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
359
- if (ctx._fields) ctx._fields.length = mark.fields;
356
+ if (ctx._cstRawChildren && ctx._cstRawChildren.length !== mark.raw) ctx._cstRawChildren.length = mark.raw;
357
+ if (ctx._cstTriviaLog && ctx._cstTriviaLog.length !== mark.tlog) ctx._cstTriviaLog.length = mark.tlog;
358
+ if (ctx._cstLeaves && ctx._cstLeaves.length !== mark.leaves) ctx._cstLeaves.length = mark.leaves;
359
+ if (ctx._fields && ctx._fields.length !== mark.fields) ctx._fields.length = mark.fields;
360
360
  }
361
361
  function pushCstTriviaEntry(ctx, start, end, kindIndex) {
362
362
  const insertIdx = cstRawLen(ctx);
@@ -1049,6 +1049,10 @@ var REC = { scan: recoverScan, at: matchesAt, or: orSentinel, sentinel: firstSet
1049
1049
 
1050
1050
  // src/combinators/expect.ts
1051
1051
  function deriveExpected(c) {
1052
+ return [...new Set(derive(c, /* @__PURE__ */ new Set()))];
1053
+ }
1054
+ function derive(c, seen) {
1055
+ const deriveExpected2 = (p) => derive(p, seen);
1052
1056
  const def = c._def;
1053
1057
  switch (def.tag) {
1054
1058
  case "literal":
@@ -1060,20 +1064,32 @@ function deriveExpected(c) {
1060
1064
  case "label":
1061
1065
  return [def.label];
1062
1066
  case "choice":
1063
- return def.parsers.flatMap(deriveExpected);
1064
- case "sequence":
1065
- return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
1067
+ return def.parsers.flatMap(deriveExpected2);
1068
+ // Union through the NULLABLE prefix, mirroring `sequenceFirstSet`. A leading
1069
+ // `optional(…)`/`many(…)` can match nothing, so the term after it is equally
1070
+ // able to fail first — deriving from term 0 alone named a token the parse
1071
+ // never actually required. A leading `not(…)` is zero-width and contributes
1072
+ // nothing (its own expectation is about what must NOT be here), but it is
1073
+ // nullable, so keep scanning past it. Stop at the first term that must match.
1074
+ case "sequence": {
1075
+ const out = [];
1076
+ for (const term of def.parsers) {
1077
+ if (!isZeroWidthAssertion(term)) out.push(...deriveExpected2(term));
1078
+ if (!matchesEmpty(term)) break;
1079
+ }
1080
+ return out;
1081
+ }
1066
1082
  case "attempt":
1067
- return deriveExpected(def.parser);
1083
+ return deriveExpected2(def.parser);
1068
1084
  // Delegating wrappers whose first-token failure is their inner parser's — must
1069
1085
  // pass through so a start-failure (and the first-set-miss fast-path in attempt/
1070
1086
  // node, which reads this) names the real expected token, not the wrapper tag.
1071
1087
  case "field":
1072
1088
  case "withCtx":
1073
1089
  case "recover":
1074
- return deriveExpected(def.parser);
1090
+ return deriveExpected2(def.parser);
1075
1091
  case "skip":
1076
- return deriveExpected(def.main);
1092
+ return deriveExpected2(def.main);
1077
1093
  case "expect":
1078
1094
  return def.expected;
1079
1095
  case "node":
@@ -1087,13 +1103,17 @@ function deriveExpected(c) {
1087
1103
  case "transform":
1088
1104
  case "not":
1089
1105
  case "peek":
1090
- return deriveExpected(def.parser);
1106
+ return deriveExpected2(def.parser);
1091
1107
  case "lazy": {
1092
1108
  const name = c._ruleName;
1109
+ if (seen.has(c)) return name ? [name] : [];
1110
+ seen.add(c);
1093
1111
  try {
1094
- return deriveExpected(def.thunk());
1112
+ return deriveExpected2(def.thunk());
1095
1113
  } catch {
1096
1114
  return name ? [name] : [];
1115
+ } finally {
1116
+ seen.delete(c);
1097
1117
  }
1098
1118
  }
1099
1119
  default:
@@ -1224,14 +1244,14 @@ function choice(...args) {
1224
1244
  const result = parsers[i].parse(input, pos, ctx);
1225
1245
  if (!result.ok) {
1226
1246
  rollbackCstCapture(ctx, mark);
1227
- if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
1247
+ if (logLen !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== logLen) ctx._triviaLog.length = logLen;
1228
1248
  expected.push(...result.expected);
1229
1249
  continue;
1230
1250
  }
1231
1251
  const checks = autoNot[i];
1232
1252
  if (checks && autoNotFires(input, result.span.end, checks)) {
1233
1253
  rollbackCstCapture(ctx, mark);
1234
- if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
1254
+ if (logLen !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== logLen) ctx._triviaLog.length = logLen;
1235
1255
  continue;
1236
1256
  }
1237
1257
  return result;
@@ -1558,7 +1578,7 @@ function saveTriviaMark(ctx) {
1558
1578
  }
1559
1579
  function rollbackTrivia(ctx, mark) {
1560
1580
  rollbackCstCapture(ctx, { raw: mark.raw, tlog: mark.tlog, leaves: mark.leaves, fields: mark.fields, errors: mark.errors });
1561
- if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
1581
+ if (ctx._triviaLog && ctx._triviaLog.length !== mark.log) ctx._triviaLog.length = mark.log;
1562
1582
  }
1563
1583
  function saveLookaheadMark(ctx) {
1564
1584
  return { ...saveTriviaMark(ctx), probeBest: ctx._probe ? ctx._probe.best : null };
@@ -1926,7 +1946,7 @@ function attempt(parser2) {
1926
1946
  const result = parser2.parse(input, pos, ctx);
1927
1947
  if (result.ok) return result;
1928
1948
  rollbackCstCapture(ctx, mark);
1929
- if (log !== void 0 && ctx._triviaLog) ctx._triviaLog.length = log;
1949
+ if (log !== void 0 && ctx._triviaLog && ctx._triviaLog.length !== log) ctx._triviaLog.length = log;
1930
1950
  return { ok: false, expected: result.expected, span: { start: pos, end: pos } };
1931
1951
  }
1932
1952
  };
@@ -3000,7 +3020,7 @@ function leaf(root, fn) {
3000
3020
  }
3001
3021
 
3002
3022
  // src/version.ts
3003
- var PARSEMAN_VERSION = "0.34.0";
3023
+ var PARSEMAN_VERSION = "0.36.0";
3004
3024
 
3005
3025
  // src/analysis/gating.ts
3006
3026
  var isAny = (fs) => fs.kind === "any";
@@ -5191,9 +5211,9 @@ function planDisjointDispatch(parsers) {
5191
5211
  return total >= SWITCH_MIN_CASES ? { kind: "switch", cases } : { kind: "if" };
5192
5212
  }
5193
5213
  function captureRestoreBody(mL, mR, mTl, mLg, mF = null) {
5194
- const fieldRestore = mF ? `; if (_ctx._fields) _ctx._fields.length = ${mF}` : "";
5195
- const base = `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${mL}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${mR}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${mTl}${fieldRestore}`;
5196
- return mLg ? `${base}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${mLg}` : base;
5214
+ const fieldRestore = mF ? `; if (_ctx._fields && _ctx._fields.length !== ${mF}) _ctx._fields.length = ${mF}` : "";
5215
+ 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}`;
5216
+ return mLg ? `${base}; if (_ctx._triviaLog && _ctx._triviaLog.length !== ${mLg}) _ctx._triviaLog.length = ${mLg}` : base;
5197
5217
  }
5198
5218
  function mayLeavePartialCapture(p, seen = /* @__PURE__ */ new Set()) {
5199
5219
  if (seen.has(p)) return false;
@@ -5555,7 +5575,7 @@ function emitSeqValues(def, ctx, pos) {
5555
5575
  const endAfterV = v(ctx, "_sea");
5556
5576
  stmts.push(
5557
5577
  `${ind(ctx)}const ${endAfterV} = ${r2.endVar}`,
5558
- `${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}; }`
5578
+ `${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}; }`
5559
5579
  );
5560
5580
  valueVars.push(r2.valueVar);
5561
5581
  continue;
@@ -6042,7 +6062,7 @@ function emitMany(def, ctx, pos) {
6042
6062
  `${ind(ctx)}const ${npV} = ${capFn}(input, ${curV}, _ctx, 1)`
6043
6063
  );
6044
6064
  itemPos = npV;
6045
- rollback = `if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markV}; if (_ctx._cstTriviaLog) _ctx._cstTriviaLog.length = ${markTl}; if (_ctx._triviaLog) _ctx._triviaLog.length = ${markLog}; `;
6065
+ 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}; `;
6046
6066
  } else {
6047
6067
  const trivFn = ensureTriviaFn(ctx);
6048
6068
  const npV = v(ctx, "_np");
@@ -6105,7 +6125,7 @@ function emitAttempt(p, def, ctx, pos) {
6105
6125
  const log = v(ctx, "_atg");
6106
6126
  const fields = v(ctx, "_atf");
6107
6127
  const errors = v(ctx, "_ate");
6108
- 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}`;
6128
+ 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}`;
6109
6129
  const traceId = ctx.coverage?.plan.attempts.get(p);
6110
6130
  const traceRollback = traceId === void 0 ? "" : ` _ctx._grammarTrace?.write({ id: ${JSON.stringify(traceId)}, phase: 'rollback', offset: ${pos} });`;
6111
6131
  const preGuard = [];
@@ -6168,7 +6188,7 @@ function emitSepBy(_p, def, ctx, pos) {
6168
6188
  `${ind(ctx)}const ${tl} = _ctx._cstTriviaLog ? _ctx._cstTriviaLog.length : 0`,
6169
6189
  `${ind(ctx)}const ${lg} = _ctx._triviaLog ? _ctx._triviaLog.length : 0`
6170
6190
  ],
6171
- 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}; `
6191
+ 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}; `
6172
6192
  };
6173
6193
  };
6174
6194
  if (rec) {
@@ -6214,7 +6234,7 @@ function emitSepBy(_p, def, ctx, pos) {
6214
6234
  `${ind(ctx)}const ${spV} = ${capFn}(input, ${curV}, _ctx, 1)`
6215
6235
  );
6216
6236
  sepAtPos = spV;
6217
- 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}; `;
6237
+ 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}; `;
6218
6238
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
6219
6239
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) { ${rollbackToSep}break }`);
6220
6240
  const post = postSepMarks();
@@ -6256,7 +6276,7 @@ function emitSepBy(_p, def, ctx, pos) {
6256
6276
  }
6257
6277
  const { stmts: sepStmts, okVar: sepOk, endVar: sepEnd } = emitFallible(def.separator, ctx, sepAtPos, true);
6258
6278
  stmts.push(...sepStmts, `${ind(ctx)}if (!${sepOk}) break`);
6259
- const nextRb = markLv ? `if (_ctx._cstLeaves) _ctx._cstLeaves.length = ${markLv}; if (_ctx._cstRawChildren) _ctx._cstRawChildren.length = ${markRw}; ` : "";
6279
+ 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}; ` : "";
6260
6280
  const post = postSepMarks();
6261
6281
  stmts.push(...post.decl);
6262
6282
  const { stmts: nextStmts, okVar: nextOk, valVar: nextVal, endVar: nextEnd } = emitFallible(def.parser, ctx, sepEnd, true);
@@ -6341,7 +6361,7 @@ function emitNot(def, ctx, pos) {
6341
6361
  ] : [],
6342
6362
  ...stmts,
6343
6363
  ...sinksLive ? [
6344
- `${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}`
6364
+ `${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}`
6345
6365
  ] : [],
6346
6366
  ...emitIfFail(ctx, okVar, failBody(ctx, label2, pos))
6347
6367
  ],