@optique/core 1.1.3 → 1.1.5

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.
@@ -6,7 +6,7 @@ import { deduplicateDocFragments } from "./doc.js";
6
6
  import { dispatchByMode, dispatchIterableByMode } from "./internal/mode-dispatch.js";
7
7
  import { createDependencySourceState, dependencyId, isDependencySourceState, isPendingDependencySourceState, isWrappedDependencySource, wrappedDependencySourceMarker } from "./internal/dependency.js";
8
8
  import { buildRuntimeNodesFromArray, buildRuntimeNodesFromPairs, collectExplicitSourceValues, collectExplicitSourceValuesAsync, collectSourcesFromState, createDependencyRuntimeContext, fillMissingSourceDefaults, fillMissingSourceDefaultsAsync, resolveStateWithRuntime, resolveStateWithRuntimeAsync } from "./dependency-runtime.js";
9
- import { defineInheritedAnnotationParser, getParserSuggestRuntimeNodes, unmatchedNonCliDependencySourceStateMarker } from "./internal/parser.js";
9
+ import { defineInheritedAnnotationParser, defineParseLanes, getOwnParseLanes, getParserSuggestRuntimeNodes, unmatchedNonCliDependencySourceStateMarker } from "./internal/parser.js";
10
10
  import { annotationViewTargets, getWrappedChildParseState, getWrappedChildState, reconcileObjectChildState, unwrapAnnotationView } from "./annotation-state.js";
11
11
  import { allowDuplicateLeadingCommandNamesKey } from "./internal/command-alias.js";
12
12
  import { mergeChildExec, withChildContext, withChildExecPath } from "./execution-context.js";
@@ -78,8 +78,8 @@ function unionLeadingNames(parsers) {
78
78
  * Computes `leadingNames` for shared-buffer compositions (`tuple()`,
79
79
  * `object()`, `merge()`, `concat()`).
80
80
  *
81
- * Children are processed in descending priority order (matching the
82
- * round-robin parse loop). Once a child with `acceptingAnyToken` is
81
+ * Sources are processed in descending priority order (matching the
82
+ * round-robin parse loop). Once a source with `acceptingAnyToken` is
83
83
  * encountered, no lower-priority children can match at position 0, so
84
84
  * their names are excluded.
85
85
  */
@@ -1528,6 +1528,33 @@ function createLongestMatch(...args) {
1528
1528
  return multiResult;
1529
1529
  }
1530
1530
  /**
1531
+ * Creates the initial parse error shared by object-like combinators.
1532
+ * @param context The current parser context.
1533
+ * @param noMatchContext The kinds of input accepted by the combinator.
1534
+ * @param errors Optional custom error formatters.
1535
+ * @returns A zero-consumption parse error.
1536
+ */
1537
+ function createObjectLikeInitialError(context, noMatchContext, errors) {
1538
+ if (context.buffer.length < 1) {
1539
+ const customEndOfInput = errors?.endOfInput;
1540
+ return {
1541
+ consumed: 0,
1542
+ error: customEndOfInput ? typeof customEndOfInput === "function" ? customEndOfInput(noMatchContext) : customEndOfInput : generateNoMatchError(noMatchContext)
1543
+ };
1544
+ }
1545
+ const token = context.buffer[0];
1546
+ const customMessage = errors?.unexpectedInput;
1547
+ if (customMessage) return {
1548
+ consumed: 0,
1549
+ error: typeof customMessage === "function" ? customMessage(token) : customMessage
1550
+ };
1551
+ const baseError = message`Unexpected option or argument: ${token}.`;
1552
+ return {
1553
+ consumed: 0,
1554
+ error: createErrorWithSuggestions(baseError, token, context.usage, "both", errors?.suggestions)
1555
+ };
1556
+ }
1557
+ /**
1531
1558
  * Internal sync helper for object suggest functionality.
1532
1559
  * @internal
1533
1560
  */
@@ -1920,19 +1947,53 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1920
1947
  checkDuplicateReachableLeadingCommandNames(parserPairs.map(([field, parser]) => [field, parser]));
1921
1948
  const noMatchContext = analyzeNoMatchContext(parserKeys.map((k) => parsers[k]));
1922
1949
  const combinedMode = parserKeys.some((k) => parsers[k].mode === "async") ? "async" : "sync";
1923
- const getInitialError = (context) => ({
1924
- consumed: 0,
1925
- error: context.buffer.length > 0 ? (() => {
1926
- const token = context.buffer[0];
1927
- const customMessage = options.errors?.unexpectedInput;
1928
- if (customMessage) return typeof customMessage === "function" ? customMessage(token) : customMessage;
1929
- const baseError = message`Unexpected option or argument: ${token}.`;
1930
- return createErrorWithSuggestions(baseError, token, context.usage, "both", options.errors?.suggestions);
1931
- })() : (() => {
1932
- const customEndOfInput = options.errors?.endOfInput;
1933
- return customEndOfInput ? typeof customEndOfInput === "function" ? customEndOfInput(noMatchContext) : customEndOfInput : generateNoMatchError(noMatchContext);
1934
- })()
1935
- });
1950
+ const getInitialError = (context) => createObjectLikeInitialError(context, noMatchContext, options.errors);
1951
+ const adaptFieldLaneResult = (context, field, parser, fieldState, result) => {
1952
+ if (!result.success) return result;
1953
+ if (result.consumed.length === 0 && result.next.state === fieldState) return {
1954
+ success: true,
1955
+ next: context,
1956
+ consumed: []
1957
+ };
1958
+ const mergedExec = mergeChildExec(context.exec, result.next.exec);
1959
+ const nextState = result.next.state === fieldState ? context.state : {
1960
+ ...context.state,
1961
+ [field]: getWrappedChildState(context.state, result.next.state, parser)
1962
+ };
1963
+ return {
1964
+ success: true,
1965
+ next: {
1966
+ ...context,
1967
+ buffer: result.next.buffer,
1968
+ optionsTerminated: result.next.optionsTerminated,
1969
+ state: nextState,
1970
+ ...mergedExec != null ? {
1971
+ trace: mergedExec.trace,
1972
+ exec: mergedExec,
1973
+ dependencyRegistry: mergedExec.dependencyRegistry
1974
+ } : {}
1975
+ },
1976
+ consumed: result.consumed
1977
+ };
1978
+ };
1979
+ const objectZeroConsumptionGroup = {};
1980
+ const objectParseLanes = parserPairs.map(([field, parser]) => ({
1981
+ priority: parser.priority,
1982
+ zeroConsumptionGroup: objectZeroConsumptionGroup,
1983
+ settlesZeroConsumption: false,
1984
+ leadingNames: parser.leadingNames,
1985
+ acceptingAnyToken: parser.acceptingAnyToken,
1986
+ parse(context) {
1987
+ const fieldState = createFieldStateGetter(context.state, getObjectParseChildState)(field, parser);
1988
+ return dispatchByMode(combinedMode, () => {
1989
+ const result = parser.parse(withChildContext$1(context, field, fieldState, parser));
1990
+ return adaptFieldLaneResult(context, field, parser, fieldState, result);
1991
+ }, async () => {
1992
+ const result = await parser.parse(withChildContext$1(context, field, fieldState, parser));
1993
+ return adaptFieldLaneResult(context, field, parser, fieldState, result);
1994
+ });
1995
+ }
1996
+ }));
1936
1997
  const parseSync = (context) => {
1937
1998
  let error = getInitialError(context);
1938
1999
  let currentContext = context;
@@ -2451,6 +2512,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2451
2512
  configurable: true,
2452
2513
  enumerable: false
2453
2514
  });
2515
+ defineParseLanes(objectParser, objectParseLanes);
2454
2516
  defineInheritedAnnotationParser(objectParser);
2455
2517
  return objectParser;
2456
2518
  }
@@ -3802,6 +3864,7 @@ function merge(...args) {
3802
3864
  const syncParsers = syncSorted.map(([p]) => p);
3803
3865
  if (!options.allowDuplicates) checkDuplicateOptionNames(sorted.map(([parser, originalIndex]) => [String(originalIndex), parser.usage]));
3804
3866
  checkDuplicateReachableLeadingCommandNames(sorted.map(([parser, originalIndex]) => [String(originalIndex), parser]));
3867
+ const noMatchContext = analyzeNoMatchContext(rawParsers);
3805
3868
  const mergedFieldParsers = collectChildFieldParsers(parsers);
3806
3869
  const duplicateOutputFieldNames = collectDuplicateFieldNames(mergedFieldParsers);
3807
3870
  const parserStateKey = (index) => `__parser_${index}`;
@@ -3854,7 +3917,140 @@ function merge(...args) {
3854
3917
  [localObjectStateKey(index)]: result.next.state
3855
3918
  };
3856
3919
  };
3857
- const parseSync = (context) => {
3920
+ const adaptMergeLaneResult = (parser, context, parserState, parsedState, result, index) => {
3921
+ if (!result.success) return result;
3922
+ const mergedExec = mergeChildExec(context.exec, result.next.exec);
3923
+ const newState = result.next.state === parsedState ? context.state : mergeResultState(parser, context, parserState, result, index);
3924
+ return {
3925
+ success: true,
3926
+ next: {
3927
+ ...context,
3928
+ buffer: result.next.buffer,
3929
+ optionsTerminated: result.next.optionsTerminated,
3930
+ state: newState,
3931
+ ...mergedExec != null ? {
3932
+ trace: mergedExec.trace,
3933
+ exec: mergedExec,
3934
+ dependencyRegistry: mergedExec.dependencyRegistry
3935
+ } : {}
3936
+ },
3937
+ consumed: result.consumed
3938
+ };
3939
+ };
3940
+ const childrenInDeclarationOrder = sorted.map(([parser, originalIndex], sortedIndex) => ({
3941
+ parser,
3942
+ originalIndex,
3943
+ sortedIndex
3944
+ })).toSorted((a, b) => a.originalIndex - b.originalIndex);
3945
+ const mergeParseLanes = childrenInDeclarationOrder.flatMap(({ parser, sortedIndex }) => {
3946
+ const occurrenceConsumptionGroups = /* @__PURE__ */ new WeakMap();
3947
+ const occurrenceZeroConsumptionGroups = /* @__PURE__ */ new WeakMap();
3948
+ const scopeConsumptionGroup = (group$1) => {
3949
+ const existing = occurrenceConsumptionGroups.get(group$1);
3950
+ if (existing != null) return existing;
3951
+ const scoped = {};
3952
+ occurrenceConsumptionGroups.set(group$1, scoped);
3953
+ return scoped;
3954
+ };
3955
+ const childLanes = getOwnParseLanes(parser);
3956
+ const lanes = childLanes ?? [{
3957
+ priority: parser.priority,
3958
+ leadingNames: parser.leadingNames,
3959
+ acceptingAnyToken: parser.acceptingAnyToken,
3960
+ parse(context) {
3961
+ return parser.parse(context);
3962
+ }
3963
+ }];
3964
+ return lanes.map((lane) => ({
3965
+ priority: lane.priority,
3966
+ zeroConsumptionGroup: (() => {
3967
+ const group$1 = lane.zeroConsumptionGroup ?? lane;
3968
+ const existing = occurrenceZeroConsumptionGroups.get(group$1);
3969
+ if (existing != null) return existing;
3970
+ const scoped = {};
3971
+ occurrenceZeroConsumptionGroups.set(group$1, scoped);
3972
+ return scoped;
3973
+ })(),
3974
+ settlesZeroConsumption: lane.settlesZeroConsumption,
3975
+ leadingNames: lane.leadingNames,
3976
+ acceptingAnyToken: lane.acceptingAnyToken,
3977
+ requiredConsumptionGroups: lane.requiredConsumptionGroups?.map((group$1) => ({
3978
+ id: scopeConsumptionGroup(group$1.id),
3979
+ ...group$1.isActive == null ? {} : { isActive(state) {
3980
+ if (state == null || typeof state !== "object") return false;
3981
+ const parserState = extractParserStateFromState(parser, state, sortedIndex);
3982
+ return group$1.isActive?.(parserState) ?? true;
3983
+ } }
3984
+ })),
3985
+ parse(context) {
3986
+ const parserState = extractParserState(parser, context, sortedIndex);
3987
+ const childContext = withChildContext$1(context, sortedIndex, parserState, parser);
3988
+ return dispatchByMode(combinedMode, () => {
3989
+ const result = lane.parse(childContext);
3990
+ return adaptMergeLaneResult(parser, context, parserState, childContext.state, result, sortedIndex);
3991
+ }, async () => {
3992
+ const result = await lane.parse(childContext);
3993
+ return adaptMergeLaneResult(parser, context, parserState, childContext.state, result, sortedIndex);
3994
+ });
3995
+ }
3996
+ }));
3997
+ }).toSorted((a, b) => b.priority - a.priority);
3998
+ const settleZeroConsumptionLanes = (context, laneResults) => {
3999
+ const groups = /* @__PURE__ */ new Map();
4000
+ for (const lane of mergeParseLanes) {
4001
+ const group$1 = lane.zeroConsumptionGroup ?? lane;
4002
+ const groupedLanes = groups.get(group$1);
4003
+ if (groupedLanes == null) groups.set(group$1, [lane]);
4004
+ else groupedLanes.push(lane);
4005
+ }
4006
+ const settledGroups = [];
4007
+ for (const groupedLanes of groups.values()) {
4008
+ const groupSucceeded = groupedLanes.every((lane) => {
4009
+ const result = laneResults.get(lane);
4010
+ return lane.settlesZeroConsumption !== false && result?.success === true && result.consumed.length === 0 && (lane.requiredConsumptionGroups?.length ?? 0) === 0;
4011
+ });
4012
+ if (!groupSucceeded) return null;
4013
+ settledGroups.push(groupedLanes);
4014
+ }
4015
+ let settledContext = context;
4016
+ for (const groupedLanes of settledGroups) for (const lane of groupedLanes) {
4017
+ const result = laneResults.get(lane);
4018
+ if (result?.success !== true) continue;
4019
+ const originalState = context.state;
4020
+ const resultState = result.next.state;
4021
+ const nextState = { ...settledContext.state };
4022
+ const stateKeys = new Set([...Reflect.ownKeys(originalState), ...Reflect.ownKeys(resultState)]);
4023
+ for (const key of stateKeys) {
4024
+ const originalHasKey = Object.hasOwn(originalState, key);
4025
+ const resultHasKey = Object.hasOwn(resultState, key);
4026
+ if (originalHasKey === resultHasKey && originalState[key] === resultState[key]) continue;
4027
+ if (resultHasKey) nextState[key] = resultState[key];
4028
+ else delete nextState[key];
4029
+ }
4030
+ const mergedExec = mergeChildExec(settledContext.exec, result.next.exec);
4031
+ settledContext = {
4032
+ ...settledContext,
4033
+ buffer: result.next.buffer,
4034
+ optionsTerminated: result.next.optionsTerminated,
4035
+ state: nextState,
4036
+ ...mergedExec != null ? {
4037
+ trace: mergedExec.trace,
4038
+ exec: mergedExec,
4039
+ dependencyRegistry: mergedExec.dependencyRegistry
4040
+ } : {}
4041
+ };
4042
+ }
4043
+ return {
4044
+ success: true,
4045
+ next: settledContext,
4046
+ consumed: []
4047
+ };
4048
+ };
4049
+ const canTryPositionalLaneAfterFailure = (lane, context) => {
4050
+ const token = context.buffer[0];
4051
+ return token != null && (context.optionsTerminated || !token.startsWith("-")) && (lane.acceptingAnyToken || lane.leadingNames.has(token));
4052
+ };
4053
+ const parseChildrenSync = (context) => {
3858
4054
  let currentContext = context;
3859
4055
  let zeroConsumedSuccess = null;
3860
4056
  for (let i = 0; i < syncParsers.length; i++) {
@@ -3895,11 +4091,10 @@ function merge(...args) {
3895
4091
  };
3896
4092
  return {
3897
4093
  success: false,
3898
- consumed: 0,
3899
- error: message`No matching option or argument found.`
4094
+ ...createObjectLikeInitialError(context, noMatchContext)
3900
4095
  };
3901
4096
  };
3902
- const parseAsync = async (context) => {
4097
+ const parseChildrenAsync = async (context) => {
3903
4098
  let currentContext = context;
3904
4099
  let zeroConsumedSuccess = null;
3905
4100
  for (let i = 0; i < parsers.length; i++) {
@@ -3941,8 +4136,133 @@ function merge(...args) {
3941
4136
  };
3942
4137
  return {
3943
4138
  success: false,
3944
- consumed: 0,
3945
- error: message`No matching option or argument found.`
4139
+ ...createObjectLikeInitialError(context, noMatchContext)
4140
+ };
4141
+ };
4142
+ const parseSync = (context) => {
4143
+ let currentContext = context;
4144
+ let error = createObjectLikeInitialError(context, noMatchContext);
4145
+ const allConsumed = [];
4146
+ const consumedLanes = /* @__PURE__ */ new Set();
4147
+ const consumedGroups = /* @__PURE__ */ new Set();
4148
+ const laneResults = /* @__PURE__ */ new Map();
4149
+ let attemptedLane = false;
4150
+ let madeProgress = true;
4151
+ while (madeProgress && currentContext.buffer.length > 0) {
4152
+ madeProgress = false;
4153
+ let consumingError = null;
4154
+ for (const lane of mergeParseLanes) {
4155
+ if (consumingError != null && lane.priority < consumingError.priority) {
4156
+ if (!canTryPositionalLaneAfterFailure(lane, currentContext)) continue;
4157
+ }
4158
+ attemptedLane = true;
4159
+ const result = lane.parse(currentContext);
4160
+ laneResults.set(lane, result);
4161
+ if (result.success && result.consumed.length > 0) {
4162
+ currentContext = result.next;
4163
+ allConsumed.push(...result.consumed);
4164
+ consumedLanes.add(lane);
4165
+ for (const group$1 of lane.requiredConsumptionGroups ?? []) if (group$1.isActive?.(result.next.state) !== false) consumedGroups.add(group$1.id);
4166
+ madeProgress = true;
4167
+ break;
4168
+ }
4169
+ if (!result.success) {
4170
+ if (result.consumed > 0 && consumingError == null) consumingError = {
4171
+ priority: lane.priority,
4172
+ result
4173
+ };
4174
+ if (error.consumed < result.consumed) error = result;
4175
+ }
4176
+ }
4177
+ if (!madeProgress && consumingError != null && allConsumed.length === 0) return consumingError.result;
4178
+ }
4179
+ if (allConsumed.length === 0) {
4180
+ if (attemptedLane) {
4181
+ const settled = settleZeroConsumptionLanes(context, laneResults);
4182
+ return settled ?? {
4183
+ ...error,
4184
+ success: false
4185
+ };
4186
+ }
4187
+ const fallback = parseChildrenSync(context);
4188
+ if (!fallback.success && fallback.consumed < error.consumed) return {
4189
+ ...error,
4190
+ success: false
4191
+ };
4192
+ return fallback;
4193
+ }
4194
+ for (const lane of mergeParseLanes) {
4195
+ if (consumedLanes.has(lane) || lane.leadingNames.size > 0 || lane.acceptingAnyToken || lane.requiredConsumptionGroups?.some((group$1) => !consumedGroups.has(group$1.id)) === true) continue;
4196
+ const result = lane.parse(currentContext);
4197
+ if (result.success && result.consumed.length === 0 && result.next.state !== currentContext.state) currentContext = result.next;
4198
+ }
4199
+ return {
4200
+ success: true,
4201
+ next: currentContext,
4202
+ consumed: allConsumed
4203
+ };
4204
+ };
4205
+ const parseAsync = async (context) => {
4206
+ let currentContext = context;
4207
+ let error = createObjectLikeInitialError(context, noMatchContext);
4208
+ const allConsumed = [];
4209
+ const consumedLanes = /* @__PURE__ */ new Set();
4210
+ const consumedGroups = /* @__PURE__ */ new Set();
4211
+ const laneResults = /* @__PURE__ */ new Map();
4212
+ let attemptedLane = false;
4213
+ let madeProgress = true;
4214
+ while (madeProgress && currentContext.buffer.length > 0) {
4215
+ madeProgress = false;
4216
+ let consumingError = null;
4217
+ for (const lane of mergeParseLanes) {
4218
+ if (consumingError != null && lane.priority < consumingError.priority) {
4219
+ if (!canTryPositionalLaneAfterFailure(lane, currentContext)) continue;
4220
+ }
4221
+ attemptedLane = true;
4222
+ const result = await lane.parse(currentContext);
4223
+ laneResults.set(lane, result);
4224
+ if (result.success && result.consumed.length > 0) {
4225
+ currentContext = result.next;
4226
+ allConsumed.push(...result.consumed);
4227
+ consumedLanes.add(lane);
4228
+ for (const group$1 of lane.requiredConsumptionGroups ?? []) if (group$1.isActive?.(result.next.state) !== false) consumedGroups.add(group$1.id);
4229
+ madeProgress = true;
4230
+ break;
4231
+ }
4232
+ if (!result.success) {
4233
+ if (result.consumed > 0 && consumingError == null) consumingError = {
4234
+ priority: lane.priority,
4235
+ result
4236
+ };
4237
+ if (error.consumed < result.consumed) error = result;
4238
+ }
4239
+ }
4240
+ if (!madeProgress && consumingError != null && allConsumed.length === 0) return consumingError.result;
4241
+ }
4242
+ if (allConsumed.length === 0) {
4243
+ if (attemptedLane) {
4244
+ const settled = settleZeroConsumptionLanes(context, laneResults);
4245
+ return settled ?? {
4246
+ ...error,
4247
+ success: false
4248
+ };
4249
+ }
4250
+ const fallback = await parseChildrenAsync(context);
4251
+ if (!fallback.success && fallback.consumed < error.consumed) return {
4252
+ ...error,
4253
+ success: false
4254
+ };
4255
+ return fallback;
4256
+ }
4257
+ for (const lane of mergeParseLanes) {
4258
+ if (consumedLanes.has(lane) || lane.leadingNames.size > 0 || lane.acceptingAnyToken || lane.requiredConsumptionGroups?.some((group$1) => !consumedGroups.has(group$1.id)) === true) continue;
4259
+ const result = await lane.parse(currentContext);
4260
+ if (result.success && result.consumed.length === 0 && result.next.state !== currentContext.state) currentContext = result.next;
4261
+ }
4262
+ return {
4263
+ success: true,
4264
+ next: currentContext,
4265
+ consumed: allConsumed
3946
4266
  };
3947
4267
  };
3948
4268
  const mergeParser = {
@@ -3950,10 +4270,10 @@ function merge(...args) {
3950
4270
  $valueType: [],
3951
4271
  $stateType: [],
3952
4272
  [fieldParsersKey]: mergedFieldParsers,
3953
- priority: Math.max(...parsers.map((p) => p.priority)),
4273
+ priority: Math.max(...mergeParseLanes.map((lane) => lane.priority)),
3954
4274
  usage: applyHiddenToUsage(parsers.flatMap((p) => p.usage), options.hidden),
3955
- leadingNames: sharedBufferLeadingNames(parsers),
3956
- acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
4275
+ leadingNames: sharedBufferLeadingNames(mergeParseLanes),
4276
+ acceptingAnyToken: mergeParseLanes.some((lane) => lane.acceptingAnyToken),
3957
4277
  initialState,
3958
4278
  canSkip(state, exec) {
3959
4279
  return parsers.every((parser, index) => {
@@ -4428,6 +4748,7 @@ function merge(...args) {
4428
4748
  };
4429
4749
  }
4430
4750
  };
4751
+ defineParseLanes(mergeParser, mergeParseLanes);
4431
4752
  defineInheritedAnnotationParser(mergeParser);
4432
4753
  return mergeParser;
4433
4754
  }
@@ -5110,6 +5431,7 @@ function group(label, parser, options = {}) {
5110
5431
  };
5111
5432
  }
5112
5433
  };
5434
+ defineParseLanes(groupParser, getOwnParseLanes(parser));
5113
5435
  Object.defineProperty(groupParser, extractPhase2SeedKey, {
5114
5436
  value(state, exec) {
5115
5437
  return extractPhase2Seed(parser, state, exec);
@@ -8,6 +8,12 @@ const require_input_trace = require('../input-trace.cjs');
8
8
 
9
9
  //#region src/internal/parser.ts
10
10
  /**
11
+ * Internal symbol used by transparent combinators to expose independently
12
+ * competing parse operations to shared-buffer parents.
13
+ * @internal
14
+ */
15
+ const parseLanesKey = Symbol("parseLanes");
16
+ /**
11
17
  * Internal marker for wrappers whose `{ hasCliValue: false }` states should
12
18
  * be treated as unmatched dependency-source states during completion-time
13
19
  * Phase 1.
@@ -387,6 +393,32 @@ function composeWrappedSourceMetadata(dependencyMetadata, wrapSource) {
387
393
  };
388
394
  }
389
395
  /**
396
+ * Defines internal parse-lane metadata without exposing it through object
397
+ * spreads used by custom parser wrappers.
398
+ *
399
+ * @internal
400
+ */
401
+ function defineParseLanes(parser, lanes) {
402
+ if (lanes == null) return;
403
+ Object.defineProperty(parser, parseLanesKey, {
404
+ value: lanes,
405
+ configurable: true,
406
+ enumerable: false
407
+ });
408
+ }
409
+ /**
410
+ * Gets parse-lane metadata defined directly on a parser.
411
+ *
412
+ * Inherited metadata belongs to the parser's prototype and must not bypass an
413
+ * overriding `parse()` implementation on a custom wrapper.
414
+ *
415
+ * @internal
416
+ */
417
+ function getOwnParseLanes(parser) {
418
+ if (!Object.hasOwn(parser, parseLanesKey)) return void 0;
419
+ return parser[parseLanesKey];
420
+ }
421
+ /**
390
422
  * Marks a parser as inheriting parent-state annotations through wrapper-state
391
423
  * reconstruction.
392
424
  *
@@ -797,15 +829,18 @@ exports.annotationWrapperRequiresSourceBindingKey = annotationWrapperRequiresSou
797
829
  exports.composeWrappedSourceMetadata = composeWrappedSourceMetadata;
798
830
  exports.createParserContext = createParserContext;
799
831
  exports.defineInheritedAnnotationParser = defineInheritedAnnotationParser;
832
+ exports.defineParseLanes = defineParseLanes;
800
833
  exports.defineSourceBindingOnlyAnnotationCompletionParser = defineSourceBindingOnlyAnnotationCompletionParser;
801
834
  exports.getDelegatingSuggestRuntimeNodes = getDelegatingSuggestRuntimeNodes;
802
835
  exports.getDocPage = getDocPage;
803
836
  exports.getDocPageAsync = getDocPageAsync;
804
837
  exports.getDocPageSync = getDocPageSync;
838
+ exports.getOwnParseLanes = getOwnParseLanes;
805
839
  exports.getParserSuggestRuntimeNodes = getParserSuggestRuntimeNodes;
806
840
  exports.inheritParentAnnotationsKey = inheritParentAnnotationsKey;
807
841
  exports.parse = parse;
808
842
  exports.parseAsync = parseAsync;
843
+ exports.parseLanesKey = parseLanesKey;
809
844
  exports.parseSync = parseSync;
810
845
  exports.suggest = suggest;
811
846
  exports.suggestAsync = suggestAsync;
@@ -42,6 +42,51 @@ type ModeValue<M extends Mode, T> = M extends "async" ? Promise<T> : T;
42
42
  * @since 0.9.0
43
43
  */
44
44
  type ModeIterable<M extends Mode, T> = M extends "async" ? AsyncIterable<T> : Iterable<T>;
45
+ /**
46
+ * Internal symbol used by transparent combinators to expose independently
47
+ * competing parse operations to shared-buffer parents.
48
+ * @internal
49
+ */
50
+ declare const parseLanesKey: unique symbol;
51
+ /**
52
+ * An owner-consumption requirement for a parse lane.
53
+ * @internal
54
+ */
55
+ interface ParseLaneConsumptionGroup {
56
+ /** Identity shared by lanes belonging to the same owning parser. */
57
+ readonly id: object;
58
+ /** Whether the owning parser is active after a consuming lane succeeds. */
59
+ readonly isActive?: (state: unknown) => boolean;
60
+ }
61
+ /**
62
+ * A state-preserving parse operation that competes at one exact priority.
63
+ * @internal
64
+ */
65
+ interface ParseLane<TState> {
66
+ /** The exact priority at which this lane competes. */
67
+ readonly priority: number;
68
+ /**
69
+ * Identity shared by lanes that must all succeed before their
70
+ * zero-consumption state updates can be committed.
71
+ */
72
+ readonly zeroConsumptionGroup?: object;
73
+ /**
74
+ * Whether a zero-consumption success can settle the owning parser while
75
+ * input remains. Defaults to `true`.
76
+ */
77
+ readonly settlesZeroConsumption?: boolean;
78
+ /** Fixed tokens reachable through this lane. */
79
+ readonly leadingNames: ReadonlySet<string>;
80
+ /** Whether this lane accepts any positional token. */
81
+ readonly acceptingAnyToken: boolean;
82
+ /**
83
+ * Groups in which a zero-consumption update is valid only after another
84
+ * lane in every group has consumed input during the same arbitration.
85
+ */
86
+ readonly requiredConsumptionGroups?: readonly ParseLaneConsumptionGroup[];
87
+ /** Parses through the owning parser's state and execution context. */
88
+ parse(context: ParserContext<TState>): ParserResult<TState> | Promise<ParserResult<TState>>;
89
+ }
45
90
  /**
46
91
  * Combines multiple modes into a single mode.
47
92
  * If any mode is `"async"`, the result is `"async"`; otherwise `"sync"`.
@@ -162,6 +207,13 @@ interface Parser<M extends Mode = "sync", TValue = unknown, TState = unknown> {
162
207
  * state when parsing starts.
163
208
  */
164
209
  readonly initialState: TState;
210
+ /**
211
+ * Independently competing parse operations exposed by transparent
212
+ * combinators. Shared-buffer parents use these to arbitrate below an
213
+ * aggregate parser boundary without bypassing the owner's state adapters.
214
+ * @internal
215
+ */
216
+ readonly [parseLanesKey]?: readonly ParseLane<TState>[];
165
217
  /**
166
218
  * Internal marker for wrappers whose `{ hasCliValue: false }` states should
167
219
  * be treated as unmatched dependency-source states during completion-time
@@ -851,6 +903,22 @@ declare function getDelegatingSuggestRuntimeNodes<TInnerState>(innerParser: Pars
851
903
  * @internal
852
904
  */
853
905
  declare function composeWrappedSourceMetadata(dependencyMetadata: ParserDependencyMetadata | undefined, wrapSource: (source: NonNullable<ParserDependencyMetadata["source"]>) => NonNullable<ParserDependencyMetadata["source"]>): ParserDependencyMetadata | undefined;
906
+ /**
907
+ * Defines internal parse-lane metadata without exposing it through object
908
+ * spreads used by custom parser wrappers.
909
+ *
910
+ * @internal
911
+ */
912
+ declare function defineParseLanes<TState>(parser: object, lanes: readonly ParseLane<TState>[] | undefined): void;
913
+ /**
914
+ * Gets parse-lane metadata defined directly on a parser.
915
+ *
916
+ * Inherited metadata belongs to the parser's prototype and must not bypass an
917
+ * overriding `parse()` implementation on a custom wrapper.
918
+ *
919
+ * @internal
920
+ */
921
+ declare function getOwnParseLanes<TState>(parser: object): readonly ParseLane<TState>[] | undefined;
854
922
  /**
855
923
  * Marks a parser as inheriting parent-state annotations through wrapper-state
856
924
  * reconstruction.
@@ -999,4 +1067,4 @@ declare function getDocPage(parser: Parser<"sync", unknown, unknown>, argsOrOpti
999
1067
  declare function getDocPage(parser: Parser<"async", unknown, unknown>, argsOrOptions?: readonly string[] | ParseOptions, options?: ParseOptions): Promise<DocPage | undefined>;
1000
1068
  declare function getDocPage<M extends Mode>(parser: Parser<M, unknown, unknown>, argsOrOptions?: readonly string[] | ParseOptions, options?: ParseOptions): ModeValue<M, DocPage | undefined>;
1001
1069
  //#endregion
1002
- export { CombineModes, DocState, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, type ParseOptions, Parser, ParserContext, ParserResult, Result, Suggestion, annotationWrapperRequiresSourceBindingKey, composeWrappedSourceMetadata, createParserContext, defineInheritedAnnotationParser, defineSourceBindingOnlyAnnotationCompletionParser, getDelegatingSuggestRuntimeNodes, getDocPage, getDocPageAsync, getDocPageSync, getParserSuggestRuntimeNodes, inheritParentAnnotationsKey, parse, parseAsync, parseSync, suggest, suggestAsync, suggestSync, unmatchedNonCliDependencySourceStateMarker };
1070
+ export { CombineModes, DocState, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, ParseLane, ParseLaneConsumptionGroup, type ParseOptions, Parser, ParserContext, ParserResult, Result, Suggestion, annotationWrapperRequiresSourceBindingKey, composeWrappedSourceMetadata, createParserContext, defineInheritedAnnotationParser, defineParseLanes, defineSourceBindingOnlyAnnotationCompletionParser, getDelegatingSuggestRuntimeNodes, getDocPage, getDocPageAsync, getDocPageSync, getOwnParseLanes, getParserSuggestRuntimeNodes, inheritParentAnnotationsKey, parse, parseAsync, parseLanesKey, parseSync, suggest, suggestAsync, suggestSync, unmatchedNonCliDependencySourceStateMarker };