@futpib/parser 1.0.3 → 1.0.6
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/.claude/settings.local.json +24 -0
- package/.github/workflows/main.yml +1 -0
- package/build/androidPackageParser.js +30 -32
- package/build/arbitraryDalvikBytecode.d.ts +3 -3
- package/build/arbitraryDalvikBytecode.js +33 -27
- package/build/arbitraryDalvikExecutable.js +55 -17
- package/build/arbitraryJava.d.ts +31 -0
- package/build/arbitraryJava.js +532 -0
- package/build/arbitraryJavaScript.d.ts +3 -0
- package/build/arbitraryJavaScript.js +263 -0
- package/build/arbitraryJavascript.d.ts +3 -0
- package/build/arbitraryJavascript.js +263 -0
- package/build/arbitraryZig.d.ts +3 -0
- package/build/arbitraryZig.js +240 -0
- package/build/arbitraryZipStream.d.ts +1 -1
- package/build/arrayParser.js +72 -13
- package/build/backsmali.d.ts +4 -3
- package/build/backsmali.js +26 -6
- package/build/bash.d.ts +89 -0
- package/build/bash.js +1 -0
- package/build/bashParser.d.ts +6 -0
- package/build/bashParser.js +335 -0
- package/build/bashParser.test.d.ts +1 -0
- package/build/bashParser.test.js +343 -0
- package/build/bashParserEdgeCases.test.d.ts +1 -0
- package/build/bashParserEdgeCases.test.js +117 -0
- package/build/dalvikBytecodeParser/addressConversion.d.ts +110 -0
- package/build/dalvikBytecodeParser/addressConversion.js +334 -0
- package/build/dalvikBytecodeParser/formatParsers.d.ts +7 -6
- package/build/dalvikBytecodeParser/formatParsers.js +13 -14
- package/build/dalvikBytecodeParser.d.ts +60 -31
- package/build/dalvikBytecodeParser.js +92 -35
- package/build/dalvikBytecodeParser.test-d.d.ts +1 -0
- package/build/dalvikBytecodeParser.test-d.js +268 -0
- package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +9 -8
- package/build/dalvikBytecodeUnparser/formatUnparsers.js +13 -12
- package/build/dalvikBytecodeUnparser.d.ts +2 -2
- package/build/dalvikBytecodeUnparser.js +23 -23
- package/build/dalvikBytecodeUnparser.test.js +7 -7
- package/build/dalvikExecutable.d.ts +3 -3
- package/build/dalvikExecutable.test-d.d.ts +1 -0
- package/build/dalvikExecutable.test-d.js +59 -0
- package/build/dalvikExecutableParser/typedNumbers.d.ts +18 -0
- package/build/dalvikExecutableParser/typedNumbers.js +3 -0
- package/build/dalvikExecutableParser.d.ts +2 -1
- package/build/dalvikExecutableParser.js +96 -77
- package/build/dalvikExecutableParser.test.js +24 -3
- package/build/dalvikExecutableParserAgainstSmaliParser.test.js +3 -0
- package/build/dalvikExecutableUnparser/poolScanners.d.ts +2 -2
- package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +3 -3
- package/build/dalvikExecutableUnparser/sectionUnparsers.js +26 -11
- package/build/dalvikExecutableUnparser.d.ts +2 -2
- package/build/dalvikExecutableUnparser.test.js +2 -1
- package/build/disjunctionParser.d.ts +5 -3
- package/build/disjunctionParser.js +79 -17
- package/build/disjunctionParser.test-d.d.ts +1 -0
- package/build/disjunctionParser.test-d.js +72 -0
- package/build/elementSwitchParser.d.ts +4 -0
- package/build/{exactElementSwitchParser.js → elementSwitchParser.js} +3 -4
- package/build/elementSwitchParser.test-d.d.ts +1 -0
- package/build/elementSwitchParser.test-d.js +44 -0
- package/build/exactSequenceParser.d.ts +4 -2
- package/build/exactSequenceParser.test-d.d.ts +1 -0
- package/build/exactSequenceParser.test-d.js +36 -0
- package/build/fetchCid.js +2 -66
- package/build/index.d.ts +25 -2
- package/build/index.js +23 -1
- package/build/index.test.js +16 -1
- package/build/inputReader.d.ts +10 -0
- package/build/inputReader.js +36 -0
- package/build/java.d.ts +502 -0
- package/build/java.js +2 -0
- package/build/javaKeyStoreParser.js +14 -17
- package/build/javaParser.d.ts +51 -0
- package/build/javaParser.js +1538 -0
- package/build/javaParser.test.d.ts +1 -0
- package/build/javaParser.test.js +1287 -0
- package/build/javaScript.d.ts +35 -0
- package/build/javaScript.js +1 -0
- package/build/javaScriptParser.d.ts +9 -0
- package/build/javaScriptParser.js +34 -0
- package/build/javaScriptUnparser.d.ts +3 -0
- package/build/javaScriptUnparser.js +4 -0
- package/build/javaScriptUnparser.test.d.ts +1 -0
- package/build/javaScriptUnparser.test.js +24 -0
- package/build/javaUnparser.d.ts +2 -0
- package/build/javaUnparser.js +519 -0
- package/build/javaUnparser.test.d.ts +1 -0
- package/build/javaUnparser.test.js +24 -0
- package/build/javascript.d.ts +35 -0
- package/build/javascript.js +1 -0
- package/build/javascriptParser.d.ts +9 -0
- package/build/javascriptParser.js +34 -0
- package/build/javascriptUnparser.d.ts +3 -0
- package/build/javascriptUnparser.js +4 -0
- package/build/javascriptUnparser.test.d.ts +1 -0
- package/build/javascriptUnparser.test.js +24 -0
- package/build/jsonParser.js +2 -12
- package/build/lazyMessageError.d.ts +3 -0
- package/build/lookaheadParser.js +60 -3
- package/build/negativeLookaheadParser.js +70 -11
- package/build/nonEmptyArrayParser.js +72 -13
- package/build/objectParser.d.ts +12 -0
- package/build/objectParser.js +31 -0
- package/build/objectParser.test-d.d.ts +1 -0
- package/build/objectParser.test-d.js +112 -0
- package/build/objectParser.test.d.ts +1 -0
- package/build/objectParser.test.js +55 -0
- package/build/optionalParser.js +69 -10
- package/build/parser.d.ts +4 -0
- package/build/parser.js +3 -1
- package/build/parser.test.js +114 -1
- package/build/parserConsumedSequenceParser.js +66 -7
- package/build/parserContext.d.ts +6 -0
- package/build/parserContext.js +20 -11
- package/build/parserError.d.ts +119 -27
- package/build/parserError.js +16 -8
- package/build/regexpParser.d.ts +2 -0
- package/build/regexpParser.js +101 -0
- package/build/regexpParser.test.d.ts +1 -0
- package/build/regexpParser.test.js +114 -0
- package/build/regularExpression.d.ts +63 -0
- package/build/regularExpression.js +1 -0
- package/build/regularExpressionParser.d.ts +3 -0
- package/build/regularExpressionParser.js +600 -0
- package/build/regularExpressionParser.test.d.ts +1 -0
- package/build/regularExpressionParser.test.js +89 -0
- package/build/separatedArrayParser.js +73 -14
- package/build/separatedNonEmptyArrayParser.js +73 -14
- package/build/sliceBoundedParser.js +62 -5
- package/build/smaliParser.d.ts +7 -7
- package/build/smaliParser.js +185 -268
- package/build/smaliParser.test.js +58 -0
- package/build/stringEscapes.d.ts +5 -0
- package/build/stringEscapes.js +244 -0
- package/build/symbolicExpression.d.ts +29 -0
- package/build/symbolicExpression.js +1 -0
- package/build/symbolicExpressionParser.d.ts +4 -0
- package/build/symbolicExpressionParser.js +123 -0
- package/build/symbolicExpressionParser.test.d.ts +1 -0
- package/build/symbolicExpressionParser.test.js +289 -0
- package/build/terminatedArrayParser.js +113 -38
- package/build/terminatedArrayParser.test.js +4 -2
- package/build/tupleParser.d.ts +7 -15
- package/build/tupleParser.js +1 -0
- package/build/unionParser.d.ts +5 -3
- package/build/unionParser.js +7 -2
- package/build/unionParser.test-d.d.ts +1 -0
- package/build/unionParser.test-d.js +72 -0
- package/build/unionParser.test.js +10 -11
- package/build/zig.d.ts +280 -0
- package/build/zig.js +2 -0
- package/build/zigParser.d.ts +3 -0
- package/build/zigParser.js +1119 -0
- package/build/zigParser.test.d.ts +1 -0
- package/build/zigParser.test.js +1590 -0
- package/build/zigUnparser.d.ts +2 -0
- package/build/zigUnparser.js +460 -0
- package/build/zigUnparser.test.d.ts +1 -0
- package/build/zigUnparser.test.js +24 -0
- package/build/zipParser.js +19 -32
- package/build/zipUnparser.js +19 -7
- package/build/zipUnparser.test.js +1 -1
- package/node_modules-@types/s-expression/index.d.ts +5 -0
- package/package.json +25 -6
- package/src/androidPackageParser.ts +33 -60
- package/src/arbitraryDalvikBytecode.ts +39 -31
- package/src/arbitraryDalvikExecutable.ts +65 -20
- package/src/arbitraryJava.ts +804 -0
- package/src/arbitraryJavaScript.ts +410 -0
- package/src/arbitraryZig.ts +380 -0
- package/src/arrayParser.ts +1 -3
- package/src/backsmali.ts +35 -4
- package/src/bash.ts +127 -0
- package/src/bashParser.test.ts +590 -0
- package/src/bashParser.ts +498 -0
- package/src/dalvikBytecodeParser/addressConversion.ts +496 -0
- package/src/dalvikBytecodeParser/formatParsers.ts +19 -29
- package/src/dalvikBytecodeParser.test-d.ts +310 -0
- package/src/dalvikBytecodeParser.ts +194 -69
- package/src/dalvikBytecodeUnparser/formatUnparsers.ts +27 -26
- package/src/dalvikBytecodeUnparser.test.ts +7 -7
- package/src/dalvikBytecodeUnparser.ts +31 -30
- package/src/dalvikExecutable.test-d.ts +132 -0
- package/src/dalvikExecutable.ts +3 -3
- package/src/dalvikExecutableParser/typedNumbers.ts +11 -0
- package/src/dalvikExecutableParser.test.ts +37 -3
- package/src/dalvikExecutableParser.test.ts.md +163 -2
- package/src/dalvikExecutableParser.test.ts.snap +0 -0
- package/src/dalvikExecutableParser.ts +121 -139
- package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +4 -0
- package/src/dalvikExecutableUnparser/poolScanners.ts +6 -6
- package/src/dalvikExecutableUnparser/sectionUnparsers.ts +38 -14
- package/src/dalvikExecutableUnparser.test.ts +3 -2
- package/src/dalvikExecutableUnparser.ts +4 -4
- package/src/disjunctionParser.test-d.ts +105 -0
- package/src/disjunctionParser.ts +18 -15
- package/src/elementSwitchParser.test-d.ts +74 -0
- package/src/elementSwitchParser.ts +51 -0
- package/src/exactSequenceParser.test-d.ts +43 -0
- package/src/exactSequenceParser.ts +13 -8
- package/src/fetchCid.ts +2 -76
- package/src/index.test.ts +22 -1
- package/src/index.ts +119 -2
- package/src/inputReader.ts +53 -0
- package/src/java.ts +708 -0
- package/src/javaKeyStoreParser.ts +18 -32
- package/src/javaParser.test.ts +1592 -0
- package/src/javaParser.ts +2640 -0
- package/src/javaScript.ts +36 -0
- package/src/javaScriptParser.ts +57 -0
- package/src/javaScriptUnparser.test.ts +37 -0
- package/src/javaScriptUnparser.ts +7 -0
- package/src/javaUnparser.test.ts +37 -0
- package/src/javaUnparser.ts +640 -0
- package/src/jsonParser.ts +6 -27
- package/src/lookaheadParser.ts +2 -6
- package/src/negativeLookaheadParser.ts +1 -3
- package/src/nonEmptyArrayParser.ts +1 -3
- package/src/objectParser.test-d.ts +152 -0
- package/src/objectParser.test.ts +71 -0
- package/src/objectParser.ts +69 -0
- package/src/optionalParser.ts +1 -3
- package/src/parser.test.ts +151 -4
- package/src/parser.ts +11 -1
- package/src/parserConsumedSequenceParser.ts +2 -4
- package/src/parserContext.ts +26 -11
- package/src/parserError.ts +17 -3
- package/src/regexpParser.test.ts +264 -0
- package/src/regexpParser.ts +126 -0
- package/src/regularExpression.ts +24 -0
- package/src/regularExpressionParser.test.ts +102 -0
- package/src/regularExpressionParser.ts +920 -0
- package/src/separatedArrayParser.ts +1 -3
- package/src/separatedNonEmptyArrayParser.ts +1 -3
- package/src/sliceBoundedParser.test.ts +2 -2
- package/src/sliceBoundedParser.ts +15 -19
- package/src/smaliParser.test.ts +64 -0
- package/src/smaliParser.test.ts.md +12 -12
- package/src/smaliParser.test.ts.snap +0 -0
- package/src/smaliParser.ts +246 -534
- package/src/stringEscapes.ts +253 -0
- package/src/symbolicExpression.ts +17 -0
- package/src/symbolicExpressionParser.test.ts +466 -0
- package/src/symbolicExpressionParser.ts +190 -0
- package/src/terminatedArrayParser.test.ts +9 -6
- package/src/terminatedArrayParser.ts +25 -29
- package/src/tupleParser.ts +21 -18
- package/src/unionParser.test-d.ts +105 -0
- package/src/unionParser.test.ts +18 -17
- package/src/unionParser.ts +28 -16
- package/src/zig.ts +411 -0
- package/src/zigParser.test.ts +1693 -0
- package/src/zigParser.ts +1745 -0
- package/src/zigUnparser.test.ts +37 -0
- package/src/zigUnparser.ts +615 -0
- package/src/zipParser.ts +20 -56
- package/src/zipUnparser.test.ts +1 -1
- package/src/zipUnparser.ts +22 -7
- package/tsconfig.json +2 -2
- package/build/exactElementSwitchParser.d.ts +0 -3
- package/src/exactElementSwitchParser.ts +0 -41
|
@@ -1,29 +1,91 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
var r, s = 0;
|
|
30
|
+
function next() {
|
|
31
|
+
while (r = env.stack.pop()) {
|
|
32
|
+
try {
|
|
33
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
+
if (r.dispose) {
|
|
35
|
+
var result = r.dispose.call(r.value);
|
|
36
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
+
}
|
|
38
|
+
else s |= 1;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
fail(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
+
if (env.hasError) throw env.error;
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
};
|
|
49
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
+
var e = new Error(message);
|
|
51
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
+
});
|
|
1
53
|
import { getParserName, setParserName } from './parser.js';
|
|
2
54
|
import { isParserParsingFailedError } from './parserError.js';
|
|
3
55
|
import { parserImplementationInvariant } from './parserImplementationInvariant.js';
|
|
4
56
|
import { promiseSettled } from './promiseSettled.js';
|
|
5
|
-
export
|
|
57
|
+
export function createDisjunctionParser(childParsers) {
|
|
6
58
|
parserImplementationInvariant(childParsers.length > 0, 'Disjunction parser must have at least one child parser.');
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
60
|
const disjunctionParser = async (parserContext) => {
|
|
8
61
|
const parserParsingFailedErrors = [];
|
|
9
62
|
for (const childParser of childParsers) {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
childParserContext
|
|
17
|
-
|
|
18
|
-
|
|
63
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
64
|
+
try {
|
|
65
|
+
const childParserContext = __addDisposableResource(env_1, parserContext.lookahead({
|
|
66
|
+
debugName: getParserName(childParser, 'anonymousDisjunctionChild'),
|
|
67
|
+
}), false);
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
|
+
const childParserResult = await promiseSettled(childParser(childParserContext));
|
|
70
|
+
if (childParserResult.status === 'fulfilled') {
|
|
71
|
+
const successfulParserOutput = childParserResult.value;
|
|
72
|
+
childParserContext.unlookahead();
|
|
73
|
+
return successfulParserOutput;
|
|
74
|
+
}
|
|
75
|
+
const error = childParserResult.reason;
|
|
76
|
+
if (isParserParsingFailedError(error)) {
|
|
77
|
+
parserParsingFailedErrors.push(error);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
19
82
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
parserParsingFailedErrors.push(error);
|
|
83
|
+
catch (e_1) {
|
|
84
|
+
env_1.error = e_1;
|
|
85
|
+
env_1.hasError = true;
|
|
24
86
|
}
|
|
25
|
-
|
|
26
|
-
|
|
87
|
+
finally {
|
|
88
|
+
__disposeResources(env_1);
|
|
27
89
|
}
|
|
28
90
|
}
|
|
29
91
|
return parserContext.invariantJoin(false, parserParsingFailedErrors, 'No disjunction child parser succeeded.');
|
|
@@ -34,4 +96,4 @@ export const createDisjunctionParser = (childParsers) => {
|
|
|
34
96
|
')',
|
|
35
97
|
].join('');
|
|
36
98
|
return setParserName(disjunctionParser, name);
|
|
37
|
-
}
|
|
99
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { expectAssignable } from 'tsd';
|
|
2
|
+
import { createDisjunctionParser } from './disjunctionParser.js';
|
|
3
|
+
import { createExactSequenceParser } from './exactSequenceParser.js';
|
|
4
|
+
import { createExactElementParser } from './exactElementParser.js';
|
|
5
|
+
import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js';
|
|
6
|
+
// Test: basic disjunction of string parsers - output inferred as string
|
|
7
|
+
{
|
|
8
|
+
const parser = createDisjunctionParser([
|
|
9
|
+
createExactElementParser('a'),
|
|
10
|
+
createExactElementParser('b'),
|
|
11
|
+
]);
|
|
12
|
+
expectAssignable(null);
|
|
13
|
+
expectAssignable(null);
|
|
14
|
+
}
|
|
15
|
+
// Test: disjunction preserves literal types when parsers have explicit literal output types
|
|
16
|
+
{
|
|
17
|
+
const parserA = async () => 'a';
|
|
18
|
+
const parserB = async () => 'b';
|
|
19
|
+
const parser = createDisjunctionParser([parserA, parserB]);
|
|
20
|
+
// Output should be 'a' | 'b', not string
|
|
21
|
+
expectAssignable(null);
|
|
22
|
+
expectAssignable(null);
|
|
23
|
+
}
|
|
24
|
+
// Test: disjunction of parsers with different output types
|
|
25
|
+
{
|
|
26
|
+
const stringParser = createFixedLengthSequenceParser(3);
|
|
27
|
+
const numberParser = () => 42;
|
|
28
|
+
const parser = createDisjunctionParser([
|
|
29
|
+
stringParser,
|
|
30
|
+
numberParser,
|
|
31
|
+
]);
|
|
32
|
+
// Output should be string | number
|
|
33
|
+
expectAssignable(null);
|
|
34
|
+
expectAssignable(null);
|
|
35
|
+
}
|
|
36
|
+
// Test: nested disjunctions
|
|
37
|
+
{
|
|
38
|
+
const inner = createDisjunctionParser([
|
|
39
|
+
createExactElementParser('a'),
|
|
40
|
+
createExactElementParser('b'),
|
|
41
|
+
]);
|
|
42
|
+
const parser = createDisjunctionParser([
|
|
43
|
+
inner,
|
|
44
|
+
createExactElementParser('c'),
|
|
45
|
+
]);
|
|
46
|
+
expectAssignable(null);
|
|
47
|
+
expectAssignable(null);
|
|
48
|
+
}
|
|
49
|
+
// Test: sequence type inferred from child parsers
|
|
50
|
+
{
|
|
51
|
+
const parser = createDisjunctionParser([
|
|
52
|
+
createExactSequenceParser('hello'),
|
|
53
|
+
createExactSequenceParser('world'),
|
|
54
|
+
]);
|
|
55
|
+
// Parser should be for string sequences, output is string (widened from literals)
|
|
56
|
+
expectAssignable(null);
|
|
57
|
+
}
|
|
58
|
+
// Test: single parser in disjunction
|
|
59
|
+
{
|
|
60
|
+
const parser = createDisjunctionParser([
|
|
61
|
+
createExactSequenceParser('only'),
|
|
62
|
+
]);
|
|
63
|
+
// Output is string (widened from literal 'only')
|
|
64
|
+
expectAssignable(null);
|
|
65
|
+
}
|
|
66
|
+
// Test: disjunction of object-producing parsers
|
|
67
|
+
{
|
|
68
|
+
const parser1 = async () => ({ type: 'a', value: 1 });
|
|
69
|
+
const parser2 = async () => ({ type: 'b', name: 'test' });
|
|
70
|
+
const parser = createDisjunctionParser([parser1, parser2]);
|
|
71
|
+
expectAssignable(null);
|
|
72
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Parser, ParserOutput, ParserSequence } from "./parser.js";
|
|
2
|
+
type ElementSwitchOutput<ChildParser extends Parser<any, any, any>, DefaultParser extends Parser<any, any, any> | undefined> = ParserOutput<ChildParser> | (DefaultParser extends undefined ? never : ParserOutput<NonNullable<DefaultParser>>);
|
|
3
|
+
export declare function createElementSwitchParser<Element, ChildParser extends Parser<any, any, Element>, DefaultParser extends Parser<any, any, Element> | undefined = undefined>(childParsers: Map<Element, ChildParser>, defaultParser?: DefaultParser): Parser<ElementSwitchOutput<ChildParser, DefaultParser>, ParserSequence<ChildParser>, Element>;
|
|
4
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import invariant from "invariant";
|
|
2
2
|
import { getParserName, setParserName } from "./parser.js";
|
|
3
3
|
import { parserImplementationInvariant } from "./parserImplementationInvariant.js";
|
|
4
|
-
export
|
|
4
|
+
export function createElementSwitchParser(childParsers, defaultParser) {
|
|
5
5
|
parserImplementationInvariant(childParsers.size > 0, 'Element switch parser must have at least one child parser.');
|
|
6
6
|
const elementSwitchParser = async (parserContext) => {
|
|
7
7
|
const currentElement = await parserContext.peek(0);
|
|
@@ -9,8 +9,7 @@ export const createElementSwitchParser = (childParsers, defaultParser) => {
|
|
|
9
9
|
invariant(currentElement !== undefined, 'Unexpected end of input.');
|
|
10
10
|
const childParser = childParsers.get(currentElement) ?? defaultParser;
|
|
11
11
|
parserContext.invariant(childParser, `No child parser found for element: ${String(currentElement)}`);
|
|
12
|
-
|
|
13
|
-
return childParserOutput;
|
|
12
|
+
return childParser(parserContext);
|
|
14
13
|
};
|
|
15
14
|
const name = [
|
|
16
15
|
'elementSwitch(',
|
|
@@ -19,4 +18,4 @@ export const createElementSwitchParser = (childParsers, defaultParser) => {
|
|
|
19
18
|
')',
|
|
20
19
|
].join('');
|
|
21
20
|
return setParserName(elementSwitchParser, name);
|
|
22
|
-
}
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { expectAssignable, expectType } from 'tsd';
|
|
2
|
+
import { createElementSwitchParser } from './elementSwitchParser.js';
|
|
3
|
+
// Test: basic element switch with inferred output type
|
|
4
|
+
{
|
|
5
|
+
const parserA = async () => 'a';
|
|
6
|
+
const parserB = async () => 'b';
|
|
7
|
+
const parser = createElementSwitchParser(new Map([
|
|
8
|
+
['x', parserA],
|
|
9
|
+
['y', parserB],
|
|
10
|
+
]));
|
|
11
|
+
// Output should be 'a' | 'b'
|
|
12
|
+
expectAssignable(null);
|
|
13
|
+
expectAssignable(null);
|
|
14
|
+
}
|
|
15
|
+
// Test: element switch with default parser
|
|
16
|
+
{
|
|
17
|
+
const parserA = async () => 'a';
|
|
18
|
+
const defaultParser = async () => 'default';
|
|
19
|
+
const parser = createElementSwitchParser(new Map([
|
|
20
|
+
['x', parserA],
|
|
21
|
+
]), defaultParser);
|
|
22
|
+
// Output should be 'a' | 'default'
|
|
23
|
+
expectAssignable(null);
|
|
24
|
+
expectAssignable(null);
|
|
25
|
+
}
|
|
26
|
+
// Test: element switch with number keys (Uint8Array sequence)
|
|
27
|
+
{
|
|
28
|
+
const parser1 = async () => ({ type: 'one' });
|
|
29
|
+
const parser2 = async () => ({ type: 'two' });
|
|
30
|
+
const parser = createElementSwitchParser(new Map([
|
|
31
|
+
[1, parser1],
|
|
32
|
+
[2, parser2],
|
|
33
|
+
]));
|
|
34
|
+
expectAssignable(null);
|
|
35
|
+
}
|
|
36
|
+
// Test: element switch without default parser has no 'never' in output
|
|
37
|
+
{
|
|
38
|
+
const parserA = async () => 'result';
|
|
39
|
+
const parser = createElementSwitchParser(new Map([
|
|
40
|
+
['key', parserA],
|
|
41
|
+
]));
|
|
42
|
+
// Output should just be string, not string | never
|
|
43
|
+
expectType(null);
|
|
44
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { type Parser } from './parser.js';
|
|
2
|
-
|
|
3
|
-
export declare const
|
|
2
|
+
type DeriveBaseSequence<T> = T extends string ? string : T extends Uint8Array ? Uint8Array : T;
|
|
3
|
+
export declare const createExactSequenceNaiveParser: <const Output>(sequence: Output) => Parser<Output, DeriveBaseSequence<Output>, unknown>;
|
|
4
|
+
export declare const createExactSequenceParser: <const Output>(expectedSequence: Output) => Parser<Output, DeriveBaseSequence<Output>, unknown>;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { expectType, expectAssignable } from 'tsd';
|
|
2
|
+
import { createExactSequenceParser, createExactSequenceNaiveParser } from './exactSequenceParser.js';
|
|
3
|
+
// Test: string literal output type is preserved, sequence type is string
|
|
4
|
+
{
|
|
5
|
+
const parser = createExactSequenceParser('foo');
|
|
6
|
+
expectType(parser);
|
|
7
|
+
}
|
|
8
|
+
// Test: string literal with 'as const' also works
|
|
9
|
+
{
|
|
10
|
+
const parser = createExactSequenceParser('bar');
|
|
11
|
+
expectType(parser);
|
|
12
|
+
}
|
|
13
|
+
// Test: plain string variable widens to string
|
|
14
|
+
{
|
|
15
|
+
const value = 'baz';
|
|
16
|
+
const parser = createExactSequenceParser(value);
|
|
17
|
+
expectType(parser);
|
|
18
|
+
}
|
|
19
|
+
// Test: Uint8Array sequence type is preserved
|
|
20
|
+
{
|
|
21
|
+
const bytes = new Uint8Array([1, 2, 3]);
|
|
22
|
+
const parser = createExactSequenceParser(bytes);
|
|
23
|
+
// Output is the specific Uint8Array instance type, Sequence is Uint8Array
|
|
24
|
+
expectAssignable(parser);
|
|
25
|
+
}
|
|
26
|
+
// Test: naive parser has same type behavior
|
|
27
|
+
{
|
|
28
|
+
const parser = createExactSequenceNaiveParser('hello');
|
|
29
|
+
expectType(parser);
|
|
30
|
+
}
|
|
31
|
+
// Test: naive parser with Uint8Array
|
|
32
|
+
{
|
|
33
|
+
const bytes = new Uint8Array([0xff]);
|
|
34
|
+
const parser = createExactSequenceNaiveParser(bytes);
|
|
35
|
+
expectAssignable(parser);
|
|
36
|
+
}
|
package/build/fetchCid.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import fsPromises from 'node:fs/promises';
|
|
2
|
-
import
|
|
3
|
-
import pMemoize from 'p-memoize';
|
|
4
|
-
import envPaths from 'env-paths';
|
|
5
|
-
const paths = envPaths('parser.futpib.github.io');
|
|
2
|
+
import { fetchCid as fetchCidFromIpfs } from '@futpib/fetch-cid';
|
|
6
3
|
function readableWebStreamOnFinish(readableWebStream, onFinish) {
|
|
7
4
|
const reader = readableWebStream.getReader();
|
|
8
5
|
const stream = new ReadableStream({
|
|
@@ -29,65 +26,6 @@ function readableWebStreamOnFinish(readableWebStream, onFinish) {
|
|
|
29
26
|
});
|
|
30
27
|
return stream;
|
|
31
28
|
}
|
|
32
|
-
class FsCache {
|
|
33
|
-
get _basePath() {
|
|
34
|
-
return path.join(paths.cache, 'fetchCid');
|
|
35
|
-
}
|
|
36
|
-
_getKeyPath(key) {
|
|
37
|
-
return path.join(this._basePath, key.replaceAll('/', '_'));
|
|
38
|
-
}
|
|
39
|
-
async get(key) {
|
|
40
|
-
try {
|
|
41
|
-
const file = await fsPromises.open(this._getKeyPath(key), 'r');
|
|
42
|
-
const stream = file.readableWebStream();
|
|
43
|
-
const streamWithClose = readableWebStreamOnFinish(stream, () => {
|
|
44
|
-
file.close();
|
|
45
|
-
});
|
|
46
|
-
return [streamWithClose, undefined];
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
if (error.code === 'ENOENT') {
|
|
50
|
-
return undefined;
|
|
51
|
-
}
|
|
52
|
-
throw error;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
async has(key) {
|
|
56
|
-
const streams = await this.get(key);
|
|
57
|
-
try {
|
|
58
|
-
return streams !== undefined;
|
|
59
|
-
}
|
|
60
|
-
finally {
|
|
61
|
-
for (const stream of streams ?? []) {
|
|
62
|
-
await stream?.cancel();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
async set(key, [_, value]) {
|
|
67
|
-
await fsPromises.mkdir(this._basePath, {
|
|
68
|
-
recursive: true,
|
|
69
|
-
});
|
|
70
|
-
const file = await fsPromises.open(this._getKeyPath(key), 'w');
|
|
71
|
-
try {
|
|
72
|
-
for await (const chunk of value) {
|
|
73
|
-
await file.write(chunk);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
await file.close();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
async delete(key) {
|
|
81
|
-
await fsPromises.unlink(this._getKeyPath(key));
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
async function reallyFetchCid(cid) {
|
|
85
|
-
const response = await fetch('https://ipfs.io/ipfs/' + cid);
|
|
86
|
-
return response.body.tee();
|
|
87
|
-
}
|
|
88
|
-
const cachedReallyFetchCid = pMemoize(reallyFetchCid, {
|
|
89
|
-
cache: new FsCache(),
|
|
90
|
-
});
|
|
91
29
|
export async function fetchCid(cidOrPath) {
|
|
92
30
|
if (cidOrPath.includes('/')) {
|
|
93
31
|
const file = await fsPromises.open(cidOrPath, 'r');
|
|
@@ -97,7 +35,5 @@ export async function fetchCid(cidOrPath) {
|
|
|
97
35
|
});
|
|
98
36
|
return streamWithClose;
|
|
99
37
|
}
|
|
100
|
-
|
|
101
|
-
await unused?.cancel();
|
|
102
|
-
return readable;
|
|
38
|
+
return fetchCidFromIpfs(cidOrPath);
|
|
103
39
|
}
|
package/build/index.d.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
export { type Parser, runParser, setParserName, getParserName, } from './parser.js';
|
|
1
|
+
export { type Parser, type ParserOutput, type ParserSequence, runParser, runParserWithRemainingInput, setParserName, getParserName, cloneParser, type RunParserOptions, type RunParserWithRemainingInputResult, } from './parser.js';
|
|
2
2
|
export type { ParserContext, } from './parserContext.js';
|
|
3
|
+
export { type ParserInputCompanion, StringParserInputCompanion, stringParserInputCompanion, Uint8ArrayParserInputCompanion, uint8ArrayParserInputCompanion, } from './parserInputCompanion.js';
|
|
4
|
+
export { type UnparserOutputCompanion, StringUnparserOutputCompanion, stringUnparserOutputCompanion, Uint8ArrayUnparserOutputCompanion, uint8ArrayUnparserOutputCompanion, } from './unparserOutputCompanion.js';
|
|
5
|
+
export { type ParserError, type ParserParsingFailedError, type ParserParsingJoinError, type ParserErrorModule, isParserError, isParserParsingFailedError, isParserParsingJoinError, normalParserErrorModule, noStackCaptureOverheadParserErrorModule, } from './parserError.js';
|
|
6
|
+
export { parserCreatorCompose, parserCreatorComposeMem, } from './parserCreatorCompose.js';
|
|
7
|
+
export { promiseCompose, } from './promiseCompose.js';
|
|
8
|
+
export type { DeriveSequenceElement, } from './sequence.js';
|
|
3
9
|
export { createTupleParser, } from './tupleParser.js';
|
|
10
|
+
export { createObjectParser, } from './objectParser.js';
|
|
4
11
|
export { createExactSequenceParser, } from './exactSequenceParser.js';
|
|
5
12
|
export { createFixedLengthSequenceParser, } from './fixedLengthSequenceParser.js';
|
|
6
13
|
export { createArrayParser, } from './arrayParser.js';
|
|
@@ -16,6 +23,22 @@ export { createSkipParser, } from './skipParser.js';
|
|
|
16
23
|
export { createEndOfInputParser, } from './endOfInputParser.js';
|
|
17
24
|
export { createListParser, } from './listParser.js';
|
|
18
25
|
export { createDebugLogParser, } from './debugLogParser.js';
|
|
19
|
-
export {
|
|
26
|
+
export { createNonEmptyArrayParser, } from './nonEmptyArrayParser.js';
|
|
27
|
+
export { createSeparatedArrayParser, } from './separatedArrayParser.js';
|
|
28
|
+
export { createSeparatedNonEmptyArrayParser, } from './separatedNonEmptyArrayParser.js';
|
|
29
|
+
export { createLookaheadParser, } from './lookaheadParser.js';
|
|
30
|
+
export { createNegativeLookaheadParser, } from './negativeLookaheadParser.js';
|
|
31
|
+
export { createElementTerminatedSequenceParser, } from './elementTerminatedSequenceParser.js';
|
|
32
|
+
export { createElementTerminatedSequenceArrayParser, } from './elementTerminatedSequenceArrayParser.js';
|
|
33
|
+
export { createElementTerminatedArrayParserUnsafe, } from './elementTerminatedArrayParser.js';
|
|
34
|
+
export { createSequenceTerminatedSequenceParser, } from './sequenceTerminatedSequenceParser.js';
|
|
35
|
+
export { createQuantifierParser, } from './quantifierParser.js';
|
|
36
|
+
export { createSkipToParser, } from './skipToParser.js';
|
|
37
|
+
export { createDebugLogInputParser, } from './debugLogInputParser.js';
|
|
38
|
+
export { createElementSwitchParser, } from './elementSwitchParser.js';
|
|
39
|
+
export { createParserConsumedSequenceParser, } from './parserConsumedSequenceParser.js';
|
|
40
|
+
export { type Unparser, type UnparserResult, runUnparser, } from './unparser.js';
|
|
41
|
+
export { type UnparserContext, WriteLater, WriteEarlier, UnparserContextImplementation, } from './unparserContext.js';
|
|
20
42
|
export { createArrayUnparser, } from './arrayUnparser.js';
|
|
21
43
|
export { createSequenceUnparser, } from './sequenceUnparser.js';
|
|
44
|
+
export { createRegExpParser, } from './regexpParser.js';
|
package/build/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
export { runParser, setParserName, getParserName, } from './parser.js';
|
|
1
|
+
export { runParser, runParserWithRemainingInput, setParserName, getParserName, cloneParser, } from './parser.js';
|
|
2
|
+
export { StringParserInputCompanion, stringParserInputCompanion, Uint8ArrayParserInputCompanion, uint8ArrayParserInputCompanion, } from './parserInputCompanion.js';
|
|
3
|
+
export { StringUnparserOutputCompanion, stringUnparserOutputCompanion, Uint8ArrayUnparserOutputCompanion, uint8ArrayUnparserOutputCompanion, } from './unparserOutputCompanion.js';
|
|
4
|
+
export { isParserError, isParserParsingFailedError, isParserParsingJoinError, normalParserErrorModule, noStackCaptureOverheadParserErrorModule, } from './parserError.js';
|
|
5
|
+
export { parserCreatorCompose, parserCreatorComposeMem, } from './parserCreatorCompose.js';
|
|
6
|
+
export { promiseCompose, } from './promiseCompose.js';
|
|
2
7
|
export { createTupleParser, } from './tupleParser.js';
|
|
8
|
+
export { createObjectParser, } from './objectParser.js';
|
|
3
9
|
export { createExactSequenceParser, } from './exactSequenceParser.js';
|
|
4
10
|
export { createFixedLengthSequenceParser, } from './fixedLengthSequenceParser.js';
|
|
5
11
|
export { createArrayParser, } from './arrayParser.js';
|
|
@@ -15,6 +21,22 @@ export { createSkipParser, } from './skipParser.js';
|
|
|
15
21
|
export { createEndOfInputParser, } from './endOfInputParser.js';
|
|
16
22
|
export { createListParser, } from './listParser.js';
|
|
17
23
|
export { createDebugLogParser, } from './debugLogParser.js';
|
|
24
|
+
export { createNonEmptyArrayParser, } from './nonEmptyArrayParser.js';
|
|
25
|
+
export { createSeparatedArrayParser, } from './separatedArrayParser.js';
|
|
26
|
+
export { createSeparatedNonEmptyArrayParser, } from './separatedNonEmptyArrayParser.js';
|
|
27
|
+
export { createLookaheadParser, } from './lookaheadParser.js';
|
|
28
|
+
export { createNegativeLookaheadParser, } from './negativeLookaheadParser.js';
|
|
29
|
+
export { createElementTerminatedSequenceParser, } from './elementTerminatedSequenceParser.js';
|
|
30
|
+
export { createElementTerminatedSequenceArrayParser, } from './elementTerminatedSequenceArrayParser.js';
|
|
31
|
+
export { createElementTerminatedArrayParserUnsafe, } from './elementTerminatedArrayParser.js';
|
|
32
|
+
export { createSequenceTerminatedSequenceParser, } from './sequenceTerminatedSequenceParser.js';
|
|
33
|
+
export { createQuantifierParser, } from './quantifierParser.js';
|
|
34
|
+
export { createSkipToParser, } from './skipToParser.js';
|
|
35
|
+
export { createDebugLogInputParser, } from './debugLogInputParser.js';
|
|
36
|
+
export { createElementSwitchParser, } from './elementSwitchParser.js';
|
|
37
|
+
export { createParserConsumedSequenceParser, } from './parserConsumedSequenceParser.js';
|
|
18
38
|
export { runUnparser, } from './unparser.js';
|
|
39
|
+
export { WriteLater, WriteEarlier, UnparserContextImplementation, } from './unparserContext.js';
|
|
19
40
|
export { createArrayUnparser, } from './arrayUnparser.js';
|
|
20
41
|
export { createSequenceUnparser, } from './sequenceUnparser.js';
|
|
42
|
+
export { createRegExpParser, } from './regexpParser.js';
|
package/build/index.test.js
CHANGED
|
@@ -1,2 +1,17 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
|
-
|
|
2
|
+
import { runParser, createExactSequenceParser, createTupleParser, stringParserInputCompanion, } from './index.js';
|
|
3
|
+
test('exports main parser functions', async (t) => {
|
|
4
|
+
// Test that runParser is exported and works
|
|
5
|
+
const parser = createExactSequenceParser('hello');
|
|
6
|
+
const result = await runParser(parser, 'hello', stringParserInputCompanion);
|
|
7
|
+
t.is(result, 'hello');
|
|
8
|
+
});
|
|
9
|
+
test('exports parser combinators', async (t) => {
|
|
10
|
+
// Test that createTupleParser is exported and works
|
|
11
|
+
const tupleParser = createTupleParser([
|
|
12
|
+
createExactSequenceParser('a'),
|
|
13
|
+
createExactSequenceParser('b'),
|
|
14
|
+
]);
|
|
15
|
+
const result = await runParser(tupleParser, 'ab', stringParserInputCompanion);
|
|
16
|
+
t.deepEqual(result, ['a', 'b']);
|
|
17
|
+
});
|
package/build/inputReader.d.ts
CHANGED
|
@@ -2,9 +2,13 @@ import { type ParserInputCompanion } from './parserInputCompanion.js';
|
|
|
2
2
|
import { type InputReaderState } from './inputReaderState.js';
|
|
3
3
|
export type InputReader<Sequence, Element> = {
|
|
4
4
|
get position(): number;
|
|
5
|
+
get furthestReadPosition(): number;
|
|
6
|
+
get furthestPeekedPosition(): number;
|
|
5
7
|
peek(offset: number): Promise<Element | undefined>;
|
|
6
8
|
peekSequence(start: number, end: number): Promise<Sequence | undefined>;
|
|
7
9
|
skip(offset: number): void;
|
|
10
|
+
updateFurthestReadPosition(position: number): void;
|
|
11
|
+
updateFurthestPeekedPosition(position: number): void;
|
|
8
12
|
lookahead(): InputReader<Sequence, Element>;
|
|
9
13
|
toInputReaderState(): InputReaderState<Sequence>;
|
|
10
14
|
};
|
|
@@ -13,6 +17,8 @@ export declare class InputReaderImplementation<Sequence, Element> implements Inp
|
|
|
13
17
|
private readonly _inputAsyncIterator;
|
|
14
18
|
private readonly _id;
|
|
15
19
|
private _position;
|
|
20
|
+
private _furthestReadPosition;
|
|
21
|
+
private _furthestPeekedPosition;
|
|
16
22
|
private _uncommitedSkipOffset;
|
|
17
23
|
private _inputAsyncIteratorDone;
|
|
18
24
|
private readonly _promiseMutex;
|
|
@@ -20,6 +26,10 @@ export declare class InputReaderImplementation<Sequence, Element> implements Inp
|
|
|
20
26
|
constructor(_parserInputCompanion: ParserInputCompanion<Sequence, Element>, _inputAsyncIterator: AsyncIterator<Sequence>);
|
|
21
27
|
get [Symbol.toStringTag](): string;
|
|
22
28
|
get position(): number;
|
|
29
|
+
get furthestReadPosition(): number;
|
|
30
|
+
get furthestPeekedPosition(): number;
|
|
31
|
+
updateFurthestReadPosition(position: number): void;
|
|
32
|
+
updateFurthestPeekedPosition(position: number): void;
|
|
23
33
|
peek(offset: number): Promise<Element | undefined>;
|
|
24
34
|
peekSequence(start: number, end: number): Promise<Sequence | undefined>;
|
|
25
35
|
skip(offset: number): void;
|
package/build/inputReader.js
CHANGED
|
@@ -8,6 +8,8 @@ export class InputReaderImplementation {
|
|
|
8
8
|
_inputAsyncIterator;
|
|
9
9
|
_id = inputReaderId++;
|
|
10
10
|
_position = 0;
|
|
11
|
+
_furthestReadPosition = 0;
|
|
12
|
+
_furthestPeekedPosition = 0;
|
|
11
13
|
_uncommitedSkipOffset = 0;
|
|
12
14
|
_inputAsyncIteratorDone = false;
|
|
13
15
|
_promiseMutex = new PromiseMutex();
|
|
@@ -27,8 +29,21 @@ export class InputReaderImplementation {
|
|
|
27
29
|
get position() {
|
|
28
30
|
return this._position;
|
|
29
31
|
}
|
|
32
|
+
get furthestReadPosition() {
|
|
33
|
+
return this._furthestReadPosition;
|
|
34
|
+
}
|
|
35
|
+
get furthestPeekedPosition() {
|
|
36
|
+
return this._furthestPeekedPosition;
|
|
37
|
+
}
|
|
38
|
+
updateFurthestReadPosition(position) {
|
|
39
|
+
this._furthestReadPosition = Math.max(this._furthestReadPosition, position);
|
|
40
|
+
}
|
|
41
|
+
updateFurthestPeekedPosition(position) {
|
|
42
|
+
this._furthestPeekedPosition = Math.max(this._furthestPeekedPosition, position);
|
|
43
|
+
}
|
|
30
44
|
async peek(offset) {
|
|
31
45
|
parserImplementationInvariant(offset >= 0, 'offset >= 0');
|
|
46
|
+
this.updateFurthestPeekedPosition(this._position + offset);
|
|
32
47
|
offset += this._uncommitedSkipOffset;
|
|
33
48
|
const element = this._sequenceBuffer.peek(offset);
|
|
34
49
|
if (element !== undefined) {
|
|
@@ -59,6 +74,9 @@ export class InputReaderImplementation {
|
|
|
59
74
|
parserImplementationInvariant(end >= start, 'end (%s) >= start (%s)', start, end);
|
|
60
75
|
parserImplementationInvariant(Number.isSafeInteger(start), 'start (%s) is not a safe integer', start);
|
|
61
76
|
parserImplementationInvariant(Number.isSafeInteger(end), 'end (%s) is not a safe integer', end);
|
|
77
|
+
if (end > start) {
|
|
78
|
+
this.updateFurthestPeekedPosition(this._position + end - 1);
|
|
79
|
+
}
|
|
62
80
|
start += this._uncommitedSkipOffset;
|
|
63
81
|
end += this._uncommitedSkipOffset;
|
|
64
82
|
const sequence = this._sequenceBuffer.peekSequence(start, end);
|
|
@@ -74,6 +92,7 @@ export class InputReaderImplementation {
|
|
|
74
92
|
skip(offset) {
|
|
75
93
|
parserImplementationInvariant(offset >= 0, 'offset >= 0');
|
|
76
94
|
this._position += offset;
|
|
95
|
+
this.updateFurthestReadPosition(this._position);
|
|
77
96
|
if (this._promiseMutex.isLocked) {
|
|
78
97
|
this._uncommitedSkipOffset += offset;
|
|
79
98
|
}
|
|
@@ -113,21 +132,38 @@ class InputReaderLookaheadImplementation {
|
|
|
113
132
|
get position() {
|
|
114
133
|
return this._initialInputReaderPosition + this._offset;
|
|
115
134
|
}
|
|
135
|
+
get furthestReadPosition() {
|
|
136
|
+
return this._inputReader.furthestReadPosition;
|
|
137
|
+
}
|
|
138
|
+
get furthestPeekedPosition() {
|
|
139
|
+
return this._inputReader.furthestPeekedPosition;
|
|
140
|
+
}
|
|
141
|
+
updateFurthestReadPosition(position) {
|
|
142
|
+
this._inputReader.updateFurthestReadPosition(position);
|
|
143
|
+
}
|
|
144
|
+
updateFurthestPeekedPosition(position) {
|
|
145
|
+
this._inputReader.updateFurthestPeekedPosition(position);
|
|
146
|
+
}
|
|
116
147
|
async peek(offset) {
|
|
117
148
|
const inputReaderMovedForward = this._inputReader.position - this._initialInputReaderPosition;
|
|
118
149
|
this._initialInputReaderPosition = this._inputReader.position;
|
|
119
150
|
this._offset -= inputReaderMovedForward;
|
|
151
|
+
this.updateFurthestPeekedPosition(this.position + offset);
|
|
120
152
|
return this._inputReader.peek(this._offset + offset);
|
|
121
153
|
}
|
|
122
154
|
async peekSequence(start, end) {
|
|
123
155
|
const inputReaderMovedForward = this._inputReader.position - this._initialInputReaderPosition;
|
|
124
156
|
this._initialInputReaderPosition = this._inputReader.position;
|
|
125
157
|
this._offset -= inputReaderMovedForward;
|
|
158
|
+
if (end > start) {
|
|
159
|
+
this.updateFurthestPeekedPosition(this.position + end - 1);
|
|
160
|
+
}
|
|
126
161
|
return this._inputReader.peekSequence(this._offset + start, this._offset + end);
|
|
127
162
|
}
|
|
128
163
|
skip(offset) {
|
|
129
164
|
parserImplementationInvariant(offset >= 0, 'offset >= 0');
|
|
130
165
|
this._offset += offset;
|
|
166
|
+
this.updateFurthestReadPosition(this.position);
|
|
131
167
|
}
|
|
132
168
|
lookahead() {
|
|
133
169
|
const lookahead = new InputReaderLookaheadImplementation(this._inputReader);
|