@futpib/parser 1.0.0 → 1.0.2
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/build/allSettledStream.js +32 -14
- package/build/allSettledStream.test.js +32 -0
- package/build/androidPackage.d.ts +39 -0
- package/build/androidPackageParser.d.ts +17 -0
- package/build/androidPackageParser.js +183 -0
- package/build/{apkParser.test.js → androidPackageParser.test.js} +7 -7
- package/build/androidPackageUnparser.d.ts +4 -0
- package/build/androidPackageUnparser.js +90 -0
- package/build/androidPackageUnparser.test.js +26 -0
- package/build/arbitrarilySlicedAsyncInterable.d.ts +3 -1
- package/build/arbitrarilySlicedAsyncInterable.js +3 -3
- package/build/arbitraryFileSystemEntry.js +1 -1
- package/build/arbitraryZip.d.ts +1 -1
- package/build/arbitraryZip.js +13 -19
- package/build/arbitraryZipPermissions.d.ts +1 -8
- package/build/arbitraryZipPermissions.js +1 -16
- package/build/arbitraryZipStream.d.ts +1 -1
- package/build/arbitraryZipStream.js +3 -3
- package/build/arrayParser.d.ts +1 -1
- package/build/arrayParser.js +2 -2
- package/build/arrayParser.test.js +4 -4
- package/build/arrayUnparser.d.ts +2 -0
- package/build/arrayUnparser.js +8 -0
- package/build/backsmali.d.ts +1 -0
- package/build/backsmali.js +22 -0
- package/build/bsonParser.js +6 -2
- package/build/bsonParser.test.js +2 -2
- package/build/{parserInvariant.d.ts → customInvariant.d.ts} +1 -1
- package/build/{parserInvariant.js → customInvariant.js} +1 -1
- package/build/dalvikBytecodeParser/formatParsers.d.ts +97 -0
- package/build/dalvikBytecodeParser/formatParsers.js +169 -0
- package/build/dalvikBytecodeParser.d.ts +107 -0
- package/build/dalvikBytecodeParser.js +836 -0
- package/build/dalvikExecutable.d.ts +158 -0
- package/build/dalvikExecutable.js +20 -0
- package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +4 -0
- package/build/dalvikExecutableParser/stringSyntaxParser.js +76 -0
- package/build/dalvikExecutableParser/typeParsers.d.ts +10 -0
- package/build/dalvikExecutableParser/typeParsers.js +34 -0
- package/build/dalvikExecutableParser/typedNumbers.d.ts +90 -0
- package/build/dalvikExecutableParser/typedNumbers.js +19 -0
- package/build/dalvikExecutableParser.d.ts +5 -0
- package/build/dalvikExecutableParser.js +1439 -0
- package/build/dalvikExecutableParser.test.js +70 -0
- package/build/dalvikExecutableParserAgainstSmaliParser.test.js +298 -0
- package/build/debugLogInputParser.d.ts +4 -0
- package/build/debugLogInputParser.js +16 -0
- package/build/debugLogParser.d.ts +1 -1
- package/build/debugLogParser.js +15 -4
- package/build/disjunctionParser.d.ts +2 -1
- package/build/disjunctionParser.js +4 -2
- package/build/elementParser.d.ts +2 -2
- package/build/elementParser.js +1 -1
- package/build/elementTerminatedArrayParser.d.ts +3 -0
- package/build/elementTerminatedArrayParser.js +18 -0
- package/build/elementTerminatedArrayParser.test.js +52 -0
- package/build/elementTerminatedSequenceArrayParser.d.ts +3 -0
- package/build/elementTerminatedSequenceArrayParser.js +32 -0
- package/build/elementTerminatedSequenceArrayParser.test.js +34 -0
- package/build/elementTerminatedSequenceParser.d.ts +3 -0
- package/build/elementTerminatedSequenceParser.js +27 -0
- package/build/elementTerminatedSequenceParser.test.js +34 -0
- package/build/endOfInputParser.d.ts +2 -2
- package/build/exactElementParser.d.ts +1 -1
- package/build/exactElementParser.js +10 -5
- package/build/exactSequenceParser.d.ts +2 -1
- package/build/exactSequenceParser.js +12 -2
- package/build/fetchCid.d.ts +1 -0
- package/build/fetchCid.js +107 -0
- package/build/fixedLengthSequenceParser.d.ts +1 -0
- package/build/fixedLengthSequenceParser.js +18 -1
- package/build/fixedLengthSequenceParser.test.js +41 -0
- package/build/hasExecutable.d.ts +1 -0
- package/build/hasExecutable.js +8 -0
- package/build/highResolutionTimer.d.ts +16 -0
- package/build/highResolutionTimer.js +42 -0
- package/build/index.d.ts +5 -2
- package/build/index.js +3 -0
- package/build/inputReader.d.ts +14 -3
- package/build/inputReader.js +43 -6
- package/build/inputReader.test.js +172 -7
- package/build/inputReaderState.d.ts +10 -0
- package/build/inputReaderState.js +16 -0
- package/build/inspect.d.ts +1 -0
- package/build/inspect.js +7 -0
- package/build/javaKeyStoreParser.d.ts +2 -0
- package/build/javaKeyStoreParser.js +67 -0
- package/build/javaKeyStoreParser.test.d.ts +1 -0
- package/build/javaKeyStoreParser.test.js +16 -0
- package/build/jsonParser.d.ts +2 -0
- package/build/jsonParser.js +13 -15
- package/build/jsonParser.test.js +2 -2
- package/build/leb128Parser.d.ts +7 -0
- package/build/leb128Parser.js +82 -0
- package/build/leb128Parser.test.d.ts +1 -0
- package/build/leb128Parser.test.js +107 -0
- package/build/listParser.d.ts +1 -1
- package/build/listParser.js +5 -5
- package/build/lookaheadParser.d.ts +2 -0
- package/build/lookaheadParser.js +14 -0
- package/build/{negativeLookahead.d.ts → negativeLookaheadParser.d.ts} +1 -1
- package/build/negativeLookaheadParser.js +24 -0
- package/build/negativeLookaheadParser.test.d.ts +1 -0
- package/build/negativeLookaheadParser.test.js +30 -0
- package/build/nonEmptyArrayParser.d.ts +2 -0
- package/build/nonEmptyArrayParser.js +32 -0
- package/build/nonEmptyArrayParser.test.d.ts +1 -0
- package/build/nonEmptyArrayParser.test.js +16 -0
- package/build/optionalParser.d.ts +1 -1
- package/build/optionalParser.js +2 -2
- package/build/parser.d.ts +13 -4
- package/build/parser.js +67 -32
- package/build/parser.test.js +94 -27
- package/build/parserAccessorParser.d.ts +1 -1
- package/build/parserAccessorParser.js +9 -1
- package/build/parserConsumedSequenceParser.d.ts +2 -0
- package/build/parserConsumedSequenceParser.js +22 -0
- package/build/parserContext.d.ts +20 -6
- package/build/parserContext.js +70 -40
- package/build/parserContext.test.js +34 -7
- package/build/parserCreatorCompose.d.ts +4 -3
- package/build/parserCreatorCompose.js +9 -3
- package/build/parserError.d.ts +6 -0
- package/build/parserError.js +6 -6
- package/build/parserImplementationInvariant.d.ts +1 -1
- package/build/parserImplementationInvariant.js +2 -2
- package/build/parserInputCompanion.d.ts +35 -0
- package/build/parserInputCompanion.js +68 -0
- package/build/promiseCompose.d.ts +1 -1
- package/build/promiseCompose.js +12 -1
- package/build/promiseSettled.d.ts +1 -0
- package/build/promiseSettled.js +4 -0
- package/build/quantifierParser.d.ts +2 -0
- package/build/quantifierParser.js +17 -0
- package/build/separatedArrayParser.d.ts +2 -0
- package/build/separatedArrayParser.js +39 -0
- package/build/separatedArrayParser.test.d.ts +1 -0
- package/build/separatedArrayParser.test.js +21 -0
- package/build/sequenceBuffer.d.ts +13 -3
- package/build/sequenceBuffer.js +60 -8
- package/build/sequenceBuffer.test.js +59 -2
- package/build/sequenceTerminatedSequenceParser.d.ts +5 -0
- package/build/sequenceTerminatedSequenceParser.js +32 -0
- package/build/sequenceTerminatedSequenceParser.test.d.ts +1 -0
- package/build/sequenceTerminatedSequenceParser.test.js +37 -0
- package/build/sequenceUnparser.d.ts +2 -0
- package/build/sequenceUnparser.js +6 -0
- package/build/skipParser.d.ts +1 -1
- package/build/skipParser.js +4 -2
- package/build/skipToParser.d.ts +2 -0
- package/build/skipToParser.js +11 -0
- package/build/sliceBoundedParser.d.ts +2 -2
- package/build/sliceBoundedParser.js +8 -3
- package/build/sliceBoundedParser.test.js +37 -3
- package/build/smali.d.ts +1 -0
- package/build/smali.js +17 -0
- package/build/smaliParser.d.ts +12 -0
- package/build/smaliParser.js +656 -0
- package/build/smaliParser.test.d.ts +1 -0
- package/build/smaliParser.test.js +115 -0
- package/build/terminatedArrayParser.d.ts +4 -2
- package/build/terminatedArrayParser.js +82 -5
- package/build/terminatedArrayParser.test.d.ts +1 -0
- package/build/terminatedArrayParser.test.js +131 -0
- package/build/toAsyncIterable.d.ts +1 -0
- package/build/toAsyncIterable.js +7 -0
- package/build/toAsyncIterator.d.ts +1 -0
- package/build/toAsyncIterator.js +33 -0
- package/build/tupleParser.d.ts +4 -0
- package/build/tupleParser.js +1 -5
- package/build/uint8Array.d.ts +1 -0
- package/build/uint8Array.js +7 -0
- package/build/unionParser.d.ts +2 -1
- package/build/unionParser.js +27 -12
- package/build/unionParser.test.d.ts +1 -0
- package/build/unionParser.test.js +60 -0
- package/build/unparser.d.ts +8 -0
- package/build/unparser.js +104 -0
- package/build/unparser.test.d.ts +1 -0
- package/build/unparser.test.js +150 -0
- package/build/unparserContext.d.ts +31 -0
- package/build/unparserContext.js +74 -0
- package/build/unparserError.d.ts +9 -0
- package/build/unparserError.js +9 -0
- package/build/unparserImplementationInvariant.d.ts +2 -0
- package/build/unparserImplementationInvariant.js +5 -0
- package/build/unparserOutputCompanion.d.ts +15 -0
- package/build/unparserOutputCompanion.js +13 -0
- package/build/zip.d.ts +9 -17
- package/build/zipParser.d.ts +20 -12
- package/build/zipParser.js +83 -71
- package/build/zipParser.test.js +2 -7
- package/build/zipUnparser.d.ts +8 -0
- package/build/zipUnparser.js +200 -0
- package/build/zipUnparser.test.d.ts +1 -0
- package/build/zipUnparser.test.js +80 -0
- package/package.json +26 -8
- package/src/allSettledStream.test.ts +40 -0
- package/src/allSettledStream.ts +47 -15
- package/src/androidPackage.ts +48 -0
- package/src/{apkParser.test.ts → androidPackageParser.test.ts} +7 -8
- package/src/androidPackageParser.test.ts.md +271 -0
- package/src/androidPackageParser.test.ts.snap +0 -0
- package/src/androidPackageParser.ts +440 -0
- package/src/androidPackageUnparser.test.ts +36 -0
- package/src/androidPackageUnparser.ts +120 -0
- package/src/arbitrarilySlicedAsyncInterable.ts +7 -2
- package/src/arbitraryFileSystemEntry.ts +2 -4
- package/src/arbitraryZip.ts +20 -27
- package/src/arbitraryZipPermissions.ts +0 -25
- package/src/arbitraryZipStream.ts +4 -4
- package/src/arrayParser.test.ts +4 -4
- package/src/arrayParser.ts +3 -2
- package/src/arrayUnparser.ts +13 -0
- package/src/backsmali.ts +30 -0
- package/src/bsonParser.test.ts +2 -2
- package/src/bsonParser.ts +16 -5
- package/src/{parserInvariant.ts → customInvariant.ts} +2 -2
- package/src/dalvikBytecodeParser/formatParsers.ts +421 -0
- package/src/dalvikBytecodeParser.ts +2074 -0
- package/src/dalvikExecutable.ts +220 -0
- package/src/dalvikExecutableParser/stringSyntaxParser.ts +145 -0
- package/src/dalvikExecutableParser/typeParsers.ts +65 -0
- package/src/dalvikExecutableParser/typedNumbers.ts +57 -0
- package/src/dalvikExecutableParser.test.ts +89 -0
- package/src/dalvikExecutableParser.test.ts.md +634 -0
- package/src/dalvikExecutableParser.test.ts.snap +0 -0
- package/src/dalvikExecutableParser.ts +2768 -0
- package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +346 -0
- package/src/debugLogInputParser.ts +28 -0
- package/src/debugLogParser.ts +20 -4
- package/src/disjunctionParser.ts +10 -5
- package/src/elementParser.ts +3 -3
- package/src/elementTerminatedArrayParser.test.ts +99 -0
- package/src/elementTerminatedArrayParser.ts +31 -0
- package/src/elementTerminatedSequenceArrayParser.test.ts +54 -0
- package/src/elementTerminatedSequenceArrayParser.ts +52 -0
- package/src/elementTerminatedSequenceParser.test.ts +54 -0
- package/src/elementTerminatedSequenceParser.ts +43 -0
- package/src/endOfInputParser.ts +4 -4
- package/src/exactElementParser.ts +18 -12
- package/src/exactSequenceParser.ts +24 -3
- package/src/fetchCid.ts +125 -0
- package/src/fixedLengthSequenceParser.test.ts +77 -0
- package/src/fixedLengthSequenceParser.ts +28 -1
- package/src/hasExecutable.ts +11 -0
- package/src/highResolutionTimer.ts +49 -0
- package/src/index.ts +15 -2
- package/src/inputReader.test.ts +216 -7
- package/src/inputReader.ts +80 -5
- package/src/inputReaderState.ts +33 -0
- package/src/inspect.ts +9 -0
- package/src/javaKeyStore.ts +0 -0
- package/src/javaKeyStoreParser.test.ts +22 -0
- package/src/javaKeyStoreParser.test.ts.md +103 -0
- package/src/javaKeyStoreParser.test.ts.snap +0 -0
- package/src/javaKeyStoreParser.ts +136 -0
- package/src/jsonParser.test.ts +2 -2
- package/src/jsonParser.ts +23 -34
- package/src/leb128Parser.test.ts +171 -0
- package/src/leb128Parser.ts +125 -0
- package/src/listParser.ts +6 -6
- package/src/lookaheadParser.ts +19 -0
- package/src/negativeLookaheadParser.test.ts +53 -0
- package/src/negativeLookaheadParser.ts +36 -0
- package/src/nonEmptyArrayParser.test.ts +20 -0
- package/src/nonEmptyArrayParser.ts +44 -0
- package/src/optionalParser.ts +4 -3
- package/src/parser.test.ts +148 -27
- package/src/parser.test.ts.md +21 -21
- package/src/parser.test.ts.snap +0 -0
- package/src/parser.ts +153 -49
- package/src/parserAccessorParser.ts +12 -2
- package/src/parserConsumedSequenceParser.ts +29 -0
- package/src/parserContext.test.ts +38 -7
- package/src/parserContext.ts +127 -51
- package/src/parserCreatorCompose.ts +25 -7
- package/src/parserError.ts +9 -6
- package/src/parserImplementationInvariant.ts +2 -2
- package/src/parserInputCompanion.ts +102 -0
- package/src/promiseCompose.ts +17 -3
- package/src/promiseSettled.ts +6 -0
- package/src/quantifierParser.ts +25 -0
- package/src/separatedArrayParser.test.ts +34 -0
- package/src/separatedArrayParser.ts +55 -0
- package/src/sequenceBuffer.test.ts +72 -2
- package/src/sequenceBuffer.ts +93 -7
- package/src/sequenceTerminatedSequenceParser.test.ts +60 -0
- package/src/sequenceTerminatedSequenceParser.ts +62 -0
- package/src/sequenceUnparser.ts +9 -0
- package/src/skipParser.ts +7 -5
- package/src/skipToParser.ts +16 -0
- package/src/sliceBoundedParser.test.ts +45 -3
- package/src/sliceBoundedParser.ts +21 -3
- package/src/smali.ts +24 -0
- package/src/smaliParser.test.ts +132 -0
- package/src/smaliParser.test.ts.md +2320 -0
- package/src/smaliParser.test.ts.snap +0 -0
- package/src/smaliParser.ts +1166 -0
- package/src/terminatedArrayParser.test.ts +258 -0
- package/src/terminatedArrayParser.ts +111 -6
- package/src/toAsyncIterable.ts +7 -0
- package/src/toAsyncIterator.ts +48 -0
- package/src/tupleParser.ts +8 -5
- package/src/uint8Array.ts +10 -0
- package/src/unionParser.test.ts +79 -0
- package/src/unionParser.ts +44 -16
- package/src/unparser.test.ts +221 -0
- package/src/unparser.ts +209 -0
- package/src/unparserContext.ts +127 -0
- package/src/unparserError.ts +12 -0
- package/src/unparserImplementationInvariant.ts +6 -0
- package/src/unparserOutputCompanion.ts +24 -0
- package/src/zip.ts +10 -22
- package/src/zipParser.test.ts +2 -8
- package/src/zipParser.ts +223 -146
- package/src/zipUnparser.test.ts +119 -0
- package/src/zipUnparser.ts +300 -0
- package/build/apk.d.ts +0 -13
- package/build/apkParser.d.ts +0 -3
- package/build/apkParser.js +0 -135
- package/build/arbitraryDosDate.d.ts +0 -2
- package/build/arbitraryDosDate.js +0 -8
- package/build/arbitraryZipEntry.d.ts +0 -3
- package/build/arbitraryZipEntry.js +0 -26
- package/build/createDisjunctionParser.d.ts +0 -2
- package/build/createDisjunctionParser.js +0 -47
- package/build/createExactParser.d.ts +0 -2
- package/build/createExactParser.js +0 -12
- package/build/createSequentialUnionParser.d.ts +0 -2
- package/build/createSequentialUnionParser.js +0 -69
- package/build/fixedLengthChunkParser.d.ts +0 -2
- package/build/fixedLengthChunkParser.js +0 -12
- package/build/fixedLengthParser.d.ts +0 -2
- package/build/fixedLengthParser.js +0 -12
- package/build/inputChunkBuffer.d.ts +0 -15
- package/build/inputChunkBuffer.js +0 -40
- package/build/inputChunkBuffer.test.js +0 -34
- package/build/inputCompanion.d.ts +0 -18
- package/build/inputCompanion.js +0 -28
- package/build/invariantDefined.d.ts +0 -1
- package/build/invariantDefined.js +0 -5
- package/build/invariantIdentity.d.ts +0 -3
- package/build/invariantIdentity.js +0 -5
- package/build/jsonParser2.d.ts +0 -3
- package/build/jsonParser2.js +0 -52
- package/build/jsonParser2.test.js +0 -22
- package/build/negativeLookahead.js +0 -20
- package/build/parserCompose.d.ts +0 -3
- package/build/parserCompose.js +0 -7
- package/build/parserImplementationInvariantInvariant.d.ts +0 -3
- package/build/parserImplementationInvariantInvariant.js +0 -15
- package/build/promiseFish.d.ts +0 -1
- package/build/promiseFish.js +0 -3
- package/build/sequenceParser.d.ts +0 -3
- package/build/sequenceParser.js +0 -10
- package/build/terminatedSequenceParser.d.ts +0 -2
- package/build/terminatedSequenceParser.js +0 -24
- package/build/zipEntry.d.ts +0 -28
- package/build/zipFile.d.ts +0 -32
- package/build/zipFileEntry.d.ts +0 -6
- package/src/apk.ts +0 -16
- package/src/apkParser.test.ts.md +0 -268
- package/src/apkParser.test.ts.snap +0 -0
- package/src/apkParser.ts +0 -327
- package/src/inputCompanion.ts +0 -43
- package/src/invariantDefined.ts +0 -6
- package/src/invariantIdentity.ts +0 -8
- package/src/negativeLookahead.ts +0 -26
- /package/build/{apk.js → androidPackage.js} +0 -0
- /package/build/{apkParser.test.d.ts → androidPackageParser.test.d.ts} +0 -0
- /package/build/{arbitraryDosPermissions.d.ts → androidPackageUnparser.test.d.ts} +0 -0
- /package/build/{arbitraryDosPermissions.js → dalvikExecutableParser.test.d.ts} +0 -0
- /package/build/{inputChunkBuffer.test.d.ts → dalvikExecutableParserAgainstSmaliParser.test.d.ts} +0 -0
- /package/build/{jsonParser2.test.d.ts → elementTerminatedArrayParser.test.d.ts} +0 -0
- /package/build/{parserParsingInvariant.d.ts → elementTerminatedSequenceArrayParser.test.d.ts} +0 -0
- /package/build/{parserParsingInvariant.js → elementTerminatedSequenceParser.test.d.ts} +0 -0
- /package/build/{zipEntry.js → fixedLengthSequenceParser.test.d.ts} +0 -0
- /package/build/{zipFile.js → javaKeyStore.d.ts} +0 -0
- /package/build/{zipFileEntry.js → javaKeyStore.js} +0 -0
package/src/parserContext.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* eslint-disable prefer-arrow-callback */
|
|
2
|
+
|
|
3
|
+
import { type ParserInputCompanion } from './parserInputCompanion.js';
|
|
3
4
|
import { type InputReader } from './inputReader.js';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
type ParserParsingFailedError, ParserUnexpectedEndOfInputError, ParserParsingInvariantError, ParserParsingJoinNoneError, ParserParsingJoinAllError, ParserParsingJoinDeepestError, ParserParsingJoinFurthestError,
|
|
7
|
+
} from './parserError.js';
|
|
8
|
+
import { type RunParserOptions } from './parser.js';
|
|
9
|
+
import { type Falsy, customInvariant, type ValueOrAccessor } from './customInvariant.js';
|
|
10
|
+
import { parserImplementationInvariant } from './parserImplementationInvariant.js';
|
|
7
11
|
|
|
8
12
|
type LookaheadOptions = {
|
|
9
13
|
debugName?: string;
|
|
@@ -17,14 +21,21 @@ type ParserContextOptions<Sequence, Element> =
|
|
|
17
21
|
|
|
18
22
|
export type ParserContext<Sequence, Element> = {
|
|
19
23
|
from(elements: Element[]): Sequence;
|
|
24
|
+
concat(sequences: Sequence[]): Sequence;
|
|
20
25
|
length(sequence: Sequence): number;
|
|
21
26
|
at(sequence: Sequence, index: number): Element | undefined;
|
|
27
|
+
subsequence(sequence: Sequence, start: number, end: number): Sequence;
|
|
28
|
+
indexOf(sequence: Sequence, element: Element, fromIndex?: number): number;
|
|
29
|
+
indexOfSubsequence(sequence: Sequence, subsequence: Sequence, fromIndex?: number): number;
|
|
30
|
+
equals(sequenceA: Sequence, sequenceB: Sequence): boolean;
|
|
22
31
|
|
|
23
32
|
get position(): number;
|
|
24
33
|
peek(offset: number): Promise<Element | undefined>;
|
|
34
|
+
peekSequence(start: number, end: number): Promise<Sequence | undefined>;
|
|
25
35
|
skip(offset: number): void;
|
|
26
36
|
|
|
27
37
|
read(offset: number): Promise<Element>;
|
|
38
|
+
readSequence(start: number, end: number): Promise<Sequence>;
|
|
28
39
|
|
|
29
40
|
lookahead(options?: LookaheadOptions): ParserContext<Sequence, Element>;
|
|
30
41
|
unlookahead(): void;
|
|
@@ -43,7 +54,7 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
43
54
|
private _exclusiveChildParserContext: ParserContext<Sequence, Element> | undefined = undefined;
|
|
44
55
|
|
|
45
56
|
constructor(
|
|
46
|
-
private readonly
|
|
57
|
+
private readonly _parserInputCompanion: ParserInputCompanion<Sequence, Element>,
|
|
47
58
|
private _inputReader: InputReader<Sequence, Element>,
|
|
48
59
|
private _parentParserContext: ParserContextImplementation<Sequence, Element> | undefined = undefined,
|
|
49
60
|
private readonly _options: ParserContextOptions<Sequence, Element>,
|
|
@@ -65,15 +76,35 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
65
76
|
}
|
|
66
77
|
|
|
67
78
|
from(elements: Element[]): Sequence {
|
|
68
|
-
return this.
|
|
79
|
+
return this._parserInputCompanion.from(elements);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
concat(sequences: Sequence[]): Sequence {
|
|
83
|
+
return this._parserInputCompanion.concat(sequences);
|
|
69
84
|
}
|
|
70
85
|
|
|
71
86
|
length(sequence: Sequence): number {
|
|
72
|
-
return this.
|
|
87
|
+
return this._parserInputCompanion.length(sequence);
|
|
73
88
|
}
|
|
74
89
|
|
|
75
90
|
at(sequence: Sequence, index: number): Element | undefined {
|
|
76
|
-
return this.
|
|
91
|
+
return this._parserInputCompanion.at(sequence, index);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
subsequence(sequence: Sequence, start: number, end: number): Sequence {
|
|
95
|
+
return this._parserInputCompanion.subsequence(sequence, start, end);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
indexOf(sequence: Sequence, element: Element, fromIndex?: number): number {
|
|
99
|
+
return this._parserInputCompanion.indexOf(sequence, element, fromIndex);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
indexOfSubsequence(sequence: Sequence, subsequence: Sequence, fromIndex?: number): number {
|
|
103
|
+
return this._parserInputCompanion.indexOfSubsequence(sequence, subsequence, fromIndex);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
equals(sequenceA: Sequence, sequenceB: Sequence): boolean {
|
|
107
|
+
return this._parserInputCompanion.equals(sequenceA, sequenceB);
|
|
77
108
|
}
|
|
78
109
|
|
|
79
110
|
get position() {
|
|
@@ -91,6 +122,39 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
91
122
|
return this._inputReader.peek(offset);
|
|
92
123
|
}
|
|
93
124
|
|
|
125
|
+
async peekSequence(start: number, end: number): Promise<Sequence | undefined> {
|
|
126
|
+
if (
|
|
127
|
+
this._options.sliceEnd !== undefined
|
|
128
|
+
&& (this.position + end - 1) >= this._options.sliceEnd
|
|
129
|
+
) {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
parserImplementationInvariant(
|
|
134
|
+
start >= 0,
|
|
135
|
+
'start (%s) >= 0',
|
|
136
|
+
start,
|
|
137
|
+
);
|
|
138
|
+
parserImplementationInvariant(
|
|
139
|
+
end >= start,
|
|
140
|
+
'end (%s) >= start (%s)',
|
|
141
|
+
start,
|
|
142
|
+
end,
|
|
143
|
+
);
|
|
144
|
+
parserImplementationInvariant(
|
|
145
|
+
Number.isSafeInteger(start),
|
|
146
|
+
'start (%d) is not a safe integer',
|
|
147
|
+
start,
|
|
148
|
+
);
|
|
149
|
+
parserImplementationInvariant(
|
|
150
|
+
Number.isSafeInteger(end),
|
|
151
|
+
'end (%d) is not a safe integer',
|
|
152
|
+
end,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
return this._inputReader.peekSequence(start, end);
|
|
156
|
+
}
|
|
157
|
+
|
|
94
158
|
skip(offset: number) {
|
|
95
159
|
this._inputReader.skip(offset);
|
|
96
160
|
}
|
|
@@ -107,22 +171,32 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
107
171
|
return element;
|
|
108
172
|
}
|
|
109
173
|
|
|
110
|
-
|
|
111
|
-
const
|
|
174
|
+
async readSequence(start: number, end: number): Promise<Sequence> {
|
|
175
|
+
const sequence = await this.peekSequence(start, end);
|
|
112
176
|
|
|
113
|
-
if (
|
|
114
|
-
|
|
177
|
+
if (sequence === undefined) {
|
|
178
|
+
throw new ParserUnexpectedEndOfInputError('', this._depth, this.position);
|
|
115
179
|
}
|
|
116
180
|
|
|
117
|
-
|
|
181
|
+
this.skip(end);
|
|
182
|
+
|
|
183
|
+
return sequence;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
lookahead(options: LookaheadOptions = {}): ParserContext<Sequence, Element> {
|
|
187
|
+
const lookaheadInputReader = this._inputReader.lookahead();
|
|
188
|
+
|
|
189
|
+
parserImplementationInvariant(
|
|
118
190
|
this.position === lookaheadInputReader.position,
|
|
119
191
|
'lookahead this.position (%s) === lookaheadInputReader.position (%s)',
|
|
120
192
|
this.position,
|
|
121
193
|
lookaheadInputReader.position,
|
|
122
194
|
);
|
|
123
195
|
|
|
124
|
-
const
|
|
125
|
-
|
|
196
|
+
const ParserContext = this._options.parserContextClass ?? ParserContextImplementation;
|
|
197
|
+
|
|
198
|
+
const lookaheadParserContext = new ParserContext<Sequence, Element>(
|
|
199
|
+
this._parserInputCompanion,
|
|
126
200
|
lookaheadInputReader,
|
|
127
201
|
this,
|
|
128
202
|
{
|
|
@@ -139,11 +213,7 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
139
213
|
},
|
|
140
214
|
);
|
|
141
215
|
|
|
142
|
-
|
|
143
|
-
debugger;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
invariant(
|
|
216
|
+
parserImplementationInvariant(
|
|
147
217
|
this.position === lookaheadParserContext.position,
|
|
148
218
|
'lookahead this.position (%s) === lookaheadParserContext.position (%s)',
|
|
149
219
|
this.position,
|
|
@@ -154,11 +224,14 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
154
224
|
}
|
|
155
225
|
|
|
156
226
|
unlookahead() {
|
|
157
|
-
|
|
158
|
-
|
|
227
|
+
const parentParserContext = parserImplementationInvariant(
|
|
228
|
+
this._parentParserContext,
|
|
229
|
+
'this._parentParserContext !== undefined',
|
|
230
|
+
);
|
|
231
|
+
parserImplementationInvariant(
|
|
159
232
|
(
|
|
160
|
-
|
|
161
|
-
||
|
|
233
|
+
parentParserContext._exclusiveChildParserContext === undefined
|
|
234
|
+
|| parentParserContext._exclusiveChildParserContext === this
|
|
162
235
|
),
|
|
163
236
|
[
|
|
164
237
|
'Parent\'s exclusive child must be undefined or this',
|
|
@@ -167,29 +240,29 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
167
240
|
'parent.exclusiveChild: %s',
|
|
168
241
|
].join('\n'),
|
|
169
242
|
this.toString(),
|
|
170
|
-
|
|
171
|
-
|
|
243
|
+
parentParserContext.toString(),
|
|
244
|
+
parentParserContext._exclusiveChildParserContext?.toString(),
|
|
172
245
|
);
|
|
173
|
-
|
|
174
|
-
|
|
246
|
+
parserImplementationInvariant(
|
|
247
|
+
parentParserContext.position <= this.position,
|
|
175
248
|
'unlookahead this._parentParserContext.position (%s) <= this.position (%s)',
|
|
176
|
-
|
|
249
|
+
parentParserContext.position,
|
|
177
250
|
this.position,
|
|
178
251
|
);
|
|
179
252
|
|
|
180
|
-
const offset = this._inputReader.position -
|
|
253
|
+
const offset = this._inputReader.position - parentParserContext._inputReader.position;
|
|
181
254
|
|
|
182
|
-
|
|
255
|
+
parentParserContext.skip(offset);
|
|
183
256
|
|
|
184
|
-
|
|
185
|
-
|
|
257
|
+
parserImplementationInvariant(
|
|
258
|
+
parentParserContext.position === this.position,
|
|
186
259
|
'unlookahead this._parentParserContext.position (%s) === this.position (%s)',
|
|
187
|
-
|
|
260
|
+
parentParserContext.position,
|
|
188
261
|
this.position,
|
|
189
262
|
);
|
|
190
263
|
|
|
191
|
-
this._inputReader =
|
|
192
|
-
|
|
264
|
+
this._inputReader = parentParserContext._inputReader;
|
|
265
|
+
parentParserContext._exclusiveChildParserContext = this;
|
|
193
266
|
|
|
194
267
|
if (this._exclusiveChildParserContext) {
|
|
195
268
|
this._exclusiveChildParserContext.unlookahead();
|
|
@@ -197,11 +270,14 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
197
270
|
}
|
|
198
271
|
|
|
199
272
|
dispose() {
|
|
200
|
-
|
|
201
|
-
|
|
273
|
+
const parentParserContext = parserImplementationInvariant(
|
|
274
|
+
this._parentParserContext,
|
|
275
|
+
'this._parentParserContext !== undefined',
|
|
276
|
+
);
|
|
277
|
+
parserImplementationInvariant(
|
|
202
278
|
(
|
|
203
|
-
|
|
204
|
-
||
|
|
279
|
+
parentParserContext._exclusiveChildParserContext === undefined
|
|
280
|
+
|| parentParserContext._exclusiveChildParserContext === this
|
|
205
281
|
),
|
|
206
282
|
[
|
|
207
283
|
'Parent\'s exclusive child must be undefined or this',
|
|
@@ -210,36 +286,36 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
210
286
|
'parent.exclusiveChild: %s',
|
|
211
287
|
].join('\n'),
|
|
212
288
|
this.toString(),
|
|
213
|
-
|
|
214
|
-
|
|
289
|
+
parentParserContext.toString(),
|
|
290
|
+
parentParserContext._exclusiveChildParserContext?.toString(),
|
|
215
291
|
);
|
|
216
292
|
|
|
217
|
-
|
|
293
|
+
parentParserContext._exclusiveChildParserContext = undefined;
|
|
218
294
|
this._parentParserContext = undefined;
|
|
219
295
|
}
|
|
220
296
|
|
|
221
297
|
invariant<T>(value: T, format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy> {
|
|
222
298
|
const parserContext = this;
|
|
223
299
|
|
|
224
|
-
return
|
|
300
|
+
return customInvariant(function (message: string) {
|
|
225
301
|
return new ParserParsingInvariantError(message, parserContext._depth, parserContext.position);
|
|
226
302
|
}, value, format, ...formatArguments);
|
|
227
303
|
}
|
|
228
304
|
|
|
229
305
|
invariantJoin<T>(value: T, childErrors: ParserParsingFailedError[], format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy> {
|
|
230
|
-
|
|
306
|
+
parserImplementationInvariant(childErrors.length > 0, 'childErrors.length > 0');
|
|
231
307
|
|
|
232
308
|
const errorJoinMode = this._options.errorJoinMode ?? 'none';
|
|
233
309
|
const parserContext = this;
|
|
234
310
|
|
|
235
311
|
if (errorJoinMode === 'none') {
|
|
236
|
-
return
|
|
312
|
+
return customInvariant(function (message: string) {
|
|
237
313
|
return new ParserParsingJoinNoneError(message, parserContext._depth, parserContext.position);
|
|
238
314
|
}, value, format, ...formatArguments);
|
|
239
315
|
}
|
|
240
316
|
|
|
241
317
|
if (errorJoinMode === 'furthest') {
|
|
242
|
-
return
|
|
318
|
+
return customInvariant(function (message: string) {
|
|
243
319
|
let furthestPosition = 0;
|
|
244
320
|
let furthestChildErrors: ParserParsingFailedError[] = [];
|
|
245
321
|
|
|
@@ -269,7 +345,7 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
269
345
|
}
|
|
270
346
|
|
|
271
347
|
if (errorJoinMode === 'deepest') {
|
|
272
|
-
return
|
|
348
|
+
return customInvariant(function (message: string) {
|
|
273
349
|
let deepestDepth = 0;
|
|
274
350
|
let deepestChildErrors: ParserParsingFailedError[] = [];
|
|
275
351
|
|
|
@@ -299,7 +375,7 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
299
375
|
}
|
|
300
376
|
|
|
301
377
|
if (errorJoinMode === 'all') {
|
|
302
|
-
return
|
|
378
|
+
return customInvariant(function (message: string) {
|
|
303
379
|
message += [
|
|
304
380
|
'',
|
|
305
381
|
'Child error stacks, indented:',
|
|
@@ -311,6 +387,6 @@ export class ParserContextImplementation<Sequence, Element> implements ParserCon
|
|
|
311
387
|
}, value, format, ...formatArguments);
|
|
312
388
|
}
|
|
313
389
|
|
|
314
|
-
|
|
390
|
+
return parserImplementationInvariant(false, 'Unsupported errorJoinMode: %s', errorJoinMode);
|
|
315
391
|
}
|
|
316
392
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import mem from 'mem';
|
|
2
|
+
import { type Parser } from './parser.js';
|
|
3
|
+
import { type DeriveSequenceElement } from './sequence.js';
|
|
3
4
|
|
|
4
5
|
export function parserCreatorCompose<
|
|
5
6
|
Arguments extends unknown[],
|
|
@@ -8,16 +9,33 @@ export function parserCreatorCompose<
|
|
|
8
9
|
Sequence,
|
|
9
10
|
Element = DeriveSequenceElement<Sequence>,
|
|
10
11
|
>(
|
|
11
|
-
f1: (...
|
|
12
|
+
f1: (...arguments_: Arguments) => Parser<OutputA, Sequence, Element>,
|
|
12
13
|
f2: (outputA: OutputA) => Parser<OutputB, Sequence, Element>,
|
|
13
|
-
): (...
|
|
14
|
-
|
|
15
|
-
const parserA = f1(...
|
|
14
|
+
): (...arguments_: Arguments) => Parser<OutputB, Sequence, Element> {
|
|
15
|
+
const parserCreatorComposedOuter: (...arguments_: Arguments) => Parser<OutputB, Sequence, Element> = (...arguments_) => {
|
|
16
|
+
const parserA = f1(...arguments_);
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
const parserCreatorComposedInner: Parser<OutputB, Sequence, Element> = async parserContext => {
|
|
18
19
|
const outputA = await parserA(parserContext);
|
|
19
20
|
const parserB = f2(outputA);
|
|
20
21
|
return parserB(parserContext);
|
|
21
22
|
};
|
|
23
|
+
|
|
24
|
+
return parserCreatorComposedInner;
|
|
22
25
|
};
|
|
26
|
+
|
|
27
|
+
return parserCreatorComposedOuter;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function parserCreatorComposeMem<
|
|
31
|
+
Arguments extends unknown[],
|
|
32
|
+
OutputA,
|
|
33
|
+
OutputB,
|
|
34
|
+
Sequence,
|
|
35
|
+
Element = DeriveSequenceElement<Sequence>,
|
|
36
|
+
>(
|
|
37
|
+
f1: (...arguments_: Arguments) => Parser<OutputA, Sequence, Element>,
|
|
38
|
+
f2: (outputA: OutputA) => Parser<OutputB, Sequence, Element>,
|
|
39
|
+
): (...arguments_: Arguments) => Parser<OutputB, Sequence, Element> {
|
|
40
|
+
return parserCreatorCompose(mem(f1), mem(f2));
|
|
23
41
|
}
|
package/src/parserError.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { InputReaderState } from "./inputReaderState.js";
|
|
1
2
|
|
|
2
3
|
export class ParserError extends Error {
|
|
3
4
|
name = 'ParserError';
|
|
5
|
+
|
|
6
|
+
public position: undefined | number = undefined;
|
|
7
|
+
public inputReaderSate: undefined | InputReaderState<unknown> = undefined;
|
|
4
8
|
}
|
|
5
9
|
|
|
6
10
|
export class ParserImplementationError extends ParserError {
|
|
@@ -18,12 +22,7 @@ export class ParserParsingFailedError extends ParserError {
|
|
|
18
22
|
public readonly depth: number,
|
|
19
23
|
public readonly position: number,
|
|
20
24
|
) {
|
|
21
|
-
super(
|
|
22
|
-
'(position: ',
|
|
23
|
-
position,
|
|
24
|
-
') ',
|
|
25
|
-
message,
|
|
26
|
-
].join(''));
|
|
25
|
+
super(message);
|
|
27
26
|
}
|
|
28
27
|
}
|
|
29
28
|
|
|
@@ -83,3 +82,7 @@ export class ParserParsingInvariantError extends ParserParsingFailedError {
|
|
|
83
82
|
export class ParserUnexpectedEndOfInputError extends ParserParsingFailedError {
|
|
84
83
|
name = 'ParserUnexpectedEndOfInputError';
|
|
85
84
|
}
|
|
85
|
+
|
|
86
|
+
export class ParserUnexpectedRemainingInputError extends ParserParsingFailedError {
|
|
87
|
+
name = 'ParserUnexpectedRemainingInputError';
|
|
88
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ParserImplementationInvariantError } from './parserError.js';
|
|
2
|
-
import { type Falsy,
|
|
2
|
+
import { type Falsy, customInvariant, type ValueOrAccessor } from './customInvariant.js';
|
|
3
3
|
|
|
4
4
|
export function parserImplementationInvariant<T>(value: T, format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy> {
|
|
5
|
-
return
|
|
5
|
+
return customInvariant(ParserImplementationInvariantError, value, format, ...formatArguments);
|
|
6
6
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
|
|
2
|
+
export type ParserInputCompanion<Sequence, Element> = {
|
|
3
|
+
is(value: unknown): value is Sequence;
|
|
4
|
+
from(elements: Element[]): Sequence;
|
|
5
|
+
concat(sequences: Sequence[]): Sequence;
|
|
6
|
+
length(sequence: Sequence): number;
|
|
7
|
+
at(sequence: Sequence, index: number): Element | undefined;
|
|
8
|
+
subsequence(sequence: Sequence, start: number, end: number): Sequence;
|
|
9
|
+
indexOf(sequence: Sequence, element: Element, fromIndex?: number): number;
|
|
10
|
+
indexOfSubsequence(sequence: Sequence, subsequence: Sequence, fromIndex?: number): number;
|
|
11
|
+
equals(sequenceA: Sequence, sequenceB: Sequence): boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export class StringParserInputCompanion implements ParserInputCompanion<string, string> {
|
|
15
|
+
is(value: unknown): value is string {
|
|
16
|
+
return typeof value === 'string';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
from(elements: string[]): string {
|
|
20
|
+
return elements.join('');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
concat(sequences: string[]): string {
|
|
24
|
+
return sequences.join('');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
length(sequence: string): number {
|
|
28
|
+
return sequence.length;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
at(sequence: string, index: number): string | undefined {
|
|
32
|
+
return sequence.at(index);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
subsequence(sequence: string, start: number, end: number): string {
|
|
36
|
+
return sequence.slice(start, end);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
indexOf(sequence: string, element: string, fromIndex?: number): number {
|
|
40
|
+
return sequence.indexOf(element, fromIndex);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
indexOfSubsequence(sequence: string, subsequence: string, fromIndex?: number): number {
|
|
44
|
+
return sequence.indexOf(subsequence, fromIndex);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
equals(sequenceA: string, sequenceB: string): boolean {
|
|
48
|
+
return sequenceA === sequenceB;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const stringParserInputCompanion = new StringParserInputCompanion();
|
|
53
|
+
|
|
54
|
+
export class Uint8ArrayParserInputCompanion implements ParserInputCompanion<Uint8Array, number> {
|
|
55
|
+
is(value: unknown): value is Uint8Array {
|
|
56
|
+
return value instanceof Uint8Array;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
from(elements: number[]): Uint8Array {
|
|
60
|
+
return new Uint8Array(elements);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
concat(sequences: Uint8Array[]): Uint8Array {
|
|
64
|
+
return new Uint8Array(Buffer.concat(sequences));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
length(sequence: Uint8Array): number {
|
|
68
|
+
return sequence.length;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
at(sequence: Uint8Array, index: number): number | undefined {
|
|
72
|
+
return sequence.at(index);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
subsequence(sequence: Uint8Array, start: number, end: number): Uint8Array {
|
|
76
|
+
return sequence.subarray(start, end);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
indexOf(sequence: Uint8Array, element: number, fromIndex?: number): number {
|
|
80
|
+
return sequence.indexOf(element, fromIndex);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
indexOfSubsequence(sequence: Uint8Array, subsequence: Uint8Array, fromIndex?: number): number {
|
|
84
|
+
return Buffer.from(sequence).indexOf(Buffer.from(subsequence), fromIndex);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
equals(sequenceA: Uint8Array, sequenceB: Uint8Array): boolean {
|
|
88
|
+
if (sequenceA.length !== sequenceB.length) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (let index = 0; index < sequenceA.length; index++) {
|
|
93
|
+
if (sequenceA[index] !== sequenceB[index]) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const uint8ArrayParserInputCompanion = new Uint8ArrayParserInputCompanion();
|
package/src/promiseCompose.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
|
|
2
2
|
export function promiseCompose<A, B, C>(
|
|
3
|
-
f1: (a: A) => Promise<B>,
|
|
3
|
+
f1: (a: A) => B | Promise<B>,
|
|
4
4
|
f2: (b: B) => C | Promise<C>,
|
|
5
|
-
): (a: A) => Promise<C> {
|
|
6
|
-
|
|
5
|
+
): (a: A) => C | Promise<C> {
|
|
6
|
+
function promiseComposed(a: A) {
|
|
7
|
+
const bOrBPromise = f1(a);
|
|
8
|
+
|
|
9
|
+
if (bOrBPromise instanceof Promise) {
|
|
10
|
+
return bOrBPromise.then(f2);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return f2(bOrBPromise);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
Object.defineProperty(promiseComposed, 'name', {
|
|
17
|
+
value: `promiseCompose(${f1.name}, ${f2.name})`,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return promiseComposed;
|
|
7
21
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getParserName, type Parser, setParserName } from './parser.js';
|
|
2
|
+
|
|
3
|
+
export const createQuantifierParser = <Output, Sequence>(
|
|
4
|
+
childParser: Parser<Output, Sequence>,
|
|
5
|
+
count: number,
|
|
6
|
+
): Parser<Output[], Sequence> => {
|
|
7
|
+
const quantifierParser: Parser<Output[], Sequence> = async parserContext => {
|
|
8
|
+
const elements: Output[] = [];
|
|
9
|
+
|
|
10
|
+
for (let index = 0; index < count; index++) {
|
|
11
|
+
elements.push(await childParser(parserContext));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return elements;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
setParserName(quantifierParser, [
|
|
18
|
+
getParserName(childParser, 'anonymousQuantifierChild'),
|
|
19
|
+
'{',
|
|
20
|
+
count,
|
|
21
|
+
'}',
|
|
22
|
+
].join(''));
|
|
23
|
+
|
|
24
|
+
return quantifierParser;
|
|
25
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { testProp, fc } from '@fast-check/ava';
|
|
3
|
+
import { createSeparatedArrayParser } from './separatedArrayParser.js';
|
|
4
|
+
import { type Parser, runParser, runParserWithRemainingInput } from './parser.js';
|
|
5
|
+
import { stringParserInputCompanion } from './parserInputCompanion.js';
|
|
6
|
+
import { createExactSequenceParser } from './exactSequenceParser.js';
|
|
7
|
+
|
|
8
|
+
test('does not loop forever with a child parser that does not consume anything', async t => {
|
|
9
|
+
const parser: Parser<undefined[], string> = createSeparatedArrayParser(async () => undefined, () => undefined);
|
|
10
|
+
const { output } = await runParserWithRemainingInput(parser, 'foo', stringParserInputCompanion);
|
|
11
|
+
|
|
12
|
+
t.deepEqual(output, []);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
testProp(
|
|
16
|
+
'separatedArray',
|
|
17
|
+
[
|
|
18
|
+
fc.array(fc.constant('element')),
|
|
19
|
+
],
|
|
20
|
+
async (t, elements) => {
|
|
21
|
+
const separatedArrayParser = createSeparatedArrayParser(
|
|
22
|
+
createExactSequenceParser('element'),
|
|
23
|
+
createExactSequenceParser('separator'),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const actual = await runParser(separatedArrayParser, elements.join('separator'), stringParserInputCompanion);
|
|
27
|
+
const expected = elements;
|
|
28
|
+
|
|
29
|
+
t.deepEqual(actual, expected);
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
verbose: true,
|
|
33
|
+
},
|
|
34
|
+
);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { getParserName, type Parser, setParserName } from './parser.js';
|
|
2
|
+
import { ParserParsingFailedError } from './parserError.js';
|
|
3
|
+
import { promiseCompose } from './promiseCompose.js';
|
|
4
|
+
import { createTupleParser } from './tupleParser.js';
|
|
5
|
+
|
|
6
|
+
export const createSeparatedArrayParser = <ElementOutput, Sequence>(
|
|
7
|
+
elementParser: Parser<ElementOutput, Sequence>,
|
|
8
|
+
separatorParser: Parser<unknown, Sequence>,
|
|
9
|
+
): Parser<ElementOutput[], Sequence> => {
|
|
10
|
+
const separatorThenElementParser: Parser<ElementOutput, Sequence> = promiseCompose(
|
|
11
|
+
createTupleParser([
|
|
12
|
+
separatorParser,
|
|
13
|
+
elementParser,
|
|
14
|
+
]),
|
|
15
|
+
([ , element ]) => element,
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const separatedArrayParser: Parser<ElementOutput[], Sequence> = async parserContext => {
|
|
19
|
+
let parser = elementParser;
|
|
20
|
+
|
|
21
|
+
const elements: ElementOutput[] = [];
|
|
22
|
+
|
|
23
|
+
while (true) {
|
|
24
|
+
const elementParserContext = parserContext.lookahead();
|
|
25
|
+
const initialPosition = elementParserContext.position;
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const element = await parser(elementParserContext);
|
|
29
|
+
|
|
30
|
+
if (elementParserContext.position === initialPosition) {
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
elements.push(element);
|
|
35
|
+
elementParserContext.unlookahead();
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error instanceof ParserParsingFailedError) {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
throw error;
|
|
42
|
+
} finally {
|
|
43
|
+
elementParserContext.dispose();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
parser = separatorThenElementParser
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return elements;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
setParserName(separatedArrayParser, getParserName(elementParser, 'anonymousSeparatedArrayChild') + '*');
|
|
53
|
+
|
|
54
|
+
return separatedArrayParser;
|
|
55
|
+
};
|