@optique/core 1.0.0-dev.1712 → 1.0.0-dev.1716
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/constructs.cjs +160 -49
- package/dist/constructs.d.cts +14 -0
- package/dist/constructs.d.ts +14 -0
- package/dist/constructs.js +160 -49
- package/package.json +1 -1
package/dist/constructs.cjs
CHANGED
|
@@ -718,6 +718,16 @@ function or(...args) {
|
|
|
718
718
|
const result = parser.parse(withChildContext(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
|
|
719
719
|
if (result.success && result.consumed.length > 0) {
|
|
720
720
|
if (result.provisional) {
|
|
721
|
+
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
722
|
+
if (activeBranchLocked && activeState[0] === i) {
|
|
723
|
+
provisionalConsuming = {
|
|
724
|
+
index: i,
|
|
725
|
+
parser,
|
|
726
|
+
result
|
|
727
|
+
};
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
if (activeBranchLocked && provisionalConsuming != null && provisionalConsuming.index === activeState[0]) continue;
|
|
721
731
|
if (provisionalConsuming == null && !provisionalAmbiguous) provisionalConsuming = {
|
|
722
732
|
index: i,
|
|
723
733
|
parser,
|
|
@@ -826,23 +836,65 @@ function or(...args) {
|
|
|
826
836
|
consumed: []
|
|
827
837
|
};
|
|
828
838
|
}
|
|
829
|
-
if (provisionalConsuming !== null
|
|
830
|
-
const
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
839
|
+
if (provisionalConsuming !== null) {
|
|
840
|
+
const activeIsLockedDifferent = activeState != null && activeState[1].success && activeState[1].consumed.length > 0 && activeState[0] !== provisionalConsuming.index;
|
|
841
|
+
if (!activeIsLockedDifferent) {
|
|
842
|
+
const mergedExec = mergeChildExec(context.exec, provisionalConsuming.result.next.exec);
|
|
843
|
+
return {
|
|
844
|
+
success: true,
|
|
845
|
+
provisional: true,
|
|
846
|
+
next: {
|
|
847
|
+
...context,
|
|
848
|
+
buffer: provisionalConsuming.result.next.buffer,
|
|
849
|
+
optionsTerminated: provisionalConsuming.result.next.optionsTerminated,
|
|
850
|
+
state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, provisionalConsuming.result),
|
|
851
|
+
...mergedExec != null ? {
|
|
852
|
+
exec: mergedExec,
|
|
853
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
854
|
+
} : {}
|
|
855
|
+
},
|
|
856
|
+
consumed: provisionalConsuming.result.consumed
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
if (activeState != null && activeState[1].success) {
|
|
860
|
+
const previouslyConsumed = activeState[1].consumed;
|
|
861
|
+
const checkResult = provisionalConsuming.parser.parse({
|
|
862
|
+
...withChildContext(context, provisionalConsuming.index, provisionalConsuming.parser.initialState, provisionalConsuming.parser),
|
|
863
|
+
buffer: previouslyConsumed
|
|
864
|
+
});
|
|
865
|
+
const canConsumeShared = checkResult.success && checkResult.consumed.length === previouslyConsumed.length && checkResult.consumed.every((c, idx) => c === previouslyConsumed[idx]);
|
|
866
|
+
if (canConsumeShared && checkResult.success) {
|
|
867
|
+
const replayExec = mergeChildExec(context.exec, checkResult.next.exec);
|
|
868
|
+
const replayedResult = provisionalConsuming.parser.parse(withChildContext({
|
|
869
|
+
...context,
|
|
870
|
+
...replayExec != null ? {
|
|
871
|
+
exec: replayExec,
|
|
872
|
+
dependencyRegistry: replayExec.dependencyRegistry
|
|
873
|
+
} : {}
|
|
874
|
+
}, provisionalConsuming.index, checkResult.next.state, provisionalConsuming.parser));
|
|
875
|
+
if (replayedResult.success) {
|
|
876
|
+
const mergedExec = mergeChildExec(replayExec, replayedResult.next.exec);
|
|
877
|
+
return {
|
|
878
|
+
success: true,
|
|
879
|
+
provisional: true,
|
|
880
|
+
next: {
|
|
881
|
+
...context,
|
|
882
|
+
buffer: replayedResult.next.buffer,
|
|
883
|
+
optionsTerminated: replayedResult.next.optionsTerminated,
|
|
884
|
+
state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, {
|
|
885
|
+
...replayedResult,
|
|
886
|
+
consumed: [...previouslyConsumed, ...replayedResult.consumed]
|
|
887
|
+
}),
|
|
888
|
+
...mergedExec != null ? {
|
|
889
|
+
exec: mergedExec,
|
|
890
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
891
|
+
} : {}
|
|
892
|
+
},
|
|
893
|
+
consumed: replayedResult.consumed
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
846
898
|
}
|
|
847
899
|
return {
|
|
848
900
|
...error,
|
|
@@ -863,6 +915,16 @@ function or(...args) {
|
|
|
863
915
|
const result = await resultOrPromise;
|
|
864
916
|
if (result.success && result.consumed.length > 0) {
|
|
865
917
|
if (result.provisional) {
|
|
918
|
+
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
919
|
+
if (activeBranchLocked && activeState[0] === i) {
|
|
920
|
+
provisionalConsuming = {
|
|
921
|
+
index: i,
|
|
922
|
+
parser,
|
|
923
|
+
result
|
|
924
|
+
};
|
|
925
|
+
continue;
|
|
926
|
+
}
|
|
927
|
+
if (activeBranchLocked && provisionalConsuming != null && provisionalConsuming.index === activeState[0]) continue;
|
|
866
928
|
if (provisionalConsuming == null && !provisionalAmbiguous) provisionalConsuming = {
|
|
867
929
|
index: i,
|
|
868
930
|
parser,
|
|
@@ -973,23 +1035,65 @@ function or(...args) {
|
|
|
973
1035
|
consumed: []
|
|
974
1036
|
};
|
|
975
1037
|
}
|
|
976
|
-
if (provisionalConsuming !== null
|
|
977
|
-
const
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1038
|
+
if (provisionalConsuming !== null) {
|
|
1039
|
+
const activeIsLockedDifferent = activeState != null && activeState[1].success && activeState[1].consumed.length > 0 && activeState[0] !== provisionalConsuming.index;
|
|
1040
|
+
if (!activeIsLockedDifferent) {
|
|
1041
|
+
const mergedExec = mergeChildExec(context.exec, provisionalConsuming.result.next.exec);
|
|
1042
|
+
return {
|
|
1043
|
+
success: true,
|
|
1044
|
+
provisional: true,
|
|
1045
|
+
next: {
|
|
1046
|
+
...context,
|
|
1047
|
+
buffer: provisionalConsuming.result.next.buffer,
|
|
1048
|
+
optionsTerminated: provisionalConsuming.result.next.optionsTerminated,
|
|
1049
|
+
state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, provisionalConsuming.result),
|
|
1050
|
+
...mergedExec != null ? {
|
|
1051
|
+
exec: mergedExec,
|
|
1052
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1053
|
+
} : {}
|
|
1054
|
+
},
|
|
1055
|
+
consumed: provisionalConsuming.result.consumed
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
if (activeState != null && activeState[1].success) {
|
|
1059
|
+
const previouslyConsumed = activeState[1].consumed;
|
|
1060
|
+
const checkResult = await provisionalConsuming.parser.parse({
|
|
1061
|
+
...withChildContext(context, provisionalConsuming.index, provisionalConsuming.parser.initialState, provisionalConsuming.parser),
|
|
1062
|
+
buffer: previouslyConsumed
|
|
1063
|
+
});
|
|
1064
|
+
const canConsumeShared = checkResult.success && checkResult.consumed.length === previouslyConsumed.length && checkResult.consumed.every((c, idx) => c === previouslyConsumed[idx]);
|
|
1065
|
+
if (canConsumeShared && checkResult.success) {
|
|
1066
|
+
const replayExec = mergeChildExec(context.exec, checkResult.next.exec);
|
|
1067
|
+
const replayedResult = await provisionalConsuming.parser.parse(withChildContext({
|
|
1068
|
+
...context,
|
|
1069
|
+
...replayExec != null ? {
|
|
1070
|
+
exec: replayExec,
|
|
1071
|
+
dependencyRegistry: replayExec.dependencyRegistry
|
|
1072
|
+
} : {}
|
|
1073
|
+
}, provisionalConsuming.index, checkResult.next.state, provisionalConsuming.parser));
|
|
1074
|
+
if (replayedResult.success) {
|
|
1075
|
+
const mergedExec = mergeChildExec(replayExec, replayedResult.next.exec);
|
|
1076
|
+
return {
|
|
1077
|
+
success: true,
|
|
1078
|
+
provisional: true,
|
|
1079
|
+
next: {
|
|
1080
|
+
...context,
|
|
1081
|
+
buffer: replayedResult.next.buffer,
|
|
1082
|
+
optionsTerminated: replayedResult.next.optionsTerminated,
|
|
1083
|
+
state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, {
|
|
1084
|
+
...replayedResult,
|
|
1085
|
+
consumed: [...previouslyConsumed, ...replayedResult.consumed]
|
|
1086
|
+
}),
|
|
1087
|
+
...mergedExec != null ? {
|
|
1088
|
+
exec: mergedExec,
|
|
1089
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1090
|
+
} : {}
|
|
1091
|
+
},
|
|
1092
|
+
consumed: replayedResult.consumed
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
993
1097
|
}
|
|
994
1098
|
return {
|
|
995
1099
|
...error,
|
|
@@ -3964,19 +4068,22 @@ function conditional(discriminator, branches, defaultBranch, options) {
|
|
|
3964
4068
|
if (discriminatorResult.success) {
|
|
3965
4069
|
if (discriminatorResult.consumed.length === 0 && discriminator.$mode === "async") {
|
|
3966
4070
|
const discriminatorExec = mergeChildExec(context.exec, discriminatorResult.next.exec);
|
|
4071
|
+
const speculationContext = {
|
|
4072
|
+
...context,
|
|
4073
|
+
buffer: discriminatorResult.next.buffer,
|
|
4074
|
+
optionsTerminated: discriminatorResult.next.optionsTerminated,
|
|
4075
|
+
...discriminatorExec != null ? {
|
|
4076
|
+
exec: discriminatorExec,
|
|
4077
|
+
dependencyRegistry: discriminatorExec.dependencyRegistry
|
|
4078
|
+
} : {}
|
|
4079
|
+
};
|
|
3967
4080
|
let speculativeHit;
|
|
3968
4081
|
let provisionalHit;
|
|
3969
4082
|
let provisionalAmbiguous = false;
|
|
3970
4083
|
let speculativeError;
|
|
3971
4084
|
let ambiguous = false;
|
|
3972
4085
|
for (const [key, bp] of branchParsers) {
|
|
3973
|
-
const branchResult = await bp.parse(withChildContext(
|
|
3974
|
-
...context,
|
|
3975
|
-
...discriminatorExec != null ? {
|
|
3976
|
-
exec: discriminatorExec,
|
|
3977
|
-
dependencyRegistry: discriminatorExec.dependencyRegistry
|
|
3978
|
-
} : {}
|
|
3979
|
-
}, "_branch", bp.initialState, bp, bp.usage));
|
|
4086
|
+
const branchResult = await bp.parse(withChildContext(speculationContext, "_branch", bp.initialState, bp, bp.usage));
|
|
3980
4087
|
if (branchResult.success && branchResult.consumed.length > 0) {
|
|
3981
4088
|
if (branchResult.provisional) {
|
|
3982
4089
|
if (provisionalHit == null && !provisionalAmbiguous) provisionalHit = {
|
|
@@ -4034,10 +4141,10 @@ function conditional(discriminator, branches, defaultBranch, options) {
|
|
|
4034
4141
|
}
|
|
4035
4142
|
}
|
|
4036
4143
|
let deferredBranchState = state.branchState;
|
|
4037
|
-
if (defaultBranch !== void 0) {
|
|
4038
|
-
const defaultResult = await defaultBranch.parse(withChildContext(
|
|
4144
|
+
if (defaultBranch !== void 0 && !ambiguous && !provisionalAmbiguous) {
|
|
4145
|
+
const defaultResult = await defaultBranch.parse(withChildContext(speculationContext, "_branch", state.branchState ?? defaultBranch.initialState, defaultBranch, defaultBranch.usage));
|
|
4039
4146
|
if (defaultResult.success && defaultResult.consumed.length > 0) {
|
|
4040
|
-
const defaultExec = mergeChildExec(context.exec, defaultResult.next.exec);
|
|
4147
|
+
const defaultExec = mergeChildExec(discriminatorExec ?? context.exec, defaultResult.next.exec);
|
|
4041
4148
|
return {
|
|
4042
4149
|
success: true,
|
|
4043
4150
|
...defaultResult.provisional ? { provisional: true } : {},
|
|
@@ -4057,7 +4164,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
|
|
|
4057
4164
|
};
|
|
4058
4165
|
}
|
|
4059
4166
|
if (!defaultResult.success && defaultResult.consumed > 0) return defaultResult;
|
|
4060
|
-
if (defaultResult.success && defaultResult.consumed.length === 0 &&
|
|
4167
|
+
if (defaultResult.success && defaultResult.consumed.length === 0 && speculationContext.buffer.length === 0) deferredBranchState = getAnnotatedChildState(state, defaultResult.next.state, defaultBranch);
|
|
4061
4168
|
}
|
|
4062
4169
|
if (speculativeError != null && !ambiguous) return speculativeError;
|
|
4063
4170
|
const annotatedDiscriminatorState$1 = getAnnotatedChildState(state, discriminatorResult.next.state, discriminator);
|
|
@@ -4400,10 +4507,14 @@ function conditional(discriminator, branches, defaultBranch, options) {
|
|
|
4400
4507
|
else if (wasSpeculative) return completedDiscriminator;
|
|
4401
4508
|
else discriminatorValue = state.selectedBranch.key;
|
|
4402
4509
|
}
|
|
4403
|
-
if (wasSpeculative && state.selectedBranch.kind === "branch" && discriminatorValue !== state.selectedBranch.key)
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4510
|
+
if (wasSpeculative && state.selectedBranch.kind === "branch" && discriminatorValue !== state.selectedBranch.key) {
|
|
4511
|
+
const speculativeKey = state.selectedBranch.key;
|
|
4512
|
+
const resolvedKey = discriminatorValue ?? "";
|
|
4513
|
+
return {
|
|
4514
|
+
success: false,
|
|
4515
|
+
error: options?.errors?.branchMismatch ? options.errors.branchMismatch(resolvedKey, speculativeKey) : require_message.message`Branch mismatch: tokens for ${speculativeKey} were consumed, but the discriminator resolved to ${resolvedKey}.`
|
|
4516
|
+
};
|
|
4517
|
+
}
|
|
4407
4518
|
const branchResult = unwrapCompleteResult(await branchParser.complete(resolvedBranchState, withChildExecPath(completionExec, "_branch")));
|
|
4408
4519
|
if (!branchResult.success) {
|
|
4409
4520
|
if (discriminatorValue !== void 0 && options?.errors?.branchError) return {
|
package/dist/constructs.d.cts
CHANGED
|
@@ -1332,6 +1332,20 @@ interface ConditionalErrorOptions {
|
|
|
1332
1332
|
* Custom error message for no matching input.
|
|
1333
1333
|
*/
|
|
1334
1334
|
noMatch?: Message | ((context: NoMatchContext) => Message);
|
|
1335
|
+
/**
|
|
1336
|
+
* Custom error message when speculative branch parsing committed
|
|
1337
|
+
* to one branch but the resolved discriminator value names a
|
|
1338
|
+
* different branch. This is the contradictory-input case: tokens
|
|
1339
|
+
* specific to one branch were consumed during the parse phase,
|
|
1340
|
+
* but the discriminator (e.g., from `prompt()` or a deferred
|
|
1341
|
+
* config source) ultimately resolved to a different key.
|
|
1342
|
+
*
|
|
1343
|
+
* Receives both the discriminator value the parser actually
|
|
1344
|
+
* resolved to (`discriminatorValue`) and the speculative key the
|
|
1345
|
+
* branch tokens were committed to (`speculativeKey`).
|
|
1346
|
+
* @since 0.10.1
|
|
1347
|
+
*/
|
|
1348
|
+
branchMismatch?: (discriminatorValue: string, speculativeKey: string) => Message;
|
|
1335
1349
|
}
|
|
1336
1350
|
/**
|
|
1337
1351
|
* Options for customizing the {@link conditional} combinator behavior.
|
package/dist/constructs.d.ts
CHANGED
|
@@ -1332,6 +1332,20 @@ interface ConditionalErrorOptions {
|
|
|
1332
1332
|
* Custom error message for no matching input.
|
|
1333
1333
|
*/
|
|
1334
1334
|
noMatch?: Message | ((context: NoMatchContext) => Message);
|
|
1335
|
+
/**
|
|
1336
|
+
* Custom error message when speculative branch parsing committed
|
|
1337
|
+
* to one branch but the resolved discriminator value names a
|
|
1338
|
+
* different branch. This is the contradictory-input case: tokens
|
|
1339
|
+
* specific to one branch were consumed during the parse phase,
|
|
1340
|
+
* but the discriminator (e.g., from `prompt()` or a deferred
|
|
1341
|
+
* config source) ultimately resolved to a different key.
|
|
1342
|
+
*
|
|
1343
|
+
* Receives both the discriminator value the parser actually
|
|
1344
|
+
* resolved to (`discriminatorValue`) and the speculative key the
|
|
1345
|
+
* branch tokens were committed to (`speculativeKey`).
|
|
1346
|
+
* @since 0.10.1
|
|
1347
|
+
*/
|
|
1348
|
+
branchMismatch?: (discriminatorValue: string, speculativeKey: string) => Message;
|
|
1335
1349
|
}
|
|
1336
1350
|
/**
|
|
1337
1351
|
* Options for customizing the {@link conditional} combinator behavior.
|
package/dist/constructs.js
CHANGED
|
@@ -718,6 +718,16 @@ function or(...args) {
|
|
|
718
718
|
const result = parser.parse(withChildContext(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
|
|
719
719
|
if (result.success && result.consumed.length > 0) {
|
|
720
720
|
if (result.provisional) {
|
|
721
|
+
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
722
|
+
if (activeBranchLocked && activeState[0] === i) {
|
|
723
|
+
provisionalConsuming = {
|
|
724
|
+
index: i,
|
|
725
|
+
parser,
|
|
726
|
+
result
|
|
727
|
+
};
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
if (activeBranchLocked && provisionalConsuming != null && provisionalConsuming.index === activeState[0]) continue;
|
|
721
731
|
if (provisionalConsuming == null && !provisionalAmbiguous) provisionalConsuming = {
|
|
722
732
|
index: i,
|
|
723
733
|
parser,
|
|
@@ -826,23 +836,65 @@ function or(...args) {
|
|
|
826
836
|
consumed: []
|
|
827
837
|
};
|
|
828
838
|
}
|
|
829
|
-
if (provisionalConsuming !== null
|
|
830
|
-
const
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
839
|
+
if (provisionalConsuming !== null) {
|
|
840
|
+
const activeIsLockedDifferent = activeState != null && activeState[1].success && activeState[1].consumed.length > 0 && activeState[0] !== provisionalConsuming.index;
|
|
841
|
+
if (!activeIsLockedDifferent) {
|
|
842
|
+
const mergedExec = mergeChildExec(context.exec, provisionalConsuming.result.next.exec);
|
|
843
|
+
return {
|
|
844
|
+
success: true,
|
|
845
|
+
provisional: true,
|
|
846
|
+
next: {
|
|
847
|
+
...context,
|
|
848
|
+
buffer: provisionalConsuming.result.next.buffer,
|
|
849
|
+
optionsTerminated: provisionalConsuming.result.next.optionsTerminated,
|
|
850
|
+
state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, provisionalConsuming.result),
|
|
851
|
+
...mergedExec != null ? {
|
|
852
|
+
exec: mergedExec,
|
|
853
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
854
|
+
} : {}
|
|
855
|
+
},
|
|
856
|
+
consumed: provisionalConsuming.result.consumed
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
if (activeState != null && activeState[1].success) {
|
|
860
|
+
const previouslyConsumed = activeState[1].consumed;
|
|
861
|
+
const checkResult = provisionalConsuming.parser.parse({
|
|
862
|
+
...withChildContext(context, provisionalConsuming.index, provisionalConsuming.parser.initialState, provisionalConsuming.parser),
|
|
863
|
+
buffer: previouslyConsumed
|
|
864
|
+
});
|
|
865
|
+
const canConsumeShared = checkResult.success && checkResult.consumed.length === previouslyConsumed.length && checkResult.consumed.every((c, idx) => c === previouslyConsumed[idx]);
|
|
866
|
+
if (canConsumeShared && checkResult.success) {
|
|
867
|
+
const replayExec = mergeChildExec(context.exec, checkResult.next.exec);
|
|
868
|
+
const replayedResult = provisionalConsuming.parser.parse(withChildContext({
|
|
869
|
+
...context,
|
|
870
|
+
...replayExec != null ? {
|
|
871
|
+
exec: replayExec,
|
|
872
|
+
dependencyRegistry: replayExec.dependencyRegistry
|
|
873
|
+
} : {}
|
|
874
|
+
}, provisionalConsuming.index, checkResult.next.state, provisionalConsuming.parser));
|
|
875
|
+
if (replayedResult.success) {
|
|
876
|
+
const mergedExec = mergeChildExec(replayExec, replayedResult.next.exec);
|
|
877
|
+
return {
|
|
878
|
+
success: true,
|
|
879
|
+
provisional: true,
|
|
880
|
+
next: {
|
|
881
|
+
...context,
|
|
882
|
+
buffer: replayedResult.next.buffer,
|
|
883
|
+
optionsTerminated: replayedResult.next.optionsTerminated,
|
|
884
|
+
state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, {
|
|
885
|
+
...replayedResult,
|
|
886
|
+
consumed: [...previouslyConsumed, ...replayedResult.consumed]
|
|
887
|
+
}),
|
|
888
|
+
...mergedExec != null ? {
|
|
889
|
+
exec: mergedExec,
|
|
890
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
891
|
+
} : {}
|
|
892
|
+
},
|
|
893
|
+
consumed: replayedResult.consumed
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
846
898
|
}
|
|
847
899
|
return {
|
|
848
900
|
...error,
|
|
@@ -863,6 +915,16 @@ function or(...args) {
|
|
|
863
915
|
const result = await resultOrPromise;
|
|
864
916
|
if (result.success && result.consumed.length > 0) {
|
|
865
917
|
if (result.provisional) {
|
|
918
|
+
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
919
|
+
if (activeBranchLocked && activeState[0] === i) {
|
|
920
|
+
provisionalConsuming = {
|
|
921
|
+
index: i,
|
|
922
|
+
parser,
|
|
923
|
+
result
|
|
924
|
+
};
|
|
925
|
+
continue;
|
|
926
|
+
}
|
|
927
|
+
if (activeBranchLocked && provisionalConsuming != null && provisionalConsuming.index === activeState[0]) continue;
|
|
866
928
|
if (provisionalConsuming == null && !provisionalAmbiguous) provisionalConsuming = {
|
|
867
929
|
index: i,
|
|
868
930
|
parser,
|
|
@@ -973,23 +1035,65 @@ function or(...args) {
|
|
|
973
1035
|
consumed: []
|
|
974
1036
|
};
|
|
975
1037
|
}
|
|
976
|
-
if (provisionalConsuming !== null
|
|
977
|
-
const
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1038
|
+
if (provisionalConsuming !== null) {
|
|
1039
|
+
const activeIsLockedDifferent = activeState != null && activeState[1].success && activeState[1].consumed.length > 0 && activeState[0] !== provisionalConsuming.index;
|
|
1040
|
+
if (!activeIsLockedDifferent) {
|
|
1041
|
+
const mergedExec = mergeChildExec(context.exec, provisionalConsuming.result.next.exec);
|
|
1042
|
+
return {
|
|
1043
|
+
success: true,
|
|
1044
|
+
provisional: true,
|
|
1045
|
+
next: {
|
|
1046
|
+
...context,
|
|
1047
|
+
buffer: provisionalConsuming.result.next.buffer,
|
|
1048
|
+
optionsTerminated: provisionalConsuming.result.next.optionsTerminated,
|
|
1049
|
+
state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, provisionalConsuming.result),
|
|
1050
|
+
...mergedExec != null ? {
|
|
1051
|
+
exec: mergedExec,
|
|
1052
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1053
|
+
} : {}
|
|
1054
|
+
},
|
|
1055
|
+
consumed: provisionalConsuming.result.consumed
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
if (activeState != null && activeState[1].success) {
|
|
1059
|
+
const previouslyConsumed = activeState[1].consumed;
|
|
1060
|
+
const checkResult = await provisionalConsuming.parser.parse({
|
|
1061
|
+
...withChildContext(context, provisionalConsuming.index, provisionalConsuming.parser.initialState, provisionalConsuming.parser),
|
|
1062
|
+
buffer: previouslyConsumed
|
|
1063
|
+
});
|
|
1064
|
+
const canConsumeShared = checkResult.success && checkResult.consumed.length === previouslyConsumed.length && checkResult.consumed.every((c, idx) => c === previouslyConsumed[idx]);
|
|
1065
|
+
if (canConsumeShared && checkResult.success) {
|
|
1066
|
+
const replayExec = mergeChildExec(context.exec, checkResult.next.exec);
|
|
1067
|
+
const replayedResult = await provisionalConsuming.parser.parse(withChildContext({
|
|
1068
|
+
...context,
|
|
1069
|
+
...replayExec != null ? {
|
|
1070
|
+
exec: replayExec,
|
|
1071
|
+
dependencyRegistry: replayExec.dependencyRegistry
|
|
1072
|
+
} : {}
|
|
1073
|
+
}, provisionalConsuming.index, checkResult.next.state, provisionalConsuming.parser));
|
|
1074
|
+
if (replayedResult.success) {
|
|
1075
|
+
const mergedExec = mergeChildExec(replayExec, replayedResult.next.exec);
|
|
1076
|
+
return {
|
|
1077
|
+
success: true,
|
|
1078
|
+
provisional: true,
|
|
1079
|
+
next: {
|
|
1080
|
+
...context,
|
|
1081
|
+
buffer: replayedResult.next.buffer,
|
|
1082
|
+
optionsTerminated: replayedResult.next.optionsTerminated,
|
|
1083
|
+
state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, {
|
|
1084
|
+
...replayedResult,
|
|
1085
|
+
consumed: [...previouslyConsumed, ...replayedResult.consumed]
|
|
1086
|
+
}),
|
|
1087
|
+
...mergedExec != null ? {
|
|
1088
|
+
exec: mergedExec,
|
|
1089
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1090
|
+
} : {}
|
|
1091
|
+
},
|
|
1092
|
+
consumed: replayedResult.consumed
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
993
1097
|
}
|
|
994
1098
|
return {
|
|
995
1099
|
...error,
|
|
@@ -3964,19 +4068,22 @@ function conditional(discriminator, branches, defaultBranch, options) {
|
|
|
3964
4068
|
if (discriminatorResult.success) {
|
|
3965
4069
|
if (discriminatorResult.consumed.length === 0 && discriminator.$mode === "async") {
|
|
3966
4070
|
const discriminatorExec = mergeChildExec(context.exec, discriminatorResult.next.exec);
|
|
4071
|
+
const speculationContext = {
|
|
4072
|
+
...context,
|
|
4073
|
+
buffer: discriminatorResult.next.buffer,
|
|
4074
|
+
optionsTerminated: discriminatorResult.next.optionsTerminated,
|
|
4075
|
+
...discriminatorExec != null ? {
|
|
4076
|
+
exec: discriminatorExec,
|
|
4077
|
+
dependencyRegistry: discriminatorExec.dependencyRegistry
|
|
4078
|
+
} : {}
|
|
4079
|
+
};
|
|
3967
4080
|
let speculativeHit;
|
|
3968
4081
|
let provisionalHit;
|
|
3969
4082
|
let provisionalAmbiguous = false;
|
|
3970
4083
|
let speculativeError;
|
|
3971
4084
|
let ambiguous = false;
|
|
3972
4085
|
for (const [key, bp] of branchParsers) {
|
|
3973
|
-
const branchResult = await bp.parse(withChildContext(
|
|
3974
|
-
...context,
|
|
3975
|
-
...discriminatorExec != null ? {
|
|
3976
|
-
exec: discriminatorExec,
|
|
3977
|
-
dependencyRegistry: discriminatorExec.dependencyRegistry
|
|
3978
|
-
} : {}
|
|
3979
|
-
}, "_branch", bp.initialState, bp, bp.usage));
|
|
4086
|
+
const branchResult = await bp.parse(withChildContext(speculationContext, "_branch", bp.initialState, bp, bp.usage));
|
|
3980
4087
|
if (branchResult.success && branchResult.consumed.length > 0) {
|
|
3981
4088
|
if (branchResult.provisional) {
|
|
3982
4089
|
if (provisionalHit == null && !provisionalAmbiguous) provisionalHit = {
|
|
@@ -4034,10 +4141,10 @@ function conditional(discriminator, branches, defaultBranch, options) {
|
|
|
4034
4141
|
}
|
|
4035
4142
|
}
|
|
4036
4143
|
let deferredBranchState = state.branchState;
|
|
4037
|
-
if (defaultBranch !== void 0) {
|
|
4038
|
-
const defaultResult = await defaultBranch.parse(withChildContext(
|
|
4144
|
+
if (defaultBranch !== void 0 && !ambiguous && !provisionalAmbiguous) {
|
|
4145
|
+
const defaultResult = await defaultBranch.parse(withChildContext(speculationContext, "_branch", state.branchState ?? defaultBranch.initialState, defaultBranch, defaultBranch.usage));
|
|
4039
4146
|
if (defaultResult.success && defaultResult.consumed.length > 0) {
|
|
4040
|
-
const defaultExec = mergeChildExec(context.exec, defaultResult.next.exec);
|
|
4147
|
+
const defaultExec = mergeChildExec(discriminatorExec ?? context.exec, defaultResult.next.exec);
|
|
4041
4148
|
return {
|
|
4042
4149
|
success: true,
|
|
4043
4150
|
...defaultResult.provisional ? { provisional: true } : {},
|
|
@@ -4057,7 +4164,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
|
|
|
4057
4164
|
};
|
|
4058
4165
|
}
|
|
4059
4166
|
if (!defaultResult.success && defaultResult.consumed > 0) return defaultResult;
|
|
4060
|
-
if (defaultResult.success && defaultResult.consumed.length === 0 &&
|
|
4167
|
+
if (defaultResult.success && defaultResult.consumed.length === 0 && speculationContext.buffer.length === 0) deferredBranchState = getAnnotatedChildState(state, defaultResult.next.state, defaultBranch);
|
|
4061
4168
|
}
|
|
4062
4169
|
if (speculativeError != null && !ambiguous) return speculativeError;
|
|
4063
4170
|
const annotatedDiscriminatorState$1 = getAnnotatedChildState(state, discriminatorResult.next.state, discriminator);
|
|
@@ -4400,10 +4507,14 @@ function conditional(discriminator, branches, defaultBranch, options) {
|
|
|
4400
4507
|
else if (wasSpeculative) return completedDiscriminator;
|
|
4401
4508
|
else discriminatorValue = state.selectedBranch.key;
|
|
4402
4509
|
}
|
|
4403
|
-
if (wasSpeculative && state.selectedBranch.kind === "branch" && discriminatorValue !== state.selectedBranch.key)
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4510
|
+
if (wasSpeculative && state.selectedBranch.kind === "branch" && discriminatorValue !== state.selectedBranch.key) {
|
|
4511
|
+
const speculativeKey = state.selectedBranch.key;
|
|
4512
|
+
const resolvedKey = discriminatorValue ?? "";
|
|
4513
|
+
return {
|
|
4514
|
+
success: false,
|
|
4515
|
+
error: options?.errors?.branchMismatch ? options.errors.branchMismatch(resolvedKey, speculativeKey) : message`Branch mismatch: tokens for ${speculativeKey} were consumed, but the discriminator resolved to ${resolvedKey}.`
|
|
4516
|
+
};
|
|
4517
|
+
}
|
|
4407
4518
|
const branchResult = unwrapCompleteResult(await branchParser.complete(resolvedBranchState, withChildExecPath(completionExec, "_branch")));
|
|
4408
4519
|
if (!branchResult.success) {
|
|
4409
4520
|
if (discriminatorValue !== void 0 && options?.errors?.branchError) return {
|