@futpib/parser 1.0.0
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/.editorconfig +12 -0
- package/.gitattributes +2 -0
- package/.github/workflows/main.yml +29 -0
- package/.yarn/releases/yarn-4.5.3.cjs +934 -0
- package/.yarnrc.yml +7 -0
- package/build/allSettledStream.d.ts +17 -0
- package/build/allSettledStream.js +21 -0
- package/build/allSettledStream.test.d.ts +1 -0
- package/build/allSettledStream.test.js +56 -0
- package/build/apk.d.ts +13 -0
- package/build/apk.js +1 -0
- package/build/apkParser.d.ts +3 -0
- package/build/apkParser.js +135 -0
- package/build/apkParser.test.d.ts +1 -0
- package/build/apkParser.test.js +22 -0
- package/build/arbitrarilySlicedAsyncInterable.d.ts +2 -0
- package/build/arbitrarilySlicedAsyncInterable.js +46 -0
- package/build/arbitrarilySlicedAsyncInterator.d.ts +2 -0
- package/build/arbitrarilySlicedAsyncInterator.js +17 -0
- package/build/arbitraryDosDate.d.ts +2 -0
- package/build/arbitraryDosDate.js +8 -0
- package/build/arbitraryDosDateTime.d.ts +2 -0
- package/build/arbitraryDosDateTime.js +9 -0
- package/build/arbitraryDosPermissions.d.ts +1 -0
- package/build/arbitraryDosPermissions.js +1 -0
- package/build/arbitraryFileSystemEntry.d.ts +14 -0
- package/build/arbitraryFileSystemEntry.js +12 -0
- package/build/arbitraryZip.d.ts +6 -0
- package/build/arbitraryZip.js +88 -0
- package/build/arbitraryZipEntry.d.ts +3 -0
- package/build/arbitraryZipEntry.js +26 -0
- package/build/arbitraryZipPermissions.d.ts +8 -0
- package/build/arbitraryZipPermissions.js +16 -0
- package/build/arbitraryZipStream.d.ts +5 -0
- package/build/arbitraryZipStream.js +50 -0
- package/build/arrayParser.d.ts +2 -0
- package/build/arrayParser.js +30 -0
- package/build/arrayParser.test.d.ts +1 -0
- package/build/arrayParser.test.js +9 -0
- package/build/bsonParser.d.ts +3 -0
- package/build/bsonParser.js +70 -0
- package/build/bsonParser.test.d.ts +1 -0
- package/build/bsonParser.test.js +24 -0
- package/build/createDisjunctionParser.d.ts +2 -0
- package/build/createDisjunctionParser.js +47 -0
- package/build/createExactParser.d.ts +2 -0
- package/build/createExactParser.js +12 -0
- package/build/createSequentialUnionParser.d.ts +2 -0
- package/build/createSequentialUnionParser.js +69 -0
- package/build/debugLogParser.d.ts +2 -0
- package/build/debugLogParser.js +23 -0
- package/build/disjunctionParser.d.ts +2 -0
- package/build/disjunctionParser.js +35 -0
- package/build/elementParser.d.ts +3 -0
- package/build/elementParser.js +1 -0
- package/build/endOfInputParser.d.ts +4 -0
- package/build/endOfInputParser.js +4 -0
- package/build/exactElementParser.d.ts +3 -0
- package/build/exactElementParser.js +6 -0
- package/build/exactSequenceParser.d.ts +2 -0
- package/build/exactSequenceParser.js +15 -0
- package/build/fixedLengthChunkParser.d.ts +2 -0
- package/build/fixedLengthChunkParser.js +12 -0
- package/build/fixedLengthParser.d.ts +2 -0
- package/build/fixedLengthParser.js +12 -0
- package/build/fixedLengthSequenceParser.d.ts +2 -0
- package/build/fixedLengthSequenceParser.js +16 -0
- package/build/index.d.ts +18 -0
- package/build/index.js +17 -0
- package/build/index.test.d.ts +1 -0
- package/build/index.test.js +2 -0
- package/build/inputChunkBuffer.d.ts +15 -0
- package/build/inputChunkBuffer.js +40 -0
- package/build/inputChunkBuffer.test.d.ts +1 -0
- package/build/inputChunkBuffer.test.js +34 -0
- package/build/inputCompanion.d.ts +18 -0
- package/build/inputCompanion.js +28 -0
- package/build/inputReader.d.ts +22 -0
- package/build/inputReader.js +105 -0
- package/build/inputReader.test.d.ts +1 -0
- package/build/inputReader.test.js +174 -0
- package/build/invariantDefined.d.ts +1 -0
- package/build/invariantDefined.js +5 -0
- package/build/invariantIdentity.d.ts +3 -0
- package/build/invariantIdentity.js +5 -0
- package/build/jsonParser.d.ts +3 -0
- package/build/jsonParser.js +133 -0
- package/build/jsonParser.test.d.ts +1 -0
- package/build/jsonParser.test.js +17 -0
- package/build/jsonParser2.d.ts +3 -0
- package/build/jsonParser2.js +52 -0
- package/build/jsonParser2.test.d.ts +1 -0
- package/build/jsonParser2.test.js +22 -0
- package/build/listParser.d.ts +2 -0
- package/build/listParser.js +34 -0
- package/build/negativeLookahead.d.ts +2 -0
- package/build/negativeLookahead.js +20 -0
- package/build/optionalParser.d.ts +2 -0
- package/build/optionalParser.js +23 -0
- package/build/parser.d.ts +10 -0
- package/build/parser.js +53 -0
- package/build/parser.test.d.ts +1 -0
- package/build/parser.test.js +126 -0
- package/build/parserAccessorParser.d.ts +2 -0
- package/build/parserAccessorParser.js +1 -0
- package/build/parserCompose.d.ts +3 -0
- package/build/parserCompose.js +7 -0
- package/build/parserContext.d.ts +48 -0
- package/build/parserContext.js +193 -0
- package/build/parserContext.test.d.ts +1 -0
- package/build/parserContext.test.js +115 -0
- package/build/parserCreatorCompose.d.ts +3 -0
- package/build/parserCreatorCompose.js +10 -0
- package/build/parserError.d.ts +43 -0
- package/build/parserError.js +61 -0
- package/build/parserImplementationInvariant.d.ts +2 -0
- package/build/parserImplementationInvariant.js +5 -0
- package/build/parserImplementationInvariantInvariant.d.ts +3 -0
- package/build/parserImplementationInvariantInvariant.js +15 -0
- package/build/parserInvariant.d.ts +4 -0
- package/build/parserInvariant.js +11 -0
- package/build/parserParsingInvariant.d.ts +1 -0
- package/build/parserParsingInvariant.js +1 -0
- package/build/promiseCompose.d.ts +1 -0
- package/build/promiseCompose.js +3 -0
- package/build/promiseFish.d.ts +1 -0
- package/build/promiseFish.js +3 -0
- package/build/sequence.d.ts +1 -0
- package/build/sequence.js +1 -0
- package/build/sequenceBuffer.d.ts +15 -0
- package/build/sequenceBuffer.js +40 -0
- package/build/sequenceBuffer.test.d.ts +1 -0
- package/build/sequenceBuffer.test.js +34 -0
- package/build/sequenceParser.d.ts +3 -0
- package/build/sequenceParser.js +10 -0
- package/build/skipParser.d.ts +2 -0
- package/build/skipParser.js +8 -0
- package/build/sliceBoundedParser.d.ts +2 -0
- package/build/sliceBoundedParser.js +24 -0
- package/build/sliceBoundedParser.test.d.ts +1 -0
- package/build/sliceBoundedParser.test.js +24 -0
- package/build/terminatedArrayParser.d.ts +2 -0
- package/build/terminatedArrayParser.js +27 -0
- package/build/terminatedSequenceParser.d.ts +2 -0
- package/build/terminatedSequenceParser.js +24 -0
- package/build/tupleParser.d.ts +11 -0
- package/build/tupleParser.js +17 -0
- package/build/unionParser.d.ts +2 -0
- package/build/unionParser.js +68 -0
- package/build/zip.d.ts +31 -0
- package/build/zip.js +1 -0
- package/build/zipEntry.d.ts +28 -0
- package/build/zipEntry.js +1 -0
- package/build/zipFile.d.ts +32 -0
- package/build/zipFile.js +1 -0
- package/build/zipFileEntry.d.ts +6 -0
- package/build/zipFileEntry.js +1 -0
- package/build/zipParser.d.ts +70 -0
- package/build/zipParser.js +255 -0
- package/build/zipParser.test.d.ts +1 -0
- package/build/zipParser.test.js +22 -0
- package/package.json +52 -0
- package/readme.md +17 -0
- package/renovate.json +6 -0
- package/src/allSettledStream.test.ts +59 -0
- package/src/allSettledStream.test.ts.md +52 -0
- package/src/allSettledStream.test.ts.snap +0 -0
- package/src/allSettledStream.ts +44 -0
- package/src/apk.ts +16 -0
- package/src/apkParser.test.ts +30 -0
- package/src/apkParser.test.ts.md +268 -0
- package/src/apkParser.test.ts.snap +0 -0
- package/src/apkParser.ts +327 -0
- package/src/arbitrarilySlicedAsyncInterable.ts +73 -0
- package/src/arbitrarilySlicedAsyncInterator.ts +25 -0
- package/src/arbitraryDosDateTime.ts +10 -0
- package/src/arbitraryFileSystemEntry.ts +36 -0
- package/src/arbitraryZip.ts +132 -0
- package/src/arbitraryZipPermissions.ts +25 -0
- package/src/arbitraryZipStream.ts +60 -0
- package/src/arrayParser.test.ts +11 -0
- package/src/arrayParser.ts +35 -0
- package/src/bsonParser.test.ts +37 -0
- package/src/bsonParser.ts +131 -0
- package/src/debugLogParser.ts +51 -0
- package/src/disjunctionParser.ts +55 -0
- package/src/elementParser.ts +4 -0
- package/src/endOfInputParser.ts +11 -0
- package/src/exactElementParser.ts +20 -0
- package/src/exactSequenceParser.ts +27 -0
- package/src/fixedLengthSequenceParser.ts +24 -0
- package/src/index.test.ts +3 -0
- package/src/index.ts +76 -0
- package/src/inputCompanion.ts +43 -0
- package/src/inputReader.test.ts +238 -0
- package/src/inputReader.ts +159 -0
- package/src/invariantDefined.ts +6 -0
- package/src/invariantIdentity.ts +8 -0
- package/src/jsonParser.test.ts +26 -0
- package/src/jsonParser.ts +225 -0
- package/src/listParser.ts +52 -0
- package/src/negativeLookahead.ts +26 -0
- package/src/optionalParser.ts +27 -0
- package/src/parser.test.ts +176 -0
- package/src/parser.test.ts.md +68 -0
- package/src/parser.test.ts.snap +0 -0
- package/src/parser.ts +103 -0
- package/src/parserAccessorParser.ts +3 -0
- package/src/parserContext.test.ts +154 -0
- package/src/parserContext.ts +316 -0
- package/src/parserCreatorCompose.ts +23 -0
- package/src/parserError.ts +85 -0
- package/src/parserImplementationInvariant.ts +6 -0
- package/src/parserInvariant.ts +26 -0
- package/src/promiseCompose.ts +7 -0
- package/src/sequence.ts +10 -0
- package/src/sequenceBuffer.test.ts +50 -0
- package/src/sequenceBuffer.ts +58 -0
- package/src/skipParser.ts +12 -0
- package/src/sliceBoundedParser.test.ts +28 -0
- package/src/sliceBoundedParser.ts +30 -0
- package/src/terminatedArrayParser.ts +40 -0
- package/src/tupleParser.ts +33 -0
- package/src/unionParser.ts +104 -0
- package/src/zip.ts +48 -0
- package/src/zipParser.test.ts +31 -0
- package/src/zipParser.ts +501 -0
- package/tsconfig.json +109 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const stringInputCompanion = new class StringInputCompanion {
|
|
2
|
+
is(value) {
|
|
3
|
+
return typeof value === 'string';
|
|
4
|
+
}
|
|
5
|
+
from(elements) {
|
|
6
|
+
return elements.join('');
|
|
7
|
+
}
|
|
8
|
+
length(sequence) {
|
|
9
|
+
return sequence.length;
|
|
10
|
+
}
|
|
11
|
+
at(sequence, index) {
|
|
12
|
+
return sequence.at(index);
|
|
13
|
+
}
|
|
14
|
+
}();
|
|
15
|
+
export const uint8ArrayInputCompanion = new class Uint8ArrayInputCompanion {
|
|
16
|
+
is(value) {
|
|
17
|
+
return value instanceof Uint8Array;
|
|
18
|
+
}
|
|
19
|
+
from(elements) {
|
|
20
|
+
return new Uint8Array(elements);
|
|
21
|
+
}
|
|
22
|
+
length(sequence) {
|
|
23
|
+
return sequence.length;
|
|
24
|
+
}
|
|
25
|
+
at(sequence, index) {
|
|
26
|
+
return sequence.at(index);
|
|
27
|
+
}
|
|
28
|
+
}();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type InputCompanion } from './inputCompanion.js';
|
|
2
|
+
export type InputReader<Sequence, Element> = {
|
|
3
|
+
get position(): number;
|
|
4
|
+
peek(offset: number): Promise<Element | undefined>;
|
|
5
|
+
skip(offset: number): void;
|
|
6
|
+
lookahead(): InputReader<Sequence, Element>;
|
|
7
|
+
};
|
|
8
|
+
export declare class InputReaderImplementation<Sequence, Element> implements InputReader<Sequence, Element> {
|
|
9
|
+
private readonly _inputCompanion;
|
|
10
|
+
private readonly _inputAsyncIterator;
|
|
11
|
+
private readonly _id;
|
|
12
|
+
private _position;
|
|
13
|
+
private _uncommitedSkipOffset;
|
|
14
|
+
private readonly _promiseMutex;
|
|
15
|
+
private readonly _sequenceBuffer;
|
|
16
|
+
constructor(_inputCompanion: InputCompanion<Sequence, Element>, _inputAsyncIterator: AsyncIterator<Sequence>);
|
|
17
|
+
get [Symbol.toStringTag](): string;
|
|
18
|
+
get position(): number;
|
|
19
|
+
peek(offset: number): Promise<Element | undefined>;
|
|
20
|
+
skip(offset: number): void;
|
|
21
|
+
lookahead(): InputReader<Sequence, Element>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import PromiseMutex from 'p-mutex';
|
|
2
|
+
import invariant from 'invariant';
|
|
3
|
+
import { SequenceBufferImplementation } from './sequenceBuffer.js';
|
|
4
|
+
import { parserImplementationInvariant } from './parserImplementationInvariant.js';
|
|
5
|
+
let inputReaderId = 0;
|
|
6
|
+
export class InputReaderImplementation {
|
|
7
|
+
_inputCompanion;
|
|
8
|
+
_inputAsyncIterator;
|
|
9
|
+
_id = inputReaderId++;
|
|
10
|
+
_position = 0;
|
|
11
|
+
_uncommitedSkipOffset = 0;
|
|
12
|
+
_promiseMutex = new PromiseMutex();
|
|
13
|
+
_sequenceBuffer;
|
|
14
|
+
constructor(_inputCompanion, _inputAsyncIterator) {
|
|
15
|
+
this._inputCompanion = _inputCompanion;
|
|
16
|
+
this._inputAsyncIterator = _inputAsyncIterator;
|
|
17
|
+
this._sequenceBuffer = new SequenceBufferImplementation(this._inputCompanion);
|
|
18
|
+
}
|
|
19
|
+
get [Symbol.toStringTag]() {
|
|
20
|
+
return [
|
|
21
|
+
'InputReader',
|
|
22
|
+
this._id,
|
|
23
|
+
this.position,
|
|
24
|
+
].join(' ');
|
|
25
|
+
}
|
|
26
|
+
get position() {
|
|
27
|
+
return this._position;
|
|
28
|
+
}
|
|
29
|
+
async peek(offset) {
|
|
30
|
+
parserImplementationInvariant(offset >= 0, 'offset >= 0');
|
|
31
|
+
offset += this._uncommitedSkipOffset;
|
|
32
|
+
const element = this._sequenceBuffer.peek(offset);
|
|
33
|
+
if (element !== undefined) {
|
|
34
|
+
return element;
|
|
35
|
+
}
|
|
36
|
+
return this._promiseMutex.withLock(async () => {
|
|
37
|
+
while (true) {
|
|
38
|
+
const element = this._sequenceBuffer.peek(offset);
|
|
39
|
+
if (element !== undefined) {
|
|
40
|
+
return element;
|
|
41
|
+
}
|
|
42
|
+
const inputIteratorResult = await this._inputAsyncIterator.next();
|
|
43
|
+
if (inputIteratorResult.done) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
parserImplementationInvariant(this._inputCompanion.is(inputIteratorResult.value), [
|
|
47
|
+
'Input iterator result value (%s) is of unexpected type.',
|
|
48
|
+
'Expected a sequence (a chunk of input) recognized by the input companion (%s).',
|
|
49
|
+
'You may have provided a wrong input companion for the input.',
|
|
50
|
+
], inputIteratorResult.value, this._inputCompanion.constructor.name);
|
|
51
|
+
this._sequenceBuffer.push(inputIteratorResult.value);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
skip(offset) {
|
|
56
|
+
parserImplementationInvariant(offset >= 0, 'offset >= 0');
|
|
57
|
+
this._position += offset;
|
|
58
|
+
if (this._promiseMutex.isLocked) {
|
|
59
|
+
this._uncommitedSkipOffset += offset;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
this._sequenceBuffer.skip(offset + this._uncommitedSkipOffset);
|
|
63
|
+
this._uncommitedSkipOffset = 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
lookahead() {
|
|
67
|
+
return new InputReaderLookaheadImplementation(this);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
class InputReaderLookaheadImplementation {
|
|
71
|
+
_inputReader;
|
|
72
|
+
_initialInputReaderPosition = 0;
|
|
73
|
+
_offset = 0;
|
|
74
|
+
constructor(_inputReader) {
|
|
75
|
+
this._inputReader = _inputReader;
|
|
76
|
+
this._initialInputReaderPosition = this._inputReader.position;
|
|
77
|
+
}
|
|
78
|
+
get [Symbol.toStringTag]() {
|
|
79
|
+
return [
|
|
80
|
+
'InputReaderLookahead',
|
|
81
|
+
this._inputReader.toString(),
|
|
82
|
+
this.position,
|
|
83
|
+
].join(' ');
|
|
84
|
+
}
|
|
85
|
+
get position() {
|
|
86
|
+
return this._initialInputReaderPosition + this._offset;
|
|
87
|
+
}
|
|
88
|
+
async peek(offset) {
|
|
89
|
+
const inputReaderMovedForward = this._inputReader.position - this._initialInputReaderPosition;
|
|
90
|
+
this._initialInputReaderPosition = this._inputReader.position;
|
|
91
|
+
this._offset -= inputReaderMovedForward;
|
|
92
|
+
return this._inputReader.peek(this._offset + offset);
|
|
93
|
+
}
|
|
94
|
+
skip(offset) {
|
|
95
|
+
parserImplementationInvariant(offset >= 0, 'offset >= 0');
|
|
96
|
+
this._offset += offset;
|
|
97
|
+
}
|
|
98
|
+
lookahead() {
|
|
99
|
+
const lookahead = new InputReaderLookaheadImplementation(this._inputReader);
|
|
100
|
+
const offset = this.position - lookahead.position;
|
|
101
|
+
lookahead.skip(offset);
|
|
102
|
+
invariant(this.position === lookahead.position, 'this.position (%s) === lookahead.position (%s)', this.position, lookahead.position);
|
|
103
|
+
return lookahead;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { InputReaderImplementation } from './inputReader.js';
|
|
3
|
+
import { stringInputCompanion } from './inputCompanion.js';
|
|
4
|
+
import { ParserImplementationError } from './parserError.js';
|
|
5
|
+
test('inputReader', async (t) => {
|
|
6
|
+
const inputReader = new InputReaderImplementation(stringInputCompanion, (async function* () {
|
|
7
|
+
yield '';
|
|
8
|
+
yield 'abc';
|
|
9
|
+
yield 'def';
|
|
10
|
+
yield '';
|
|
11
|
+
yield 'gh';
|
|
12
|
+
})());
|
|
13
|
+
t.is(await inputReader.peek(0), 'a');
|
|
14
|
+
inputReader.skip(0);
|
|
15
|
+
t.is(await inputReader.peek(1), 'b');
|
|
16
|
+
inputReader.skip(1);
|
|
17
|
+
t.is(await inputReader.peek(1), 'c');
|
|
18
|
+
t.is(await inputReader.peek(2), 'd');
|
|
19
|
+
t.is(await inputReader.peek(3), 'e');
|
|
20
|
+
t.is(await inputReader.peek(4), 'f');
|
|
21
|
+
t.is(await inputReader.peek(5), 'g');
|
|
22
|
+
t.is(await inputReader.peek(6), 'h');
|
|
23
|
+
t.is(await inputReader.peek(7), undefined);
|
|
24
|
+
inputReader.skip(6);
|
|
25
|
+
t.is(await inputReader.peek(0), 'h');
|
|
26
|
+
t.is(await inputReader.peek(1), undefined);
|
|
27
|
+
inputReader.skip(1);
|
|
28
|
+
t.is(await inputReader.peek(0), undefined);
|
|
29
|
+
inputReader.skip(0);
|
|
30
|
+
t.is(await inputReader.peek(0), undefined);
|
|
31
|
+
inputReader.skip(1);
|
|
32
|
+
t.is(await inputReader.peek(0), undefined);
|
|
33
|
+
});
|
|
34
|
+
test('inputReader.peek concurrent', async (t) => {
|
|
35
|
+
const inputReader = new InputReaderImplementation(stringInputCompanion, (async function* () {
|
|
36
|
+
yield* 'abcdefgh';
|
|
37
|
+
})());
|
|
38
|
+
const peeks = await Promise.all([
|
|
39
|
+
inputReader.peek(0),
|
|
40
|
+
inputReader.peek(0),
|
|
41
|
+
inputReader.peek(0),
|
|
42
|
+
inputReader.peek(0),
|
|
43
|
+
inputReader.peek(1),
|
|
44
|
+
inputReader.peek(2),
|
|
45
|
+
inputReader.peek(3),
|
|
46
|
+
inputReader.peek(4),
|
|
47
|
+
inputReader.peek(5),
|
|
48
|
+
inputReader.peek(6),
|
|
49
|
+
inputReader.peek(7),
|
|
50
|
+
]);
|
|
51
|
+
t.deepEqual(peeks, ['a', 'a', 'a', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
|
52
|
+
});
|
|
53
|
+
test('inputReader skip while peeking', async (t) => {
|
|
54
|
+
const inputReader = new InputReaderImplementation(stringInputCompanion, (async function* () {
|
|
55
|
+
yield* 'abcdefgh';
|
|
56
|
+
})());
|
|
57
|
+
const peekPromise = inputReader.peek(0);
|
|
58
|
+
inputReader.skip(1);
|
|
59
|
+
t.is(await peekPromise, 'a');
|
|
60
|
+
t.is(await inputReader.peek(0), 'b');
|
|
61
|
+
});
|
|
62
|
+
test('inputReader.lookahead', async (t) => {
|
|
63
|
+
let read = 0;
|
|
64
|
+
const inputReader = new InputReaderImplementation(stringInputCompanion, (async function* () {
|
|
65
|
+
for (const character of 'abcdefgh') {
|
|
66
|
+
read++;
|
|
67
|
+
yield character;
|
|
68
|
+
}
|
|
69
|
+
})());
|
|
70
|
+
const lookahead0a = inputReader.lookahead();
|
|
71
|
+
const lookahead0b = lookahead0a.lookahead();
|
|
72
|
+
const lookahead0c = lookahead0b.lookahead();
|
|
73
|
+
t.is(await inputReader.peek(0), 'a');
|
|
74
|
+
t.is(await lookahead0a.peek(0), 'a');
|
|
75
|
+
t.is(await lookahead0b.peek(0), 'a');
|
|
76
|
+
t.is(await lookahead0c.peek(0), 'a');
|
|
77
|
+
t.is(inputReader.position, 0);
|
|
78
|
+
t.is(lookahead0a.position, 0);
|
|
79
|
+
t.is(lookahead0b.position, 0);
|
|
80
|
+
t.is(lookahead0c.position, 0);
|
|
81
|
+
t.is(read, 1);
|
|
82
|
+
t.is(await lookahead0b.peek(1), 'b');
|
|
83
|
+
t.is(await inputReader.peek(0), 'a');
|
|
84
|
+
t.is(read, 2);
|
|
85
|
+
inputReader.skip(1);
|
|
86
|
+
await t.throwsAsync(async () => lookahead0a.peek(0), {
|
|
87
|
+
instanceOf: ParserImplementationError,
|
|
88
|
+
});
|
|
89
|
+
await t.throwsAsync(async () => lookahead0b.peek(0));
|
|
90
|
+
await t.throwsAsync(async () => lookahead0c.peek(0));
|
|
91
|
+
const lookahead1a = inputReader.lookahead();
|
|
92
|
+
const lookahead1b = inputReader.lookahead();
|
|
93
|
+
t.is(await lookahead1a.peek(0), 'b');
|
|
94
|
+
t.is(await lookahead1b.peek(0), 'b');
|
|
95
|
+
t.is(lookahead1a.position, 1);
|
|
96
|
+
t.is(lookahead1b.position, 1);
|
|
97
|
+
lookahead1a.skip(1);
|
|
98
|
+
t.is(await lookahead1a.peek(0), 'c');
|
|
99
|
+
t.is(await lookahead1b.peek(0), 'b');
|
|
100
|
+
t.is(lookahead1a.position, 2);
|
|
101
|
+
t.is(lookahead1b.position, 1);
|
|
102
|
+
const lookahead2a = lookahead1a.lookahead();
|
|
103
|
+
const lookahead2b = lookahead1a.lookahead();
|
|
104
|
+
lookahead2a.skip(1);
|
|
105
|
+
t.is(await lookahead2a.peek(0), 'd');
|
|
106
|
+
t.is(await lookahead2b.peek(0), 'c');
|
|
107
|
+
t.is(lookahead2a.position, 3);
|
|
108
|
+
t.is(lookahead2b.position, 2);
|
|
109
|
+
t.is(read, 4);
|
|
110
|
+
t.is(await inputReader.peek(0), 'b');
|
|
111
|
+
t.is(inputReader.position, 1);
|
|
112
|
+
inputReader.skip(1);
|
|
113
|
+
t.is(await inputReader.peek(0), 'c');
|
|
114
|
+
t.is(inputReader.position, 2);
|
|
115
|
+
await t.throwsAsync(async () => lookahead0a.peek(0));
|
|
116
|
+
await t.throwsAsync(async () => lookahead0b.peek(0));
|
|
117
|
+
await t.throwsAsync(async () => lookahead0c.peek(0));
|
|
118
|
+
t.is(await lookahead1a.peek(0), 'c');
|
|
119
|
+
await t.throwsAsync(async () => lookahead1b.peek(0));
|
|
120
|
+
t.is(await lookahead2a.peek(0), 'd');
|
|
121
|
+
t.is(await lookahead2b.peek(0), 'c');
|
|
122
|
+
t.is(lookahead0a.position, 0);
|
|
123
|
+
t.is(lookahead0b.position, 0);
|
|
124
|
+
t.is(lookahead0c.position, 0);
|
|
125
|
+
t.is(lookahead1a.position, 2);
|
|
126
|
+
t.is(lookahead1b.position, 1);
|
|
127
|
+
t.is(lookahead2a.position, 3);
|
|
128
|
+
t.is(lookahead2b.position, 2);
|
|
129
|
+
});
|
|
130
|
+
test('inputReader.lookahead concurrent', async (t) => {
|
|
131
|
+
let read = 0;
|
|
132
|
+
const inputReader = new InputReaderImplementation(stringInputCompanion, (async function* () {
|
|
133
|
+
for (const character of 'abcdefgh') {
|
|
134
|
+
read++;
|
|
135
|
+
yield character;
|
|
136
|
+
}
|
|
137
|
+
})());
|
|
138
|
+
const lookahead1 = inputReader.lookahead();
|
|
139
|
+
const lookahead2 = inputReader.lookahead();
|
|
140
|
+
const lookahead3 = inputReader.lookahead();
|
|
141
|
+
const peeks = await Promise.all([
|
|
142
|
+
lookahead1.peek(0),
|
|
143
|
+
lookahead2.peek(0),
|
|
144
|
+
lookahead3.peek(0),
|
|
145
|
+
]);
|
|
146
|
+
const positions = [
|
|
147
|
+
lookahead1.position,
|
|
148
|
+
lookahead2.position,
|
|
149
|
+
lookahead3.position,
|
|
150
|
+
];
|
|
151
|
+
t.deepEqual(peeks, ['a', 'a', 'a']);
|
|
152
|
+
t.deepEqual(positions, [0, 0, 0]);
|
|
153
|
+
t.is(read, 1);
|
|
154
|
+
});
|
|
155
|
+
test('inputReader.lookahead skip position', async (t) => {
|
|
156
|
+
let read = 0;
|
|
157
|
+
const inputReader = new InputReaderImplementation(stringInputCompanion, (async function* () {
|
|
158
|
+
for (const character of 'abcdefgh') {
|
|
159
|
+
read++;
|
|
160
|
+
yield character;
|
|
161
|
+
}
|
|
162
|
+
})());
|
|
163
|
+
inputReader.skip(1);
|
|
164
|
+
const lookahead = inputReader.lookahead();
|
|
165
|
+
lookahead.skip(1);
|
|
166
|
+
const lookahead1 = lookahead.lookahead();
|
|
167
|
+
lookahead1.skip(1);
|
|
168
|
+
t.is(inputReader.position, 1);
|
|
169
|
+
t.is(lookahead.position, 2);
|
|
170
|
+
t.is(lookahead1.position, 3);
|
|
171
|
+
t.is(await inputReader.peek(0), 'b');
|
|
172
|
+
t.is(await lookahead.peek(0), 'c');
|
|
173
|
+
t.is(await lookahead1.peek(0), 'd');
|
|
174
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function invariantDefined<T>(value: T, format: string, ...extra: any[]): Exclude<T, undefined>;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { setParserName } from './parser.js';
|
|
2
|
+
import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js';
|
|
3
|
+
import { createUnionParser } from './unionParser.js';
|
|
4
|
+
import { createExactSequenceParser } from './exactSequenceParser.js';
|
|
5
|
+
import { promiseCompose } from './promiseCompose.js';
|
|
6
|
+
import { createTupleParser } from './tupleParser.js';
|
|
7
|
+
import { createDisjunctionParser } from './disjunctionParser.js';
|
|
8
|
+
import { createTerminatedArrayParser } from './terminatedArrayParser.js';
|
|
9
|
+
import { createArrayParser } from './arrayParser.js';
|
|
10
|
+
import { createParserAccessorParser } from './parserAccessorParser.js';
|
|
11
|
+
import { createElementParser } from './elementParser.js';
|
|
12
|
+
import { parserCreatorCompose } from './parserCreatorCompose.js';
|
|
13
|
+
const whitespaceParser = createArrayParser(createUnionParser([
|
|
14
|
+
createExactSequenceParser(' '),
|
|
15
|
+
createExactSequenceParser('\t'),
|
|
16
|
+
createExactSequenceParser('\r'),
|
|
17
|
+
createExactSequenceParser('\n'),
|
|
18
|
+
]));
|
|
19
|
+
const jsonQuoteEscapeSequenceParser = promiseCompose(createExactSequenceParser('\\"'), () => '"');
|
|
20
|
+
const jsonBackslashEscapeSequenceParser = promiseCompose(createExactSequenceParser('\\\\'), () => '\\');
|
|
21
|
+
const jsonSlashEscapeSequenceParser = promiseCompose(createExactSequenceParser('\\/'), () => '/');
|
|
22
|
+
const jsonBackspaceEscapeSequenceParser = promiseCompose(createExactSequenceParser('\\b'), () => '\b');
|
|
23
|
+
const jsonFormFeedEscapeSequenceParser = promiseCompose(createExactSequenceParser('\\f'), () => '\f');
|
|
24
|
+
const jsonNewLineEscapeSequenceParser = promiseCompose(createExactSequenceParser('\\n'), () => '\n');
|
|
25
|
+
const jsonCarriageReturnEscapeSequenceParser = promiseCompose(createExactSequenceParser('\\r'), () => '\r');
|
|
26
|
+
const jsonTabEscapeSequenceParser = promiseCompose(createExactSequenceParser('\\t'), () => '\t');
|
|
27
|
+
const jsonUnicodeEscapeSequenceParser = promiseCompose(createTupleParser([
|
|
28
|
+
createExactSequenceParser('\\u'),
|
|
29
|
+
createFixedLengthSequenceParser(4),
|
|
30
|
+
]), ([, hexCode]) => String.fromCharCode(Number.parseInt(hexCode, 16)));
|
|
31
|
+
const jsonStringEscapeSequenceParser = createUnionParser([
|
|
32
|
+
jsonQuoteEscapeSequenceParser,
|
|
33
|
+
jsonBackslashEscapeSequenceParser,
|
|
34
|
+
jsonSlashEscapeSequenceParser,
|
|
35
|
+
jsonBackspaceEscapeSequenceParser,
|
|
36
|
+
jsonFormFeedEscapeSequenceParser,
|
|
37
|
+
jsonNewLineEscapeSequenceParser,
|
|
38
|
+
jsonCarriageReturnEscapeSequenceParser,
|
|
39
|
+
jsonTabEscapeSequenceParser,
|
|
40
|
+
jsonUnicodeEscapeSequenceParser,
|
|
41
|
+
]);
|
|
42
|
+
const elementParser = createElementParser();
|
|
43
|
+
const jsonStringCharacterParser = createDisjunctionParser([
|
|
44
|
+
jsonStringEscapeSequenceParser,
|
|
45
|
+
parserCreatorCompose(() => elementParser, character => async (parserContext) => {
|
|
46
|
+
parserContext.invariant(character !== '"', 'Unexpected """');
|
|
47
|
+
return character;
|
|
48
|
+
})(),
|
|
49
|
+
]);
|
|
50
|
+
const jsonStringParser = promiseCompose(createTupleParser([
|
|
51
|
+
createExactSequenceParser('"'),
|
|
52
|
+
promiseCompose(createTerminatedArrayParser(jsonStringCharacterParser, createExactSequenceParser('"')), ([characters]) => characters.join('')),
|
|
53
|
+
]), ([, string]) => string);
|
|
54
|
+
const jsonNumberParser = parserCreatorCompose(() => createArrayParser(parserCreatorCompose(() => elementParser, (character) => async (parserContext) => {
|
|
55
|
+
parserContext.invariant((character === '-'
|
|
56
|
+
|| (character >= '0' && character <= '9')
|
|
57
|
+
|| character === '.'
|
|
58
|
+
|| character === 'e'
|
|
59
|
+
|| character === 'E'
|
|
60
|
+
|| character === '+'), 'Expected "-", "0" to "9", ".", "e", "E", "+", got "%s"', character);
|
|
61
|
+
return character;
|
|
62
|
+
})()), (characters) => async (parserContext) => {
|
|
63
|
+
parserContext.invariant(characters.length > 0, 'Expected at least one character');
|
|
64
|
+
return Number(characters.join(''));
|
|
65
|
+
})();
|
|
66
|
+
const jsonTrueParser = promiseCompose(createExactSequenceParser('true'), () => true);
|
|
67
|
+
setParserName(jsonTrueParser, 'jsonTrueParser');
|
|
68
|
+
const jsonFalseParser = promiseCompose(createExactSequenceParser('false'), () => false);
|
|
69
|
+
setParserName(jsonFalseParser, 'jsonFalseParser');
|
|
70
|
+
const jsonNullParser = promiseCompose(createExactSequenceParser('null'), () => null);
|
|
71
|
+
setParserName(jsonNullParser, 'jsonNullParser');
|
|
72
|
+
const jsonPrimitiveParser = createUnionParser([
|
|
73
|
+
jsonStringParser,
|
|
74
|
+
jsonNumberParser,
|
|
75
|
+
jsonTrueParser,
|
|
76
|
+
jsonFalseParser,
|
|
77
|
+
jsonNullParser,
|
|
78
|
+
]);
|
|
79
|
+
setParserName(jsonPrimitiveParser, 'jsonPrimitiveParser');
|
|
80
|
+
const jsonObjectEntryParser = promiseCompose(createTupleParser([
|
|
81
|
+
jsonStringParser,
|
|
82
|
+
whitespaceParser,
|
|
83
|
+
createExactSequenceParser(':'),
|
|
84
|
+
whitespaceParser,
|
|
85
|
+
createParserAccessorParser(() => jsonValueParser),
|
|
86
|
+
]), ([key, _whitespace1, _colon, _whitespace2, value]) => [key, value]);
|
|
87
|
+
const jsonObjectParser = promiseCompose(createTupleParser([
|
|
88
|
+
createExactSequenceParser('{'),
|
|
89
|
+
whitespaceParser,
|
|
90
|
+
promiseCompose(createTerminatedArrayParser(createDisjunctionParser([
|
|
91
|
+
promiseCompose(createTupleParser([
|
|
92
|
+
createParserAccessorParser(() => jsonObjectEntryParser),
|
|
93
|
+
whitespaceParser,
|
|
94
|
+
createExactSequenceParser(','),
|
|
95
|
+
whitespaceParser,
|
|
96
|
+
]), ([entry]) => entry),
|
|
97
|
+
promiseCompose(createTupleParser([
|
|
98
|
+
createParserAccessorParser(() => jsonObjectEntryParser),
|
|
99
|
+
whitespaceParser,
|
|
100
|
+
]), ([value]) => value),
|
|
101
|
+
]), createExactSequenceParser('}')), ([entries]) => entries),
|
|
102
|
+
]), ([_brace, _whitespace, entries]) => {
|
|
103
|
+
const object = {};
|
|
104
|
+
for (const [key, value] of entries) {
|
|
105
|
+
Object.defineProperty(object, key, {
|
|
106
|
+
value,
|
|
107
|
+
enumerable: true,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return object;
|
|
111
|
+
});
|
|
112
|
+
const jsonArrayParser = promiseCompose(createTupleParser([
|
|
113
|
+
createExactSequenceParser('['),
|
|
114
|
+
whitespaceParser,
|
|
115
|
+
promiseCompose(createTerminatedArrayParser(createDisjunctionParser([
|
|
116
|
+
promiseCompose(createTupleParser([
|
|
117
|
+
createParserAccessorParser(() => jsonValueParser),
|
|
118
|
+
whitespaceParser,
|
|
119
|
+
createExactSequenceParser(','),
|
|
120
|
+
whitespaceParser,
|
|
121
|
+
]), ([value]) => value),
|
|
122
|
+
promiseCompose(createTupleParser([
|
|
123
|
+
createParserAccessorParser(() => jsonValueParser),
|
|
124
|
+
whitespaceParser,
|
|
125
|
+
]), ([value]) => value),
|
|
126
|
+
]), createExactSequenceParser(']')), ([values]) => values),
|
|
127
|
+
]), ([_bracket, _whitespace, values]) => values);
|
|
128
|
+
export const jsonValueParser = createUnionParser([
|
|
129
|
+
jsonObjectParser,
|
|
130
|
+
jsonArrayParser,
|
|
131
|
+
jsonPrimitiveParser,
|
|
132
|
+
]);
|
|
133
|
+
setParserName(jsonValueParser, 'jsonValueParser');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { testProp, fc } from '@fast-check/ava';
|
|
2
|
+
import { jsonValueParser } from './jsonParser.js';
|
|
3
|
+
import { runParser } from './parser.js';
|
|
4
|
+
import { arbitrarilySlicedAsyncIterator } from './arbitrarilySlicedAsyncInterator.js';
|
|
5
|
+
import { stringInputCompanion } from './inputCompanion.js';
|
|
6
|
+
testProp('json', [
|
|
7
|
+
arbitrarilySlicedAsyncIterator(fc.tuple(fc.json(), fc.nat())
|
|
8
|
+
.map(([jsonString, indent]) => JSON.stringify(JSON.parse(jsonString), null, indent))),
|
|
9
|
+
], async (t, [jsonString, jsonStringChunkIterator]) => {
|
|
10
|
+
const actual = await runParser(jsonValueParser, jsonStringChunkIterator, stringInputCompanion, {
|
|
11
|
+
errorJoinMode: 'none',
|
|
12
|
+
});
|
|
13
|
+
const expected = JSON.parse(jsonString);
|
|
14
|
+
t.deepEqual(actual, expected);
|
|
15
|
+
}, {
|
|
16
|
+
verbose: true,
|
|
17
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { parserParsingInvariant } from './parserParsingInvariant.js';
|
|
2
|
+
import { createUnionParser } from './unionParser.js';
|
|
3
|
+
import { createExactSequenceParser } from './exactSequenceParser.js';
|
|
4
|
+
import { promiseCompose } from './promiseCompose.js';
|
|
5
|
+
const jsonStringParser = async (inputContext) => {
|
|
6
|
+
await inputContext.read(0);
|
|
7
|
+
await inputContext.read(0);
|
|
8
|
+
return '';
|
|
9
|
+
};
|
|
10
|
+
const jsonDummyParser = async (inputContext) => {
|
|
11
|
+
await inputContext.read(0);
|
|
12
|
+
parserParsingInvariant(false, 'dummy');
|
|
13
|
+
return 0;
|
|
14
|
+
};
|
|
15
|
+
const jsonNullParser = promiseCompose(createExactSequenceParser('null'), () => null);
|
|
16
|
+
Object.defineProperty(jsonNullParser, 'name', { value: 'jsonNullParser' });
|
|
17
|
+
const jsonPrimitiveParser = createUnionParser([
|
|
18
|
+
jsonDummyParser,
|
|
19
|
+
jsonDummyParser,
|
|
20
|
+
jsonDummyParser,
|
|
21
|
+
jsonDummyParser,
|
|
22
|
+
jsonNullParser,
|
|
23
|
+
]);
|
|
24
|
+
Object.defineProperty(jsonPrimitiveParser, 'name', { value: 'jsonPrimitiveParser' });
|
|
25
|
+
const jsonObjectParser = async (inputContext) => {
|
|
26
|
+
const value = {};
|
|
27
|
+
const firstCharacter = await inputContext.read(0);
|
|
28
|
+
parserParsingInvariant(firstCharacter === '{', 'Expected "{", got "%s"', firstCharacter);
|
|
29
|
+
const key = await jsonStringParser(inputContext);
|
|
30
|
+
const colon = await inputContext.read(0);
|
|
31
|
+
parserParsingInvariant(colon === ':', 'Expected ":", got "%s"', colon);
|
|
32
|
+
const keyValue = await jsonValueParser2(inputContext);
|
|
33
|
+
Object.defineProperty(value, key, {
|
|
34
|
+
value: keyValue,
|
|
35
|
+
enumerable: true,
|
|
36
|
+
});
|
|
37
|
+
const commaOrClosingBrace = await inputContext.peek(0);
|
|
38
|
+
parserParsingInvariant((commaOrClosingBrace === ','
|
|
39
|
+
|| commaOrClosingBrace === '}'), 'Expected "," or "}", got "%s"', commaOrClosingBrace);
|
|
40
|
+
if (commaOrClosingBrace === '}') {
|
|
41
|
+
inputContext.skip(1);
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
parserParsingInvariant(commaOrClosingBrace === ',', 'Expected ",", got "%s"', commaOrClosingBrace);
|
|
45
|
+
inputContext.skip(1);
|
|
46
|
+
return value;
|
|
47
|
+
};
|
|
48
|
+
export const jsonValueParser2 = createUnionParser([
|
|
49
|
+
jsonObjectParser,
|
|
50
|
+
jsonPrimitiveParser,
|
|
51
|
+
]);
|
|
52
|
+
Object.defineProperty(jsonValueParser2, 'name', { value: 'jsonValueParser2' });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { testProp, fc } from '@fast-check/ava';
|
|
2
|
+
import { jsonValueParser2 } from './jsonParser2.js';
|
|
3
|
+
import { runParser } from './parser.js';
|
|
4
|
+
import { arbitrarilySlicedAsyncIterator } from './arbitrarilySlicedAsyncInterator.js';
|
|
5
|
+
import { stringInputCompanion } from './inputCompanion.js';
|
|
6
|
+
testProp('json', [
|
|
7
|
+
arbitrarilySlicedAsyncIterator(fc.json()),
|
|
8
|
+
], async (t, [jsonString, jsonStringChunkIterator]) => {
|
|
9
|
+
if (jsonString !== '{"":null}') {
|
|
10
|
+
throw new Error('This test is only for the JSON string \'{"":null}\'.');
|
|
11
|
+
}
|
|
12
|
+
const actual = await runParser(jsonValueParser2, jsonStringChunkIterator, stringInputCompanion);
|
|
13
|
+
const expected = JSON.parse(jsonString);
|
|
14
|
+
t.deepEqual(actual, expected);
|
|
15
|
+
}, {
|
|
16
|
+
verbose: true,
|
|
17
|
+
examples: [
|
|
18
|
+
[['{"":null}', (async function* () {
|
|
19
|
+
yield* ['{"":null}'];
|
|
20
|
+
})()[Symbol.asyncIterator]()]],
|
|
21
|
+
],
|
|
22
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createNegativeLookaheadParser } from "./negativeLookahead.js";
|
|
2
|
+
import { createParserAccessorParser } from "./parserAccessorParser.js";
|
|
3
|
+
import { promiseCompose } from "./promiseCompose.js";
|
|
4
|
+
import { createTupleParser } from "./tupleParser.js";
|
|
5
|
+
import { createUnionParser } from "./unionParser.js";
|
|
6
|
+
class Nil {
|
|
7
|
+
}
|
|
8
|
+
class Cons {
|
|
9
|
+
head;
|
|
10
|
+
tail;
|
|
11
|
+
constructor(head, tail) {
|
|
12
|
+
this.head = head;
|
|
13
|
+
this.tail = tail;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export const createListParser = (elementParser) => {
|
|
17
|
+
const consParser = promiseCompose(createTupleParser([
|
|
18
|
+
elementParser,
|
|
19
|
+
createParserAccessorParser(() => listParser),
|
|
20
|
+
]), ([head, tail]) => new Cons(head, tail));
|
|
21
|
+
const nilParser = promiseCompose(createNegativeLookaheadParser(elementParser), () => new Nil());
|
|
22
|
+
const listParser = createUnionParser([
|
|
23
|
+
consParser,
|
|
24
|
+
nilParser,
|
|
25
|
+
]);
|
|
26
|
+
return promiseCompose(listParser, list => {
|
|
27
|
+
const array = [];
|
|
28
|
+
while (list instanceof Cons) {
|
|
29
|
+
array.push(list.head);
|
|
30
|
+
list = list.tail;
|
|
31
|
+
}
|
|
32
|
+
return array;
|
|
33
|
+
});
|
|
34
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { getParserName } from "./parser.js";
|
|
2
|
+
import { ParserParsingFailedError } from "./parserError.js";
|
|
3
|
+
export const createNegativeLookaheadParser = (childParser) => {
|
|
4
|
+
return async (parserContext) => {
|
|
5
|
+
const childParserContext = parserContext.lookahead();
|
|
6
|
+
try {
|
|
7
|
+
await childParser(childParserContext);
|
|
8
|
+
parserContext.invariant(false, 'Negative lookahead assertion failed for child parser %s.', getParserName(childParser));
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
if (error instanceof ParserParsingFailedError) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
childParserContext.dispose();
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
};
|