@optique/core 0.3.0-dev.36 → 0.3.0-dev.38

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/parser.cjs CHANGED
@@ -717,30 +717,44 @@ function object(labelOrParsers, maybeParsers) {
717
717
  consumed: 0,
718
718
  error: context.buffer.length > 0 ? require_message.message`Unexpected option or argument: ${context.buffer[0]}.` : require_message.message`Expected an option or argument, but got end of input.`
719
719
  };
720
- for (const [field, parser] of parserPairs) {
721
- const result = parser.parse({
722
- ...context,
723
- state: context.state[field]
724
- });
725
- if (result.success && result.consumed.length > 0) return {
726
- success: true,
727
- next: {
728
- ...context,
729
- buffer: result.next.buffer,
730
- optionsTerminated: result.next.optionsTerminated,
731
- state: {
732
- ...context.state,
733
- [field]: result.next.state
734
- }
735
- },
736
- consumed: result.consumed
737
- };
738
- else if (!result.success && error.consumed < result.consumed) error = result;
720
+ let currentContext = context;
721
+ let anySuccess = false;
722
+ const allConsumed = [];
723
+ let madeProgress = true;
724
+ while (madeProgress && currentContext.buffer.length > 0) {
725
+ madeProgress = false;
726
+ for (const [field, parser] of parserPairs) {
727
+ const result = parser.parse({
728
+ ...currentContext,
729
+ state: currentContext.state && typeof currentContext.state === "object" && field in currentContext.state ? currentContext.state[field] : parser.initialState
730
+ });
731
+ if (result.success && result.consumed.length > 0) {
732
+ currentContext = {
733
+ ...currentContext,
734
+ buffer: result.next.buffer,
735
+ optionsTerminated: result.next.optionsTerminated,
736
+ state: {
737
+ ...currentContext.state,
738
+ [field]: result.next.state
739
+ }
740
+ };
741
+ allConsumed.push(...result.consumed);
742
+ anySuccess = true;
743
+ madeProgress = true;
744
+ break;
745
+ } else if (!result.success && error.consumed < result.consumed) error = result;
746
+ }
739
747
  }
748
+ if (anySuccess) return {
749
+ success: true,
750
+ next: currentContext,
751
+ consumed: allConsumed
752
+ };
740
753
  if (context.buffer.length === 0) {
741
754
  let allCanComplete = true;
742
755
  for (const [field, parser] of parserPairs) {
743
- const completeResult = parser.complete(context.state[field]);
756
+ const fieldState = context.state && typeof context.state === "object" && field in context.state ? context.state[field] : parser.initialState;
757
+ const completeResult = parser.complete(fieldState);
744
758
  if (!completeResult.success) {
745
759
  allCanComplete = false;
746
760
  break;
@@ -992,7 +1006,7 @@ function or(...parsers) {
992
1006
  function merge(...parsers) {
993
1007
  parsers = parsers.toSorted((a, b) => b.priority - a.priority);
994
1008
  const initialState = {};
995
- for (const parser of parsers) for (const field in parser.initialState) initialState[field] = parser.initialState[field];
1009
+ for (const parser of parsers) if (parser.initialState && typeof parser.initialState === "object") for (const field in parser.initialState) initialState[field] = parser.initialState[field];
996
1010
  return {
997
1011
  $valueType: [],
998
1012
  $stateType: [],
@@ -1000,22 +1014,41 @@ function merge(...parsers) {
1000
1014
  usage: parsers.flatMap((p) => p.usage),
1001
1015
  initialState,
1002
1016
  parse(context) {
1003
- for (const parser of parsers) {
1004
- const result = parser.parse(context);
1005
- if (result.success) return {
1006
- success: true,
1007
- next: {
1008
- ...context,
1009
- buffer: result.next.buffer,
1010
- optionsTerminated: result.next.optionsTerminated,
1011
- state: {
1012
- ...context.state,
1013
- ...result.next.state
1014
- }
1015
- },
1016
- consumed: result.consumed
1017
- };
1018
- else if (result.consumed < 1) continue;
1017
+ for (let i = 0; i < parsers.length; i++) {
1018
+ const parser = parsers[i];
1019
+ let parserState;
1020
+ if (parser.initialState === void 0) parserState = void 0;
1021
+ else if (parser.initialState && typeof parser.initialState === "object") if (context.state && typeof context.state === "object") {
1022
+ const extractedState = {};
1023
+ for (const field in parser.initialState) extractedState[field] = field in context.state ? context.state[field] : parser.initialState[field];
1024
+ parserState = extractedState;
1025
+ } else parserState = parser.initialState;
1026
+ else parserState = parser.initialState;
1027
+ const result = parser.parse({
1028
+ ...context,
1029
+ state: parserState
1030
+ });
1031
+ if (result.success) {
1032
+ let newState;
1033
+ if (parser.initialState === void 0) newState = {
1034
+ ...context.state,
1035
+ [`__parser_${i}`]: result.next.state
1036
+ };
1037
+ else newState = {
1038
+ ...context.state,
1039
+ ...result.next.state
1040
+ };
1041
+ return {
1042
+ success: true,
1043
+ next: {
1044
+ ...context,
1045
+ buffer: result.next.buffer,
1046
+ optionsTerminated: result.next.optionsTerminated,
1047
+ state: newState
1048
+ },
1049
+ consumed: result.consumed
1050
+ };
1051
+ } else if (result.consumed < 1) continue;
1019
1052
  else return result;
1020
1053
  }
1021
1054
  return {
@@ -1026,8 +1059,20 @@ function merge(...parsers) {
1026
1059
  },
1027
1060
  complete(state) {
1028
1061
  const object$1 = {};
1029
- for (const parser of parsers) {
1030
- const result = parser.complete(state);
1062
+ for (let i = 0; i < parsers.length; i++) {
1063
+ const parser = parsers[i];
1064
+ let parserState;
1065
+ if (parser.initialState === void 0) {
1066
+ const key = `__parser_${i}`;
1067
+ if (state && typeof state === "object" && key in state) parserState = state[key];
1068
+ else parserState = void 0;
1069
+ } else if (parser.initialState && typeof parser.initialState === "object") if (state && typeof state === "object") {
1070
+ const extractedState = {};
1071
+ for (const field in parser.initialState) extractedState[field] = field in state ? state[field] : parser.initialState[field];
1072
+ parserState = extractedState;
1073
+ } else parserState = parser.initialState;
1074
+ else parserState = parser.initialState;
1075
+ const result = parser.complete(parserState);
1031
1076
  if (!result.success) return result;
1032
1077
  for (const field in result.value) object$1[field] = result.value[field];
1033
1078
  }
package/dist/parser.d.cts CHANGED
@@ -636,6 +636,16 @@ declare function or<TA, TB, TC, TD, TE, TF, TG, TH, TI, TStateA, TStateB, TState
636
636
  * in order, returning the result of the first successful parser.
637
637
  */
638
638
  declare function or<TA, TB, TC, TD, TE, TF, TG, TH, TI, TJ, TStateA, TStateB, TStateC, TStateD, TStateE, TStateF, TStateG, TStateH, TStateI, TStateJ>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>, c: Parser<TC, TStateC>, d: Parser<TD, TStateD>, e: Parser<TE, TStateE>, f: Parser<TF, TStateF>, g: Parser<TG, TStateG>, h: Parser<TH, TStateH>, i: Parser<TI, TStateI>, j: Parser<TJ, TStateJ>): Parser<TA | TB | TC | TD | TE | TF | TG | TH | TI | TJ, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>] | [2, ParserResult<TStateC>] | [3, ParserResult<TStateD>] | [4, ParserResult<TStateE>] | [5, ParserResult<TStateF>] | [6, ParserResult<TStateG>] | [7, ParserResult<TStateH>] | [8, ParserResult<TStateI>] | [9, ParserResult<TStateJ>]>;
639
+ /**
640
+ * Helper type to check if all members of a union are object-like.
641
+ * This allows merge() to work with parsers like withDefault() that produce union types.
642
+ */
643
+ type AllObjectLike<T> = T extends Record<string | symbol, unknown> ? T : never;
644
+ /**
645
+ * Helper type to extract object-like types from parser value types,
646
+ * including union types where all members are objects.
647
+ */
648
+ type ExtractObjectTypes<P> = P extends Parser<infer V, unknown> ? [AllObjectLike<V>] extends [never] ? never : V : never;
639
649
  /**
640
650
  * Merges multiple {@link object} parsers into a single {@link object} parser.
641
651
  * It is useful for combining multiple {@link object} parsers so that
@@ -649,7 +659,7 @@ declare function or<TA, TB, TC, TD, TE, TF, TG, TH, TI, TJ, TStateA, TStateB, TS
649
659
  * @return A new {@link object} parser that combines the values and states
650
660
  * of the two parsers into a single object.
651
661
  */
652
- declare function merge<TA extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TB extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>>(a: TA, b: TB): Parser<{ readonly [K in keyof TA["$valueType"][number]]: TA["$valueType"][number][K] extends (infer U) ? U : never } & { readonly [K in keyof TB["$valueType"][number]]: TB["$valueType"][number][K] extends (infer U2) ? U2 : never }, { readonly [K in keyof TA]: unknown } & { readonly [K in keyof TB]: unknown }>;
662
+ declare function merge<TA extends Parser<unknown, unknown>, TB extends Parser<unknown, unknown>>(a: TA, b: TB): ExtractObjectTypes<TA> extends never ? never : ExtractObjectTypes<TB> extends never ? never : Parser<ExtractObjectTypes<TA> & ExtractObjectTypes<TB>, Record<string | symbol, unknown>>;
653
663
  /**
654
664
  * Merges multiple {@link object} parsers into a single {@link object} parser.
655
665
  * It is useful for combining multiple {@link object} parsers so that
@@ -665,7 +675,7 @@ declare function merge<TA extends Parser<Record<string | symbol, unknown>, Recor
665
675
  * @return A new {@link object} parser that combines the values and states
666
676
  * of the two parsers into a single object.
667
677
  */
668
- declare function merge<TA extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TB extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TC extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>>(a: TA, b: TB, c: TC): Parser<{ readonly [K in keyof TA["$valueType"][number]]: TA["$valueType"][number][K] extends (infer U) ? U : never } & { readonly [K in keyof TB["$valueType"][number]]: TB["$valueType"][number][K] extends (infer U2) ? U2 : never } & { readonly [K in keyof TC["$valueType"][number]]: TC["$valueType"][number][K] extends (infer U3) ? U3 : never }, { readonly [K in keyof TA]: unknown } & { readonly [K in keyof TB]: unknown } & { readonly [K in keyof TC]: unknown }>;
678
+ declare function merge<TA extends Parser<unknown, unknown>, TB extends Parser<unknown, unknown>, TC extends Parser<unknown, unknown>>(a: TA, b: TB, c: TC): ExtractObjectTypes<TA> extends never ? never : ExtractObjectTypes<TB> extends never ? never : ExtractObjectTypes<TC> extends never ? never : Parser<ExtractObjectTypes<TA> & ExtractObjectTypes<TB> & ExtractObjectTypes<TC>, Record<string | symbol, unknown>>;
669
679
  /**
670
680
  * Merges multiple {@link object} parsers into a single {@link object} parser.
671
681
  * It is useful for combining multiple {@link object} parsers so that
@@ -683,7 +693,7 @@ declare function merge<TA extends Parser<Record<string | symbol, unknown>, Recor
683
693
  * @return A new {@link object} parser that combines the values and states
684
694
  * of the two parsers into a single object.
685
695
  */
686
- declare function merge<TA extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TB extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TC extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TD extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>>(a: TA, b: TB, c: TC, d: TD): Parser<{ readonly [K in keyof TA["$valueType"][number]]: TA["$valueType"][number][K] extends (infer U) ? U : never } & { readonly [K in keyof TB["$valueType"][number]]: TB["$valueType"][number][K] extends (infer U2) ? U2 : never } & { readonly [K in keyof TC["$valueType"][number]]: TC["$valueType"][number][K] extends (infer U3) ? U3 : never } & { readonly [K in keyof TD["$valueType"][number]]: TD["$valueType"][number][K] extends (infer U4) ? U4 : never }, { readonly [K in keyof TA]: unknown } & { readonly [K in keyof TB]: unknown } & { readonly [K in keyof TC]: unknown } & { readonly [K in keyof TD]: unknown }>;
696
+ declare function merge<TA extends Parser<unknown, unknown>, TB extends Parser<unknown, unknown>, TC extends Parser<unknown, unknown>, TD extends Parser<unknown, unknown>>(a: TA, b: TB, c: TC, d: TD): ExtractObjectTypes<TA> extends never ? never : ExtractObjectTypes<TB> extends never ? never : ExtractObjectTypes<TC> extends never ? never : ExtractObjectTypes<TD> extends never ? never : Parser<ExtractObjectTypes<TA> & ExtractObjectTypes<TB> & ExtractObjectTypes<TC> & ExtractObjectTypes<TD>, Record<string | symbol, unknown>>;
687
697
  /**
688
698
  * Merges multiple {@link object} parsers into a single {@link object} parser.
689
699
  * It is useful for combining multiple {@link object} parsers so that
@@ -703,7 +713,7 @@ declare function merge<TA extends Parser<Record<string | symbol, unknown>, Recor
703
713
  * @return A new {@link object} parser that combines the values and states
704
714
  * of the two parsers into a single object.
705
715
  */
706
- declare function merge<TA extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TB extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TC extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TD extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TE extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>>(a: TA, b: TB, c: TC, d: TD, e: TE): Parser<{ readonly [K in keyof TA["$valueType"][number]]: TA["$valueType"][number][K] extends (infer U) ? U : never } & { readonly [K in keyof TB["$valueType"][number]]: TB["$valueType"][number][K] extends (infer U2) ? U2 : never } & { readonly [K in keyof TC["$valueType"][number]]: TC["$valueType"][number][K] extends (infer U3) ? U3 : never } & { readonly [K in keyof TD["$valueType"][number]]: TD["$valueType"][number][K] extends (infer U4) ? U4 : never } & { readonly [K in keyof TE["$valueType"][number]]: TE["$valueType"][number][K] extends (infer U5) ? U5 : never }, { readonly [K in keyof TA]: unknown } & { readonly [K in keyof TB]: unknown } & { readonly [K in keyof TC]: unknown } & { readonly [K in keyof TD]: unknown } & { readonly [K in keyof TE]: unknown }>;
716
+ declare function merge<TA extends Parser<unknown, unknown>, TB extends Parser<unknown, unknown>, TC extends Parser<unknown, unknown>, TD extends Parser<unknown, unknown>, TE extends Parser<unknown, unknown>>(a: TA, b: TB, c: TC, d: TD, e: TE): ExtractObjectTypes<TA> extends never ? never : ExtractObjectTypes<TB> extends never ? never : ExtractObjectTypes<TC> extends never ? never : ExtractObjectTypes<TD> extends never ? never : ExtractObjectTypes<TE> extends never ? never : Parser<ExtractObjectTypes<TA> & ExtractObjectTypes<TB> & ExtractObjectTypes<TC> & ExtractObjectTypes<TD> & ExtractObjectTypes<TE>, Record<string | symbol, unknown>>;
707
717
  /**
708
718
  * Concatenates two {@link tuple} parsers into a single parser that produces
709
719
  * a flattened tuple containing the values from both parsers in order.
package/dist/parser.d.ts CHANGED
@@ -636,6 +636,16 @@ declare function or<TA, TB, TC, TD, TE, TF, TG, TH, TI, TStateA, TStateB, TState
636
636
  * in order, returning the result of the first successful parser.
637
637
  */
638
638
  declare function or<TA, TB, TC, TD, TE, TF, TG, TH, TI, TJ, TStateA, TStateB, TStateC, TStateD, TStateE, TStateF, TStateG, TStateH, TStateI, TStateJ>(a: Parser<TA, TStateA>, b: Parser<TB, TStateB>, c: Parser<TC, TStateC>, d: Parser<TD, TStateD>, e: Parser<TE, TStateE>, f: Parser<TF, TStateF>, g: Parser<TG, TStateG>, h: Parser<TH, TStateH>, i: Parser<TI, TStateI>, j: Parser<TJ, TStateJ>): Parser<TA | TB | TC | TD | TE | TF | TG | TH | TI | TJ, undefined | [0, ParserResult<TStateA>] | [1, ParserResult<TStateB>] | [2, ParserResult<TStateC>] | [3, ParserResult<TStateD>] | [4, ParserResult<TStateE>] | [5, ParserResult<TStateF>] | [6, ParserResult<TStateG>] | [7, ParserResult<TStateH>] | [8, ParserResult<TStateI>] | [9, ParserResult<TStateJ>]>;
639
+ /**
640
+ * Helper type to check if all members of a union are object-like.
641
+ * This allows merge() to work with parsers like withDefault() that produce union types.
642
+ */
643
+ type AllObjectLike<T> = T extends Record<string | symbol, unknown> ? T : never;
644
+ /**
645
+ * Helper type to extract object-like types from parser value types,
646
+ * including union types where all members are objects.
647
+ */
648
+ type ExtractObjectTypes<P> = P extends Parser<infer V, unknown> ? [AllObjectLike<V>] extends [never] ? never : V : never;
639
649
  /**
640
650
  * Merges multiple {@link object} parsers into a single {@link object} parser.
641
651
  * It is useful for combining multiple {@link object} parsers so that
@@ -649,7 +659,7 @@ declare function or<TA, TB, TC, TD, TE, TF, TG, TH, TI, TJ, TStateA, TStateB, TS
649
659
  * @return A new {@link object} parser that combines the values and states
650
660
  * of the two parsers into a single object.
651
661
  */
652
- declare function merge<TA extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TB extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>>(a: TA, b: TB): Parser<{ readonly [K in keyof TA["$valueType"][number]]: TA["$valueType"][number][K] extends (infer U) ? U : never } & { readonly [K in keyof TB["$valueType"][number]]: TB["$valueType"][number][K] extends (infer U2) ? U2 : never }, { readonly [K in keyof TA]: unknown } & { readonly [K in keyof TB]: unknown }>;
662
+ declare function merge<TA extends Parser<unknown, unknown>, TB extends Parser<unknown, unknown>>(a: TA, b: TB): ExtractObjectTypes<TA> extends never ? never : ExtractObjectTypes<TB> extends never ? never : Parser<ExtractObjectTypes<TA> & ExtractObjectTypes<TB>, Record<string | symbol, unknown>>;
653
663
  /**
654
664
  * Merges multiple {@link object} parsers into a single {@link object} parser.
655
665
  * It is useful for combining multiple {@link object} parsers so that
@@ -665,7 +675,7 @@ declare function merge<TA extends Parser<Record<string | symbol, unknown>, Recor
665
675
  * @return A new {@link object} parser that combines the values and states
666
676
  * of the two parsers into a single object.
667
677
  */
668
- declare function merge<TA extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TB extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TC extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>>(a: TA, b: TB, c: TC): Parser<{ readonly [K in keyof TA["$valueType"][number]]: TA["$valueType"][number][K] extends (infer U) ? U : never } & { readonly [K in keyof TB["$valueType"][number]]: TB["$valueType"][number][K] extends (infer U2) ? U2 : never } & { readonly [K in keyof TC["$valueType"][number]]: TC["$valueType"][number][K] extends (infer U3) ? U3 : never }, { readonly [K in keyof TA]: unknown } & { readonly [K in keyof TB]: unknown } & { readonly [K in keyof TC]: unknown }>;
678
+ declare function merge<TA extends Parser<unknown, unknown>, TB extends Parser<unknown, unknown>, TC extends Parser<unknown, unknown>>(a: TA, b: TB, c: TC): ExtractObjectTypes<TA> extends never ? never : ExtractObjectTypes<TB> extends never ? never : ExtractObjectTypes<TC> extends never ? never : Parser<ExtractObjectTypes<TA> & ExtractObjectTypes<TB> & ExtractObjectTypes<TC>, Record<string | symbol, unknown>>;
669
679
  /**
670
680
  * Merges multiple {@link object} parsers into a single {@link object} parser.
671
681
  * It is useful for combining multiple {@link object} parsers so that
@@ -683,7 +693,7 @@ declare function merge<TA extends Parser<Record<string | symbol, unknown>, Recor
683
693
  * @return A new {@link object} parser that combines the values and states
684
694
  * of the two parsers into a single object.
685
695
  */
686
- declare function merge<TA extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TB extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TC extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TD extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>>(a: TA, b: TB, c: TC, d: TD): Parser<{ readonly [K in keyof TA["$valueType"][number]]: TA["$valueType"][number][K] extends (infer U) ? U : never } & { readonly [K in keyof TB["$valueType"][number]]: TB["$valueType"][number][K] extends (infer U2) ? U2 : never } & { readonly [K in keyof TC["$valueType"][number]]: TC["$valueType"][number][K] extends (infer U3) ? U3 : never } & { readonly [K in keyof TD["$valueType"][number]]: TD["$valueType"][number][K] extends (infer U4) ? U4 : never }, { readonly [K in keyof TA]: unknown } & { readonly [K in keyof TB]: unknown } & { readonly [K in keyof TC]: unknown } & { readonly [K in keyof TD]: unknown }>;
696
+ declare function merge<TA extends Parser<unknown, unknown>, TB extends Parser<unknown, unknown>, TC extends Parser<unknown, unknown>, TD extends Parser<unknown, unknown>>(a: TA, b: TB, c: TC, d: TD): ExtractObjectTypes<TA> extends never ? never : ExtractObjectTypes<TB> extends never ? never : ExtractObjectTypes<TC> extends never ? never : ExtractObjectTypes<TD> extends never ? never : Parser<ExtractObjectTypes<TA> & ExtractObjectTypes<TB> & ExtractObjectTypes<TC> & ExtractObjectTypes<TD>, Record<string | symbol, unknown>>;
687
697
  /**
688
698
  * Merges multiple {@link object} parsers into a single {@link object} parser.
689
699
  * It is useful for combining multiple {@link object} parsers so that
@@ -703,7 +713,7 @@ declare function merge<TA extends Parser<Record<string | symbol, unknown>, Recor
703
713
  * @return A new {@link object} parser that combines the values and states
704
714
  * of the two parsers into a single object.
705
715
  */
706
- declare function merge<TA extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TB extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TC extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TD extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>, TE extends Parser<Record<string | symbol, unknown>, Record<string | symbol, unknown>>>(a: TA, b: TB, c: TC, d: TD, e: TE): Parser<{ readonly [K in keyof TA["$valueType"][number]]: TA["$valueType"][number][K] extends (infer U) ? U : never } & { readonly [K in keyof TB["$valueType"][number]]: TB["$valueType"][number][K] extends (infer U2) ? U2 : never } & { readonly [K in keyof TC["$valueType"][number]]: TC["$valueType"][number][K] extends (infer U3) ? U3 : never } & { readonly [K in keyof TD["$valueType"][number]]: TD["$valueType"][number][K] extends (infer U4) ? U4 : never } & { readonly [K in keyof TE["$valueType"][number]]: TE["$valueType"][number][K] extends (infer U5) ? U5 : never }, { readonly [K in keyof TA]: unknown } & { readonly [K in keyof TB]: unknown } & { readonly [K in keyof TC]: unknown } & { readonly [K in keyof TD]: unknown } & { readonly [K in keyof TE]: unknown }>;
716
+ declare function merge<TA extends Parser<unknown, unknown>, TB extends Parser<unknown, unknown>, TC extends Parser<unknown, unknown>, TD extends Parser<unknown, unknown>, TE extends Parser<unknown, unknown>>(a: TA, b: TB, c: TC, d: TD, e: TE): ExtractObjectTypes<TA> extends never ? never : ExtractObjectTypes<TB> extends never ? never : ExtractObjectTypes<TC> extends never ? never : ExtractObjectTypes<TD> extends never ? never : ExtractObjectTypes<TE> extends never ? never : Parser<ExtractObjectTypes<TA> & ExtractObjectTypes<TB> & ExtractObjectTypes<TC> & ExtractObjectTypes<TD> & ExtractObjectTypes<TE>, Record<string | symbol, unknown>>;
707
717
  /**
708
718
  * Concatenates two {@link tuple} parsers into a single parser that produces
709
719
  * a flattened tuple containing the values from both parsers in order.
package/dist/parser.js CHANGED
@@ -717,30 +717,44 @@ function object(labelOrParsers, maybeParsers) {
717
717
  consumed: 0,
718
718
  error: context.buffer.length > 0 ? message`Unexpected option or argument: ${context.buffer[0]}.` : message`Expected an option or argument, but got end of input.`
719
719
  };
720
- for (const [field, parser] of parserPairs) {
721
- const result = parser.parse({
722
- ...context,
723
- state: context.state[field]
724
- });
725
- if (result.success && result.consumed.length > 0) return {
726
- success: true,
727
- next: {
728
- ...context,
729
- buffer: result.next.buffer,
730
- optionsTerminated: result.next.optionsTerminated,
731
- state: {
732
- ...context.state,
733
- [field]: result.next.state
734
- }
735
- },
736
- consumed: result.consumed
737
- };
738
- else if (!result.success && error.consumed < result.consumed) error = result;
720
+ let currentContext = context;
721
+ let anySuccess = false;
722
+ const allConsumed = [];
723
+ let madeProgress = true;
724
+ while (madeProgress && currentContext.buffer.length > 0) {
725
+ madeProgress = false;
726
+ for (const [field, parser] of parserPairs) {
727
+ const result = parser.parse({
728
+ ...currentContext,
729
+ state: currentContext.state && typeof currentContext.state === "object" && field in currentContext.state ? currentContext.state[field] : parser.initialState
730
+ });
731
+ if (result.success && result.consumed.length > 0) {
732
+ currentContext = {
733
+ ...currentContext,
734
+ buffer: result.next.buffer,
735
+ optionsTerminated: result.next.optionsTerminated,
736
+ state: {
737
+ ...currentContext.state,
738
+ [field]: result.next.state
739
+ }
740
+ };
741
+ allConsumed.push(...result.consumed);
742
+ anySuccess = true;
743
+ madeProgress = true;
744
+ break;
745
+ } else if (!result.success && error.consumed < result.consumed) error = result;
746
+ }
739
747
  }
748
+ if (anySuccess) return {
749
+ success: true,
750
+ next: currentContext,
751
+ consumed: allConsumed
752
+ };
740
753
  if (context.buffer.length === 0) {
741
754
  let allCanComplete = true;
742
755
  for (const [field, parser] of parserPairs) {
743
- const completeResult = parser.complete(context.state[field]);
756
+ const fieldState = context.state && typeof context.state === "object" && field in context.state ? context.state[field] : parser.initialState;
757
+ const completeResult = parser.complete(fieldState);
744
758
  if (!completeResult.success) {
745
759
  allCanComplete = false;
746
760
  break;
@@ -992,7 +1006,7 @@ function or(...parsers) {
992
1006
  function merge(...parsers) {
993
1007
  parsers = parsers.toSorted((a, b) => b.priority - a.priority);
994
1008
  const initialState = {};
995
- for (const parser of parsers) for (const field in parser.initialState) initialState[field] = parser.initialState[field];
1009
+ for (const parser of parsers) if (parser.initialState && typeof parser.initialState === "object") for (const field in parser.initialState) initialState[field] = parser.initialState[field];
996
1010
  return {
997
1011
  $valueType: [],
998
1012
  $stateType: [],
@@ -1000,22 +1014,41 @@ function merge(...parsers) {
1000
1014
  usage: parsers.flatMap((p) => p.usage),
1001
1015
  initialState,
1002
1016
  parse(context) {
1003
- for (const parser of parsers) {
1004
- const result = parser.parse(context);
1005
- if (result.success) return {
1006
- success: true,
1007
- next: {
1008
- ...context,
1009
- buffer: result.next.buffer,
1010
- optionsTerminated: result.next.optionsTerminated,
1011
- state: {
1012
- ...context.state,
1013
- ...result.next.state
1014
- }
1015
- },
1016
- consumed: result.consumed
1017
- };
1018
- else if (result.consumed < 1) continue;
1017
+ for (let i = 0; i < parsers.length; i++) {
1018
+ const parser = parsers[i];
1019
+ let parserState;
1020
+ if (parser.initialState === void 0) parserState = void 0;
1021
+ else if (parser.initialState && typeof parser.initialState === "object") if (context.state && typeof context.state === "object") {
1022
+ const extractedState = {};
1023
+ for (const field in parser.initialState) extractedState[field] = field in context.state ? context.state[field] : parser.initialState[field];
1024
+ parserState = extractedState;
1025
+ } else parserState = parser.initialState;
1026
+ else parserState = parser.initialState;
1027
+ const result = parser.parse({
1028
+ ...context,
1029
+ state: parserState
1030
+ });
1031
+ if (result.success) {
1032
+ let newState;
1033
+ if (parser.initialState === void 0) newState = {
1034
+ ...context.state,
1035
+ [`__parser_${i}`]: result.next.state
1036
+ };
1037
+ else newState = {
1038
+ ...context.state,
1039
+ ...result.next.state
1040
+ };
1041
+ return {
1042
+ success: true,
1043
+ next: {
1044
+ ...context,
1045
+ buffer: result.next.buffer,
1046
+ optionsTerminated: result.next.optionsTerminated,
1047
+ state: newState
1048
+ },
1049
+ consumed: result.consumed
1050
+ };
1051
+ } else if (result.consumed < 1) continue;
1019
1052
  else return result;
1020
1053
  }
1021
1054
  return {
@@ -1026,8 +1059,20 @@ function merge(...parsers) {
1026
1059
  },
1027
1060
  complete(state) {
1028
1061
  const object$1 = {};
1029
- for (const parser of parsers) {
1030
- const result = parser.complete(state);
1062
+ for (let i = 0; i < parsers.length; i++) {
1063
+ const parser = parsers[i];
1064
+ let parserState;
1065
+ if (parser.initialState === void 0) {
1066
+ const key = `__parser_${i}`;
1067
+ if (state && typeof state === "object" && key in state) parserState = state[key];
1068
+ else parserState = void 0;
1069
+ } else if (parser.initialState && typeof parser.initialState === "object") if (state && typeof state === "object") {
1070
+ const extractedState = {};
1071
+ for (const field in parser.initialState) extractedState[field] = field in state ? state[field] : parser.initialState[field];
1072
+ parserState = extractedState;
1073
+ } else parserState = parser.initialState;
1074
+ else parserState = parser.initialState;
1075
+ const result = parser.complete(parserState);
1031
1076
  if (!result.success) return result;
1032
1077
  for (const field in result.value) object$1[field] = result.value[field];
1033
1078
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "0.3.0-dev.36+680746e6",
3
+ "version": "0.3.0-dev.38+3b6c02a6",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",