parseman 0.39.1 → 0.40.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.
@@ -2986,12 +2986,30 @@ function isCstChild(value) {
2986
2986
  function missingInferredType() {
2987
2987
  throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
2988
2988
  }
2989
+ function normalizeProject(project) {
2990
+ if (project === void 0) return void 0;
2991
+ if (!Number.isInteger(project) || project < 0) {
2992
+ throw new Error("node() project child must be a non-negative integer");
2993
+ }
2994
+ return project;
2995
+ }
2996
+ function projectChild(children2, project, type) {
2997
+ if (!(project in children2)) {
2998
+ throw new Error(`node(${JSON.stringify(type)}) project child ${project} was not captured`);
2999
+ }
3000
+ return unwrapChild(children2[project]);
3001
+ }
2989
3002
  function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
2990
3003
  const hasExplicitType = typeof typeOrCombinator === "string";
2991
3004
  const type = hasExplicitType ? typeOrCombinator : void 0;
2992
3005
  const combinator = hasExplicitType ? combinatorOrBuild : typeOrCombinator;
2993
- const build = hasExplicitType ? buildOrOpts : combinatorOrBuild;
2994
- const opts = hasExplicitType ? maybeOpts : buildOrOpts;
3006
+ const buildArg = hasExplicitType ? buildOrOpts : combinatorOrBuild;
3007
+ const build = typeof buildArg === "function" ? buildArg : void 0;
3008
+ const opts = typeof buildArg === "function" ? maybeOpts : buildArg ?? maybeOpts;
3009
+ const project = normalizeProject(opts?.project);
3010
+ if (project !== void 0 && build !== void 0) {
3011
+ throw new Error("node() options cannot combine project with a build callback");
3012
+ }
2995
3013
  const baseDef = { tag: "node", parser: combinator, ...type === void 0 ? {} : { type }, ...build === void 0 ? {} : { build } };
2996
3014
  const meta = {
2997
3015
  firstSet: combinator._meta.firstSet,
@@ -3005,11 +3023,14 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
3005
3023
  if (unwrap && collapse) {
3006
3024
  throw new Error("node() options cannot set both unwrap and collapse");
3007
3025
  }
3008
- const def = unwrap || collapse || captureTrivia || trailingTrivia ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {} } : baseDef;
3009
- const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : true);
3010
- const clonesState = build ? buildReadsState(def) : true;
3026
+ if (project !== void 0 && (unwrap || collapse)) {
3027
+ throw new Error("node() options cannot combine project with unwrap or collapse");
3028
+ }
3029
+ const def = unwrap || collapse || project !== void 0 || captureTrivia || trailingTrivia ? { ...baseDef, ...unwrap ? { unwrap: true } : {}, ...collapse ? { collapse: true } : {}, ...project !== void 0 ? { project } : {}, ...captureTrivia ? { captureTrivia: true } : {}, ...trailingTrivia ? { trailingTrivia: true } : {} } : baseDef;
3030
+ const capturesTrivia = captureTrivia || trailingTrivia || (build ? buildReadsTrivia(def) : project === void 0);
3031
+ const clonesState = build ? buildReadsState(def) : project === void 0;
3011
3032
  const hasOwnFields = parserHasOwnFields(combinator);
3012
- const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : true);
3033
+ const capturesFields = hasOwnFields && (build ? buildReadsFields(def) : project === void 0);
3013
3034
  const guardable = combinator._meta.firstSet.kind !== "any" && !matchesEmpty(combinator);
3014
3035
  let failExpected;
3015
3036
  return {
@@ -3024,14 +3045,15 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
3024
3045
  }
3025
3046
  return { ok: false, expected: failExpected, span: { start: pos, end: pos } };
3026
3047
  }
3027
- const hostCst = build !== void 0 && cstOutputHost(ctx.build);
3048
+ const hasDirectValue = build !== void 0 || project !== void 0;
3049
+ const hostCst = hasDirectValue && cstOutputHost(ctx.build);
3028
3050
  const effTrivia = capturesTrivia || hostCst;
3029
3051
  const effFields = capturesFields || hostCst && hasOwnFields;
3030
3052
  const saved = beginCstNodeCapture(ctx);
3031
3053
  const savedFields = ctx._fields;
3032
3054
  ctx._fields = effFields ? [] : void 0;
3033
3055
  const savedMask = ctx._triviaCaptureMask;
3034
- if (build === void 0 && ctx.build?._parsemanTriviaKinds !== void 0 && def.type !== void 0) {
3056
+ if (build === void 0 && project === void 0 && ctx.build?._parsemanTriviaKinds !== void 0 && def.type !== void 0) {
3035
3057
  ctx._triviaCaptureMask = ctx.build._parsemanTriviaKinds(def.type);
3036
3058
  }
3037
3059
  if (!effTrivia) ctx.captureTrivia = false;
@@ -3049,7 +3071,7 @@ function node(typeOrCombinator, combinatorOrBuild, buildOrOpts, maybeOpts) {
3049
3071
  const nodeType = def.type ?? missingInferredType();
3050
3072
  const cstOutput = cstOutputHost(ctx.build);
3051
3073
  const hostState = clonesState ? st : ctx.state !== void 0 ? Object.assign({}, ctx.state) : void 0;
3052
- const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : !build && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, hostState) : build(children2, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
3074
+ const built = unwrap && children2.length === 1 ? unwrapChild(children2[0]) : collapse && children2.length === 1 ? children2[0] : !build && project === void 0 && ctx.build?._parsemanCstCollapse && children2.length === 1 && rawChildren.length === 1 && ctx.build._parsemanCstCollapse(nodeType, children2[0], children2, rawChildren) ? children2[0] : project !== void 0 ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, hostState) : projectChild(children2, project, nodeType) : build ? cstOutput && ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, hostState) : build(children2, fields, r.span, rawChildren, triviaLog, st) : ctx.build ? ctx.build(nodeType, children2, fields, r.span, rawChildren, triviaLog, st) : { _tag: "node", type: nodeType, span: { start: r.span.start, end: r.span.end }, state: st ?? null, children: children2 };
3053
3075
  const rawEntry = isCstChild(built) ? built : { _tag: "leaf", value: typeof built === "string" ? built : typeof built === "object" && built !== null ? input.slice(r.span.start, r.span.end) : "", span: r.span };
3054
3076
  if (saved.buf !== void 0 || saved.ch !== void 0) {
3055
3077
  pushCstChild(ctx, built, rawEntry);
@@ -3300,7 +3322,7 @@ function leaf(root, fn) {
3300
3322
  }
3301
3323
 
3302
3324
  // src/version.ts
3303
- var PARSEMAN_VERSION = "0.39.1";
3325
+ var PARSEMAN_VERSION = "0.40.0";
3304
3326
 
3305
3327
  // src/cst/host-mode.ts
3306
3328
  var FUSED_HOST_MODE = /* @__PURE__ */ Symbol.for("parseman.fusedHostMode");
@@ -8471,14 +8493,20 @@ function emitLeaf(def, ctx, pos) {
8471
8493
  endVar: inner.endVar
8472
8494
  };
8473
8495
  }
8496
+ function emitNodeProjectExpr(type, project, chV) {
8497
+ const child = `${chV}[${project}]`;
8498
+ const missing = `(() => { throw new Error(${JSON.stringify(`node(${JSON.stringify(type)}) project child ${project} was not captured`)}) })()`;
8499
+ const value = `(${child} !== null && typeof ${child} === 'object' && ${child}._tag === 'leaf' ? ${child}.value : ${child})`;
8500
+ return `(${project} in ${chV} ? ${value} : ${missing})`;
8501
+ }
8474
8502
  function emitNode(def, ctx, pos) {
8475
8503
  if (def.type === void 0) {
8476
8504
  throw new Error('node(): inferred node type requires a rules() key; pass node("Type", parser) outside rules()');
8477
8505
  }
8478
- const structural = def.build === void 0;
8479
- const mkType = structural ? null : analyzeMkInlineBuild(def);
8506
+ const structural = def.build === void 0 && def.project === void 0;
8507
+ const mkType = structural || def.project !== void 0 ? null : analyzeMkInlineBuild(def);
8480
8508
  let buildIdx = null;
8481
- if (!mkType && !structural) {
8509
+ if (!mkType && !structural && def.project === void 0) {
8482
8510
  buildIdx = ctx.buildFns.length;
8483
8511
  ctx.buildFns.push(def.build);
8484
8512
  ctx.buildSrcs.push(def.buildSrc ?? null);
@@ -8486,12 +8514,13 @@ function emitNode(def, ctx, pos) {
8486
8514
  const i = ind(ctx);
8487
8515
  const cstOut = ctx.hostMode === "cst" && !structural;
8488
8516
  if (!structural && !cstOut) ctx.hostBranchElided = true;
8489
- const capturesTrivia = cstOut || mkType !== null || def.captureTrivia === true || def.trailingTrivia === true || !structural && buildReadsTrivia(def);
8490
- const clonesState = !structural && (cstOut || buildReadsState(def));
8491
- const capturesChildren = !structural && (cstOut || mkType !== null || def.unwrap || def.collapse || buildReadsChildren(def));
8492
- const capturesRaw = !structural && (cstOut || mkType !== null || buildReadsRaw(def));
8517
+ const hasProject = def.project !== void 0;
8518
+ const capturesTrivia = cstOut || mkType !== null || def.captureTrivia === true || def.trailingTrivia === true || !structural && !hasProject && buildReadsTrivia(def);
8519
+ const clonesState = !structural && (cstOut || !hasProject && buildReadsState(def));
8520
+ const capturesChildren = !structural && (cstOut || mkType !== null || def.unwrap || def.collapse || def.project !== void 0 || buildReadsChildren(def));
8521
+ const capturesRaw = !structural && (cstOut || mkType !== null || def.project === void 0 && buildReadsRaw(def));
8493
8522
  const hasFields = parserHasOwnFields(def.parser);
8494
- const capturesFields = hasFields && !structural && (cstOut || buildReadsFields(def));
8523
+ const capturesFields = hasFields && !structural && (cstOut || !hasProject && buildReadsFields(def));
8495
8524
  const innerEnablesTriviaCapture = parserEnablesTriviaCapture(def.parser);
8496
8525
  const chV = v(ctx, "_ch");
8497
8526
  const rawV = v(ctx, "_raw");
@@ -8589,7 +8618,7 @@ ${i}const ${chV} = ${chAlloc}, ${rawV} = ${profileRecognizer} ? undefined : [],
8589
8618
  );
8590
8619
  }
8591
8620
  const ndV = v(ctx, "_nd");
8592
- const buildExpr = structural ? `{ _tag: 'node', type: ${JSON.stringify(def.type)}, span: { start: ${pos}, end: ${endVar} }, state: ${stV} ?? null, children: ${chV} }` : mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : `${buildRef(ctx)}[${buildIdx}](${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
8621
+ const buildExpr = structural ? `{ _tag: 'node', type: ${JSON.stringify(def.type)}, span: { start: ${pos}, end: ${endVar} }, state: ${stV} ?? null, children: ${chV} }` : mkType ? emitInlineMkNodeExpr(mkType, chV, rawV, pos, endVar, tlV) : def.project !== void 0 ? emitNodeProjectExpr(def.type, def.project, chV) : `${buildRef(ctx)}[${buildIdx}](${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
8593
8622
  const hostBuildExpr = `_ctx._pmProfile?.phase === 'host' && _ctx._pmProfile.hostCalls++, _ctx.build(${JSON.stringify(def.type)}, ${chV}, ${fObj}, { start: ${pos}, end: ${endVar} }, ${rawV}, ${tlV}, ${stV})`;
8594
8623
  const ndExpr = structural ? `_ctx.build !== undefined ? (${hostBuildExpr}) : (${buildExpr})` : cstOut ? hostBuildExpr : buildExpr;
8595
8624
  const hostCollapseExpr = structural ? `_ctx.build !== undefined && _ctx.build._parsemanCstCollapse !== undefined && ${chV}.length === 1 && ${rawV}.length === 1 && _ctx.build._parsemanCstCollapse(${JSON.stringify(def.type)}, ${chV}[0], ${chV}, ${rawV}) ? ${chV}[0] : (${ndExpr})` : ndExpr;
@@ -10000,6 +10029,10 @@ function repeatOpts(min, max, trailing) {
10000
10029
  if (trailing !== void 0) parts.push(`trailing: ${JSON.stringify(trailing)}`);
10001
10030
  return parts.length === 0 ? "" : `, { ${parts.join(", ")} }`;
10002
10031
  }
10032
+ function projectOpt(project) {
10033
+ if (project === void 0) return void 0;
10034
+ return `project: ${project}`;
10035
+ }
10003
10036
  function matcherExpr(entry) {
10004
10037
  switch (entry.kind) {
10005
10038
  case "startsWith":
@@ -10393,9 +10426,11 @@ ${outerDecls.map((d) => " " + d).join("\n")}
10393
10426
  }
10394
10427
  case "node": {
10395
10428
  if (def.build !== void 0 && def.buildSrc === void 0) throw new Unserializable("node build without buildSrc");
10429
+ const projectEntry = projectOpt(def.project);
10396
10430
  const optEntries = [
10397
10431
  ...def.unwrap ? ["unwrap: true"] : [],
10398
10432
  ...def.collapse ? ["collapse: true"] : [],
10433
+ ...projectEntry === void 0 ? [] : [projectEntry],
10399
10434
  ...def.captureTrivia ? ["captureTrivia: true"] : [],
10400
10435
  ...def.trailingTrivia ? ["trailingTrivia: true"] : []
10401
10436
  ];
@@ -11000,6 +11035,18 @@ function scopeGet(scope, name, mfs) {
11000
11035
  if (isCombinator(entry)) return entry;
11001
11036
  return null;
11002
11037
  }
11038
+ function staticLiteralValue(expr) {
11039
+ const val = expr;
11040
+ return val.type === "Literal" || val.type === "BooleanLiteral" || val.type === "NumericLiteral" ? val.value : void 0;
11041
+ }
11042
+ function staticNodeProject(expr) {
11043
+ const literalValue = staticLiteralValue(expr);
11044
+ if (typeof literalValue === "number" && Number.isInteger(literalValue) && literalValue >= 0) {
11045
+ return { ok: true, value: literalValue };
11046
+ }
11047
+ if (typeof literalValue === "number" || literalValue !== void 0) return { ok: false };
11048
+ return { ok: false };
11049
+ }
11003
11050
  function staticNodeOptions(expr) {
11004
11051
  if (expr.type !== "ObjectExpression") return void 0;
11005
11052
  const opts = {};
@@ -11009,11 +11056,14 @@ function staticNodeOptions(expr) {
11009
11056
  const key = p.key;
11010
11057
  const name = key.type === "Identifier" ? key.name : key.type === "Literal" ? String(key.value) : void 0;
11011
11058
  if (name === "unwrap" || name === "collapse" || name === "captureTrivia" || name === "trailingTrivia") {
11012
- const val = p.value;
11013
- if ((val.type === "Literal" || val.type === "BooleanLiteral") && val.value === true) opts[name] = true;
11059
+ if (staticLiteralValue(p.value) === true) opts[name] = true;
11060
+ } else if (name === "project") {
11061
+ const project = staticNodeProject(p.value);
11062
+ if (project?.ok === false) return { project: -1 };
11063
+ if (project !== void 0) opts.project = project.value;
11014
11064
  }
11015
11065
  }
11016
- return opts.unwrap || opts.collapse || opts.captureTrivia || opts.trailingTrivia ? opts : void 0;
11066
+ return opts.unwrap || opts.collapse || opts.project !== void 0 || opts.captureTrivia || opts.trailingTrivia ? opts : void 0;
11017
11067
  }
11018
11068
  function exprToCombi(node2, scope, code, mfs) {
11019
11069
  if (node2.type === "Identifier") return scopeGet(scope, node2.name, mfs);
@@ -11088,9 +11138,10 @@ function exprToCombi(node2, scope, code, mfs) {
11088
11138
  const inner = anyValue(parserArg, scope, code, mfs);
11089
11139
  if (!isCombinator(inner)) return null;
11090
11140
  const be = buildArg;
11091
- const hasBuild = be !== void 0 && be.type !== "SpreadElement" && !(be.type === "Identifier" && be.name === "undefined");
11141
+ const hasBuild = be !== void 0 && be.type !== "SpreadElement" && be.type !== "ObjectExpression" && !(be.type === "Identifier" && be.name === "undefined");
11092
11142
  const buildSrc = hasBuild ? stripTsFromSource(be, code) : void 0;
11093
- const opts = optsArg !== void 0 && optsArg.type !== "SpreadElement" ? staticNodeOptions(optsArg) : void 0;
11143
+ const optionsArg = hasBuild ? optsArg : be?.type === "ObjectExpression" ? buildArg : optsArg;
11144
+ const opts = optionsArg !== void 0 && optionsArg.type !== "SpreadElement" ? staticNodeOptions(optionsArg) : void 0;
11094
11145
  try {
11095
11146
  const combi = explicitType !== void 0 ? node(explicitType, inner, hasBuild ? () => null : void 0, opts) : node(inner, hasBuild ? () => null : void 0, opts);
11096
11147
  if (combi._def.tag === "node" && buildSrc !== void 0) {