@optique/core 1.1.2 → 1.1.3
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 +124 -41
- package/dist/constructs.js +124 -41
- package/package.json +2 -2
package/dist/constructs.cjs
CHANGED
|
@@ -581,6 +581,35 @@ function createExclusiveState(parentState, index, parser, result) {
|
|
|
581
581
|
return require_internal_annotations.annotateFreshArray(parentState, [index, annotatedResult]);
|
|
582
582
|
}
|
|
583
583
|
/**
|
|
584
|
+
* Detects a branch result that handled only the global options terminator.
|
|
585
|
+
* Such a result advances the shared parser context, but does not identify
|
|
586
|
+
* which exclusive branch matched.
|
|
587
|
+
* @internal
|
|
588
|
+
*/
|
|
589
|
+
function isOptionsTerminatorOnlyResult(context, result) {
|
|
590
|
+
return !context.optionsTerminated && context.buffer[0] === "--" && result.success && result.next.optionsTerminated && result.consumed.length === 1 && result.consumed[0] === "--";
|
|
591
|
+
}
|
|
592
|
+
function isUnselectedBooleanOptionState(state) {
|
|
593
|
+
return state != null && typeof state === "object" && "success" in state && state.success === true && "value" in state && state.value === false;
|
|
594
|
+
}
|
|
595
|
+
function preserveExclusiveStateAfterOptionsTerminator(context, result) {
|
|
596
|
+
const mergedExec = require_execution_context.mergeChildExec(context.exec, result.next.exec);
|
|
597
|
+
return {
|
|
598
|
+
success: true,
|
|
599
|
+
next: {
|
|
600
|
+
...context,
|
|
601
|
+
buffer: result.next.buffer,
|
|
602
|
+
optionsTerminated: true,
|
|
603
|
+
state: context.state,
|
|
604
|
+
...mergedExec != null ? {
|
|
605
|
+
exec: mergedExec,
|
|
606
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
607
|
+
} : {}
|
|
608
|
+
},
|
|
609
|
+
consumed: result.consumed
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
584
613
|
* Creates a complete() method shared by or() and longestMatch().
|
|
585
614
|
* @internal
|
|
586
615
|
*/
|
|
@@ -818,9 +847,15 @@ function or(...args) {
|
|
|
818
847
|
let zeroConsumedBranch = null;
|
|
819
848
|
let zeroConsumedCount = 0;
|
|
820
849
|
let provisionalConsuming = null;
|
|
850
|
+
let optionsTerminatorResult = null;
|
|
821
851
|
let provisionalAmbiguous = false;
|
|
822
852
|
for (const [parser, i] of orderedParsers) {
|
|
823
853
|
const result = parser.parse(withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
|
|
854
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
855
|
+
if (activeState?.[0] === i && activeState[1].success && activeState[1].consumed.length > 0 && result.next.buffer.length < 1) return preserveExclusiveStateAfterOptionsTerminator(context, result);
|
|
856
|
+
optionsTerminatorResult ??= result;
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
824
859
|
if (result.success && result.consumed.length > 0) {
|
|
825
860
|
if (result.provisional) {
|
|
826
861
|
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
@@ -1001,6 +1036,7 @@ function or(...args) {
|
|
|
1001
1036
|
}
|
|
1002
1037
|
}
|
|
1003
1038
|
}
|
|
1039
|
+
if (optionsTerminatorResult != null) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorResult);
|
|
1004
1040
|
return {
|
|
1005
1041
|
...error,
|
|
1006
1042
|
success: false
|
|
@@ -1014,10 +1050,16 @@ function or(...args) {
|
|
|
1014
1050
|
let zeroConsumedBranch = null;
|
|
1015
1051
|
let zeroConsumedCount = 0;
|
|
1016
1052
|
let provisionalConsuming = null;
|
|
1053
|
+
let optionsTerminatorResult = null;
|
|
1017
1054
|
let provisionalAmbiguous = false;
|
|
1018
1055
|
for (const [parser, i] of orderedParsers) {
|
|
1019
1056
|
const resultOrPromise = parser.parse(withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
|
|
1020
1057
|
const result = await resultOrPromise;
|
|
1058
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1059
|
+
if (activeState?.[0] === i && activeState[1].success && activeState[1].consumed.length > 0 && result.next.buffer.length < 1) return preserveExclusiveStateAfterOptionsTerminator(context, result);
|
|
1060
|
+
optionsTerminatorResult ??= result;
|
|
1061
|
+
continue;
|
|
1062
|
+
}
|
|
1021
1063
|
if (result.success && result.consumed.length > 0) {
|
|
1022
1064
|
if (result.provisional) {
|
|
1023
1065
|
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
@@ -1200,6 +1242,7 @@ function or(...args) {
|
|
|
1200
1242
|
}
|
|
1201
1243
|
}
|
|
1202
1244
|
}
|
|
1245
|
+
if (optionsTerminatorResult != null) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorResult);
|
|
1203
1246
|
return {
|
|
1204
1247
|
...error,
|
|
1205
1248
|
success: false
|
|
@@ -1301,82 +1344,122 @@ function createLongestMatch(...args) {
|
|
|
1301
1344
|
return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
|
|
1302
1345
|
})()
|
|
1303
1346
|
});
|
|
1304
|
-
const
|
|
1347
|
+
const commitLongestMatch = (context, match, optionsTerminatorResult) => {
|
|
1348
|
+
const selectedResult = optionsTerminatorResult == null ? match.result : {
|
|
1349
|
+
...match.result,
|
|
1350
|
+
next: {
|
|
1351
|
+
...match.result.next,
|
|
1352
|
+
buffer: optionsTerminatorResult.next.buffer,
|
|
1353
|
+
optionsTerminated: true
|
|
1354
|
+
},
|
|
1355
|
+
consumed: [...optionsTerminatorResult.consumed, ...match.result.consumed]
|
|
1356
|
+
};
|
|
1357
|
+
const parser = parsers[match.index];
|
|
1358
|
+
const mergedExec = require_execution_context.mergeChildExec(context.exec, selectedResult.next.exec);
|
|
1359
|
+
return {
|
|
1360
|
+
success: true,
|
|
1361
|
+
next: {
|
|
1362
|
+
...context,
|
|
1363
|
+
buffer: selectedResult.next.buffer,
|
|
1364
|
+
optionsTerminated: selectedResult.next.optionsTerminated,
|
|
1365
|
+
state: createExclusiveState(context.state, match.index, parser, selectedResult),
|
|
1366
|
+
...mergedExec != null ? {
|
|
1367
|
+
exec: mergedExec,
|
|
1368
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1369
|
+
} : {}
|
|
1370
|
+
},
|
|
1371
|
+
consumed: selectedResult.consumed
|
|
1372
|
+
};
|
|
1373
|
+
};
|
|
1374
|
+
const resolveLongestMatchOptionsTerminator = (context, bestMatch, optionsTerminatorMatches) => {
|
|
1375
|
+
if (optionsTerminatorMatches.length < 1) return null;
|
|
1376
|
+
if (bestMatch != null && bestMatch.consumed > 0) return null;
|
|
1377
|
+
const activeState = normalizeExclusiveState(context.state);
|
|
1378
|
+
if (activeState != null && activeState[1].success && activeState[1].consumed.length > 0) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorMatches[0].result);
|
|
1379
|
+
let selected = bestMatch == null ? null : {
|
|
1380
|
+
match: bestMatch,
|
|
1381
|
+
fromTerminator: false
|
|
1382
|
+
};
|
|
1383
|
+
for (const match of optionsTerminatorMatches) {
|
|
1384
|
+
if (!match.selectedAfterTerminator && (extractRequiredUsage(parsers[match.index].usage).length > 0 || isUnselectedBooleanOptionState(match.result.next.state))) continue;
|
|
1385
|
+
const selectedIsProvisional = selected != null && !!selected.match.result.provisional;
|
|
1386
|
+
const matchIsProvisional = !!match.result.provisional;
|
|
1387
|
+
if (selected == null || selectedIsProvisional && !matchIsProvisional || selectedIsProvisional === matchIsProvisional && match.index < selected.match.index) selected = {
|
|
1388
|
+
match,
|
|
1389
|
+
fromTerminator: true
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
if (selected != null) return commitLongestMatch(context, selected.match, selected.fromTerminator ? void 0 : optionsTerminatorMatches[0].result);
|
|
1393
|
+
return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorMatches[0].result);
|
|
1394
|
+
};
|
|
1395
|
+
const parseSyncBranches = (context) => {
|
|
1305
1396
|
let bestMatch = null;
|
|
1397
|
+
const optionsTerminatorMatches = [];
|
|
1306
1398
|
let error = getInitialError(context);
|
|
1307
1399
|
const activeState = normalizeExclusiveState(context.state);
|
|
1308
1400
|
for (let i = 0; i < syncParsers.length; i++) {
|
|
1309
1401
|
const parser = syncParsers[i];
|
|
1310
|
-
const
|
|
1402
|
+
const childContext = withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser);
|
|
1403
|
+
const result = parser.parse(childContext);
|
|
1404
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1405
|
+
optionsTerminatorMatches.push({
|
|
1406
|
+
index: i,
|
|
1407
|
+
result,
|
|
1408
|
+
consumed: 1,
|
|
1409
|
+
...normalizeExclusiveState(result.next.state) != null ? { selectedAfterTerminator: true } : {}
|
|
1410
|
+
});
|
|
1411
|
+
continue;
|
|
1412
|
+
}
|
|
1311
1413
|
if (result.success) {
|
|
1312
1414
|
const consumed = context.buffer.length - result.next.buffer.length;
|
|
1313
1415
|
const bestIsProvisional = bestMatch != null && bestMatch.result.success && !!bestMatch.result.provisional;
|
|
1314
1416
|
if (bestMatch === null || consumed > bestMatch.consumed || consumed === bestMatch.consumed && bestIsProvisional && !result.provisional) bestMatch = {
|
|
1315
1417
|
index: i,
|
|
1316
|
-
parser,
|
|
1317
1418
|
result,
|
|
1318
1419
|
consumed
|
|
1319
1420
|
};
|
|
1320
1421
|
} else if (error.consumed < result.consumed) error = result;
|
|
1321
1422
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
success: true,
|
|
1326
|
-
next: {
|
|
1327
|
-
...context,
|
|
1328
|
-
buffer: bestMatch.result.next.buffer,
|
|
1329
|
-
optionsTerminated: bestMatch.result.next.optionsTerminated,
|
|
1330
|
-
state: createExclusiveState(context.state, bestMatch.index, bestMatch.parser, bestMatch.result),
|
|
1331
|
-
...mergedExec != null ? {
|
|
1332
|
-
exec: mergedExec,
|
|
1333
|
-
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1334
|
-
} : {}
|
|
1335
|
-
},
|
|
1336
|
-
consumed: bestMatch.result.consumed
|
|
1337
|
-
};
|
|
1338
|
-
}
|
|
1423
|
+
const optionsTerminatorResolution = resolveLongestMatchOptionsTerminator(context, bestMatch, optionsTerminatorMatches);
|
|
1424
|
+
if (optionsTerminatorResolution != null) return optionsTerminatorResolution;
|
|
1425
|
+
if (bestMatch != null) return commitLongestMatch(context, bestMatch);
|
|
1339
1426
|
return {
|
|
1340
1427
|
...error,
|
|
1341
1428
|
success: false
|
|
1342
1429
|
};
|
|
1343
1430
|
};
|
|
1344
|
-
const
|
|
1431
|
+
const parseAsyncBranches = async (context) => {
|
|
1345
1432
|
let bestMatch = null;
|
|
1433
|
+
const optionsTerminatorMatches = [];
|
|
1346
1434
|
let error = getInitialError(context);
|
|
1347
1435
|
const activeState = normalizeExclusiveState(context.state);
|
|
1348
1436
|
for (let i = 0; i < parsers.length; i++) {
|
|
1349
1437
|
const parser = parsers[i];
|
|
1350
|
-
const
|
|
1438
|
+
const childContext = withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser);
|
|
1439
|
+
const resultOrPromise = parser.parse(childContext);
|
|
1351
1440
|
const result = await resultOrPromise;
|
|
1441
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1442
|
+
optionsTerminatorMatches.push({
|
|
1443
|
+
index: i,
|
|
1444
|
+
result,
|
|
1445
|
+
consumed: 1,
|
|
1446
|
+
...normalizeExclusiveState(result.next.state) != null ? { selectedAfterTerminator: true } : {}
|
|
1447
|
+
});
|
|
1448
|
+
continue;
|
|
1449
|
+
}
|
|
1352
1450
|
if (result.success) {
|
|
1353
1451
|
const consumed = context.buffer.length - result.next.buffer.length;
|
|
1354
1452
|
const bestIsProvisional = bestMatch != null && bestMatch.result.success && !!bestMatch.result.provisional;
|
|
1355
1453
|
if (bestMatch === null || consumed > bestMatch.consumed || consumed === bestMatch.consumed && bestIsProvisional && !result.provisional) bestMatch = {
|
|
1356
1454
|
index: i,
|
|
1357
|
-
parser,
|
|
1358
1455
|
result,
|
|
1359
1456
|
consumed
|
|
1360
1457
|
};
|
|
1361
1458
|
} else if (error.consumed < result.consumed) error = result;
|
|
1362
1459
|
}
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
success: true,
|
|
1367
|
-
next: {
|
|
1368
|
-
...context,
|
|
1369
|
-
buffer: bestMatch.result.next.buffer,
|
|
1370
|
-
optionsTerminated: bestMatch.result.next.optionsTerminated,
|
|
1371
|
-
state: createExclusiveState(context.state, bestMatch.index, bestMatch.parser, bestMatch.result),
|
|
1372
|
-
...mergedExec != null ? {
|
|
1373
|
-
exec: mergedExec,
|
|
1374
|
-
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1375
|
-
} : {}
|
|
1376
|
-
},
|
|
1377
|
-
consumed: bestMatch.result.consumed
|
|
1378
|
-
};
|
|
1379
|
-
}
|
|
1460
|
+
const optionsTerminatorResolution = resolveLongestMatchOptionsTerminator(context, bestMatch, optionsTerminatorMatches);
|
|
1461
|
+
if (optionsTerminatorResolution != null) return optionsTerminatorResolution;
|
|
1462
|
+
if (bestMatch != null) return commitLongestMatch(context, bestMatch);
|
|
1380
1463
|
return {
|
|
1381
1464
|
...error,
|
|
1382
1465
|
success: false
|
|
@@ -1399,7 +1482,7 @@ function createLongestMatch(...args) {
|
|
|
1399
1482
|
return extractExclusivePhase2Seed(parsers, state, exec, combinedMode);
|
|
1400
1483
|
},
|
|
1401
1484
|
parse(context) {
|
|
1402
|
-
return require_mode_dispatch.dispatchByMode(combinedMode, () =>
|
|
1485
|
+
return require_mode_dispatch.dispatchByMode(combinedMode, () => parseSyncBranches(context), () => parseAsyncBranches(context));
|
|
1403
1486
|
},
|
|
1404
1487
|
getSuggestRuntimeNodes(state, path) {
|
|
1405
1488
|
return getExclusiveSuggestRuntimeNodes(parsers, state, path);
|
package/dist/constructs.js
CHANGED
|
@@ -581,6 +581,35 @@ function createExclusiveState(parentState, index, parser, result) {
|
|
|
581
581
|
return annotateFreshArray(parentState, [index, annotatedResult]);
|
|
582
582
|
}
|
|
583
583
|
/**
|
|
584
|
+
* Detects a branch result that handled only the global options terminator.
|
|
585
|
+
* Such a result advances the shared parser context, but does not identify
|
|
586
|
+
* which exclusive branch matched.
|
|
587
|
+
* @internal
|
|
588
|
+
*/
|
|
589
|
+
function isOptionsTerminatorOnlyResult(context, result) {
|
|
590
|
+
return !context.optionsTerminated && context.buffer[0] === "--" && result.success && result.next.optionsTerminated && result.consumed.length === 1 && result.consumed[0] === "--";
|
|
591
|
+
}
|
|
592
|
+
function isUnselectedBooleanOptionState(state) {
|
|
593
|
+
return state != null && typeof state === "object" && "success" in state && state.success === true && "value" in state && state.value === false;
|
|
594
|
+
}
|
|
595
|
+
function preserveExclusiveStateAfterOptionsTerminator(context, result) {
|
|
596
|
+
const mergedExec = mergeChildExec(context.exec, result.next.exec);
|
|
597
|
+
return {
|
|
598
|
+
success: true,
|
|
599
|
+
next: {
|
|
600
|
+
...context,
|
|
601
|
+
buffer: result.next.buffer,
|
|
602
|
+
optionsTerminated: true,
|
|
603
|
+
state: context.state,
|
|
604
|
+
...mergedExec != null ? {
|
|
605
|
+
exec: mergedExec,
|
|
606
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
607
|
+
} : {}
|
|
608
|
+
},
|
|
609
|
+
consumed: result.consumed
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
584
613
|
* Creates a complete() method shared by or() and longestMatch().
|
|
585
614
|
* @internal
|
|
586
615
|
*/
|
|
@@ -818,9 +847,15 @@ function or(...args) {
|
|
|
818
847
|
let zeroConsumedBranch = null;
|
|
819
848
|
let zeroConsumedCount = 0;
|
|
820
849
|
let provisionalConsuming = null;
|
|
850
|
+
let optionsTerminatorResult = null;
|
|
821
851
|
let provisionalAmbiguous = false;
|
|
822
852
|
for (const [parser, i] of orderedParsers) {
|
|
823
853
|
const result = parser.parse(withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
|
|
854
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
855
|
+
if (activeState?.[0] === i && activeState[1].success && activeState[1].consumed.length > 0 && result.next.buffer.length < 1) return preserveExclusiveStateAfterOptionsTerminator(context, result);
|
|
856
|
+
optionsTerminatorResult ??= result;
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
824
859
|
if (result.success && result.consumed.length > 0) {
|
|
825
860
|
if (result.provisional) {
|
|
826
861
|
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
@@ -1001,6 +1036,7 @@ function or(...args) {
|
|
|
1001
1036
|
}
|
|
1002
1037
|
}
|
|
1003
1038
|
}
|
|
1039
|
+
if (optionsTerminatorResult != null) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorResult);
|
|
1004
1040
|
return {
|
|
1005
1041
|
...error,
|
|
1006
1042
|
success: false
|
|
@@ -1014,10 +1050,16 @@ function or(...args) {
|
|
|
1014
1050
|
let zeroConsumedBranch = null;
|
|
1015
1051
|
let zeroConsumedCount = 0;
|
|
1016
1052
|
let provisionalConsuming = null;
|
|
1053
|
+
let optionsTerminatorResult = null;
|
|
1017
1054
|
let provisionalAmbiguous = false;
|
|
1018
1055
|
for (const [parser, i] of orderedParsers) {
|
|
1019
1056
|
const resultOrPromise = parser.parse(withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
|
|
1020
1057
|
const result = await resultOrPromise;
|
|
1058
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1059
|
+
if (activeState?.[0] === i && activeState[1].success && activeState[1].consumed.length > 0 && result.next.buffer.length < 1) return preserveExclusiveStateAfterOptionsTerminator(context, result);
|
|
1060
|
+
optionsTerminatorResult ??= result;
|
|
1061
|
+
continue;
|
|
1062
|
+
}
|
|
1021
1063
|
if (result.success && result.consumed.length > 0) {
|
|
1022
1064
|
if (result.provisional) {
|
|
1023
1065
|
const activeBranchLocked = activeState != null && activeState[1].success && activeState[1].consumed.length > 0;
|
|
@@ -1200,6 +1242,7 @@ function or(...args) {
|
|
|
1200
1242
|
}
|
|
1201
1243
|
}
|
|
1202
1244
|
}
|
|
1245
|
+
if (optionsTerminatorResult != null) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorResult);
|
|
1203
1246
|
return {
|
|
1204
1247
|
...error,
|
|
1205
1248
|
success: false
|
|
@@ -1301,82 +1344,122 @@ function createLongestMatch(...args) {
|
|
|
1301
1344
|
return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
|
|
1302
1345
|
})()
|
|
1303
1346
|
});
|
|
1304
|
-
const
|
|
1347
|
+
const commitLongestMatch = (context, match, optionsTerminatorResult) => {
|
|
1348
|
+
const selectedResult = optionsTerminatorResult == null ? match.result : {
|
|
1349
|
+
...match.result,
|
|
1350
|
+
next: {
|
|
1351
|
+
...match.result.next,
|
|
1352
|
+
buffer: optionsTerminatorResult.next.buffer,
|
|
1353
|
+
optionsTerminated: true
|
|
1354
|
+
},
|
|
1355
|
+
consumed: [...optionsTerminatorResult.consumed, ...match.result.consumed]
|
|
1356
|
+
};
|
|
1357
|
+
const parser = parsers[match.index];
|
|
1358
|
+
const mergedExec = mergeChildExec(context.exec, selectedResult.next.exec);
|
|
1359
|
+
return {
|
|
1360
|
+
success: true,
|
|
1361
|
+
next: {
|
|
1362
|
+
...context,
|
|
1363
|
+
buffer: selectedResult.next.buffer,
|
|
1364
|
+
optionsTerminated: selectedResult.next.optionsTerminated,
|
|
1365
|
+
state: createExclusiveState(context.state, match.index, parser, selectedResult),
|
|
1366
|
+
...mergedExec != null ? {
|
|
1367
|
+
exec: mergedExec,
|
|
1368
|
+
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1369
|
+
} : {}
|
|
1370
|
+
},
|
|
1371
|
+
consumed: selectedResult.consumed
|
|
1372
|
+
};
|
|
1373
|
+
};
|
|
1374
|
+
const resolveLongestMatchOptionsTerminator = (context, bestMatch, optionsTerminatorMatches) => {
|
|
1375
|
+
if (optionsTerminatorMatches.length < 1) return null;
|
|
1376
|
+
if (bestMatch != null && bestMatch.consumed > 0) return null;
|
|
1377
|
+
const activeState = normalizeExclusiveState(context.state);
|
|
1378
|
+
if (activeState != null && activeState[1].success && activeState[1].consumed.length > 0) return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorMatches[0].result);
|
|
1379
|
+
let selected = bestMatch == null ? null : {
|
|
1380
|
+
match: bestMatch,
|
|
1381
|
+
fromTerminator: false
|
|
1382
|
+
};
|
|
1383
|
+
for (const match of optionsTerminatorMatches) {
|
|
1384
|
+
if (!match.selectedAfterTerminator && (extractRequiredUsage(parsers[match.index].usage).length > 0 || isUnselectedBooleanOptionState(match.result.next.state))) continue;
|
|
1385
|
+
const selectedIsProvisional = selected != null && !!selected.match.result.provisional;
|
|
1386
|
+
const matchIsProvisional = !!match.result.provisional;
|
|
1387
|
+
if (selected == null || selectedIsProvisional && !matchIsProvisional || selectedIsProvisional === matchIsProvisional && match.index < selected.match.index) selected = {
|
|
1388
|
+
match,
|
|
1389
|
+
fromTerminator: true
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
if (selected != null) return commitLongestMatch(context, selected.match, selected.fromTerminator ? void 0 : optionsTerminatorMatches[0].result);
|
|
1393
|
+
return preserveExclusiveStateAfterOptionsTerminator(context, optionsTerminatorMatches[0].result);
|
|
1394
|
+
};
|
|
1395
|
+
const parseSyncBranches = (context) => {
|
|
1305
1396
|
let bestMatch = null;
|
|
1397
|
+
const optionsTerminatorMatches = [];
|
|
1306
1398
|
let error = getInitialError(context);
|
|
1307
1399
|
const activeState = normalizeExclusiveState(context.state);
|
|
1308
1400
|
for (let i = 0; i < syncParsers.length; i++) {
|
|
1309
1401
|
const parser = syncParsers[i];
|
|
1310
|
-
const
|
|
1402
|
+
const childContext = withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser);
|
|
1403
|
+
const result = parser.parse(childContext);
|
|
1404
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1405
|
+
optionsTerminatorMatches.push({
|
|
1406
|
+
index: i,
|
|
1407
|
+
result,
|
|
1408
|
+
consumed: 1,
|
|
1409
|
+
...normalizeExclusiveState(result.next.state) != null ? { selectedAfterTerminator: true } : {}
|
|
1410
|
+
});
|
|
1411
|
+
continue;
|
|
1412
|
+
}
|
|
1311
1413
|
if (result.success) {
|
|
1312
1414
|
const consumed = context.buffer.length - result.next.buffer.length;
|
|
1313
1415
|
const bestIsProvisional = bestMatch != null && bestMatch.result.success && !!bestMatch.result.provisional;
|
|
1314
1416
|
if (bestMatch === null || consumed > bestMatch.consumed || consumed === bestMatch.consumed && bestIsProvisional && !result.provisional) bestMatch = {
|
|
1315
1417
|
index: i,
|
|
1316
|
-
parser,
|
|
1317
1418
|
result,
|
|
1318
1419
|
consumed
|
|
1319
1420
|
};
|
|
1320
1421
|
} else if (error.consumed < result.consumed) error = result;
|
|
1321
1422
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
success: true,
|
|
1326
|
-
next: {
|
|
1327
|
-
...context,
|
|
1328
|
-
buffer: bestMatch.result.next.buffer,
|
|
1329
|
-
optionsTerminated: bestMatch.result.next.optionsTerminated,
|
|
1330
|
-
state: createExclusiveState(context.state, bestMatch.index, bestMatch.parser, bestMatch.result),
|
|
1331
|
-
...mergedExec != null ? {
|
|
1332
|
-
exec: mergedExec,
|
|
1333
|
-
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1334
|
-
} : {}
|
|
1335
|
-
},
|
|
1336
|
-
consumed: bestMatch.result.consumed
|
|
1337
|
-
};
|
|
1338
|
-
}
|
|
1423
|
+
const optionsTerminatorResolution = resolveLongestMatchOptionsTerminator(context, bestMatch, optionsTerminatorMatches);
|
|
1424
|
+
if (optionsTerminatorResolution != null) return optionsTerminatorResolution;
|
|
1425
|
+
if (bestMatch != null) return commitLongestMatch(context, bestMatch);
|
|
1339
1426
|
return {
|
|
1340
1427
|
...error,
|
|
1341
1428
|
success: false
|
|
1342
1429
|
};
|
|
1343
1430
|
};
|
|
1344
|
-
const
|
|
1431
|
+
const parseAsyncBranches = async (context) => {
|
|
1345
1432
|
let bestMatch = null;
|
|
1433
|
+
const optionsTerminatorMatches = [];
|
|
1346
1434
|
let error = getInitialError(context);
|
|
1347
1435
|
const activeState = normalizeExclusiveState(context.state);
|
|
1348
1436
|
for (let i = 0; i < parsers.length; i++) {
|
|
1349
1437
|
const parser = parsers[i];
|
|
1350
|
-
const
|
|
1438
|
+
const childContext = withChildContext$1(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser);
|
|
1439
|
+
const resultOrPromise = parser.parse(childContext);
|
|
1351
1440
|
const result = await resultOrPromise;
|
|
1441
|
+
if (isOptionsTerminatorOnlyResult(context, result)) {
|
|
1442
|
+
optionsTerminatorMatches.push({
|
|
1443
|
+
index: i,
|
|
1444
|
+
result,
|
|
1445
|
+
consumed: 1,
|
|
1446
|
+
...normalizeExclusiveState(result.next.state) != null ? { selectedAfterTerminator: true } : {}
|
|
1447
|
+
});
|
|
1448
|
+
continue;
|
|
1449
|
+
}
|
|
1352
1450
|
if (result.success) {
|
|
1353
1451
|
const consumed = context.buffer.length - result.next.buffer.length;
|
|
1354
1452
|
const bestIsProvisional = bestMatch != null && bestMatch.result.success && !!bestMatch.result.provisional;
|
|
1355
1453
|
if (bestMatch === null || consumed > bestMatch.consumed || consumed === bestMatch.consumed && bestIsProvisional && !result.provisional) bestMatch = {
|
|
1356
1454
|
index: i,
|
|
1357
|
-
parser,
|
|
1358
1455
|
result,
|
|
1359
1456
|
consumed
|
|
1360
1457
|
};
|
|
1361
1458
|
} else if (error.consumed < result.consumed) error = result;
|
|
1362
1459
|
}
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
success: true,
|
|
1367
|
-
next: {
|
|
1368
|
-
...context,
|
|
1369
|
-
buffer: bestMatch.result.next.buffer,
|
|
1370
|
-
optionsTerminated: bestMatch.result.next.optionsTerminated,
|
|
1371
|
-
state: createExclusiveState(context.state, bestMatch.index, bestMatch.parser, bestMatch.result),
|
|
1372
|
-
...mergedExec != null ? {
|
|
1373
|
-
exec: mergedExec,
|
|
1374
|
-
dependencyRegistry: mergedExec.dependencyRegistry
|
|
1375
|
-
} : {}
|
|
1376
|
-
},
|
|
1377
|
-
consumed: bestMatch.result.consumed
|
|
1378
|
-
};
|
|
1379
|
-
}
|
|
1460
|
+
const optionsTerminatorResolution = resolveLongestMatchOptionsTerminator(context, bestMatch, optionsTerminatorMatches);
|
|
1461
|
+
if (optionsTerminatorResolution != null) return optionsTerminatorResolution;
|
|
1462
|
+
if (bestMatch != null) return commitLongestMatch(context, bestMatch);
|
|
1380
1463
|
return {
|
|
1381
1464
|
...error,
|
|
1382
1465
|
success: false
|
|
@@ -1399,7 +1482,7 @@ function createLongestMatch(...args) {
|
|
|
1399
1482
|
return extractExclusivePhase2Seed(parsers, state, exec, combinedMode);
|
|
1400
1483
|
},
|
|
1401
1484
|
parse(context) {
|
|
1402
|
-
return dispatchByMode(combinedMode, () =>
|
|
1485
|
+
return dispatchByMode(combinedMode, () => parseSyncBranches(context), () => parseAsyncBranches(context));
|
|
1403
1486
|
},
|
|
1404
1487
|
getSuggestRuntimeNodes(state, path) {
|
|
1405
1488
|
return getExclusiveSuggestRuntimeNodes(parsers, state, path);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optique/core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Type-safe combinatorial command-line interface parser",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CLI",
|
|
@@ -200,7 +200,7 @@
|
|
|
200
200
|
"fast-check": "^4.7.0",
|
|
201
201
|
"tsdown": "^0.13.0",
|
|
202
202
|
"typescript": "^5.8.3",
|
|
203
|
-
"@optique/env": "1.1.
|
|
203
|
+
"@optique/env": "1.1.3"
|
|
204
204
|
},
|
|
205
205
|
"scripts": {
|
|
206
206
|
"build": "tsdown",
|