@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.
Files changed (228) hide show
  1. package/.editorconfig +12 -0
  2. package/.gitattributes +2 -0
  3. package/.github/workflows/main.yml +29 -0
  4. package/.yarn/releases/yarn-4.5.3.cjs +934 -0
  5. package/.yarnrc.yml +7 -0
  6. package/build/allSettledStream.d.ts +17 -0
  7. package/build/allSettledStream.js +21 -0
  8. package/build/allSettledStream.test.d.ts +1 -0
  9. package/build/allSettledStream.test.js +56 -0
  10. package/build/apk.d.ts +13 -0
  11. package/build/apk.js +1 -0
  12. package/build/apkParser.d.ts +3 -0
  13. package/build/apkParser.js +135 -0
  14. package/build/apkParser.test.d.ts +1 -0
  15. package/build/apkParser.test.js +22 -0
  16. package/build/arbitrarilySlicedAsyncInterable.d.ts +2 -0
  17. package/build/arbitrarilySlicedAsyncInterable.js +46 -0
  18. package/build/arbitrarilySlicedAsyncInterator.d.ts +2 -0
  19. package/build/arbitrarilySlicedAsyncInterator.js +17 -0
  20. package/build/arbitraryDosDate.d.ts +2 -0
  21. package/build/arbitraryDosDate.js +8 -0
  22. package/build/arbitraryDosDateTime.d.ts +2 -0
  23. package/build/arbitraryDosDateTime.js +9 -0
  24. package/build/arbitraryDosPermissions.d.ts +1 -0
  25. package/build/arbitraryDosPermissions.js +1 -0
  26. package/build/arbitraryFileSystemEntry.d.ts +14 -0
  27. package/build/arbitraryFileSystemEntry.js +12 -0
  28. package/build/arbitraryZip.d.ts +6 -0
  29. package/build/arbitraryZip.js +88 -0
  30. package/build/arbitraryZipEntry.d.ts +3 -0
  31. package/build/arbitraryZipEntry.js +26 -0
  32. package/build/arbitraryZipPermissions.d.ts +8 -0
  33. package/build/arbitraryZipPermissions.js +16 -0
  34. package/build/arbitraryZipStream.d.ts +5 -0
  35. package/build/arbitraryZipStream.js +50 -0
  36. package/build/arrayParser.d.ts +2 -0
  37. package/build/arrayParser.js +30 -0
  38. package/build/arrayParser.test.d.ts +1 -0
  39. package/build/arrayParser.test.js +9 -0
  40. package/build/bsonParser.d.ts +3 -0
  41. package/build/bsonParser.js +70 -0
  42. package/build/bsonParser.test.d.ts +1 -0
  43. package/build/bsonParser.test.js +24 -0
  44. package/build/createDisjunctionParser.d.ts +2 -0
  45. package/build/createDisjunctionParser.js +47 -0
  46. package/build/createExactParser.d.ts +2 -0
  47. package/build/createExactParser.js +12 -0
  48. package/build/createSequentialUnionParser.d.ts +2 -0
  49. package/build/createSequentialUnionParser.js +69 -0
  50. package/build/debugLogParser.d.ts +2 -0
  51. package/build/debugLogParser.js +23 -0
  52. package/build/disjunctionParser.d.ts +2 -0
  53. package/build/disjunctionParser.js +35 -0
  54. package/build/elementParser.d.ts +3 -0
  55. package/build/elementParser.js +1 -0
  56. package/build/endOfInputParser.d.ts +4 -0
  57. package/build/endOfInputParser.js +4 -0
  58. package/build/exactElementParser.d.ts +3 -0
  59. package/build/exactElementParser.js +6 -0
  60. package/build/exactSequenceParser.d.ts +2 -0
  61. package/build/exactSequenceParser.js +15 -0
  62. package/build/fixedLengthChunkParser.d.ts +2 -0
  63. package/build/fixedLengthChunkParser.js +12 -0
  64. package/build/fixedLengthParser.d.ts +2 -0
  65. package/build/fixedLengthParser.js +12 -0
  66. package/build/fixedLengthSequenceParser.d.ts +2 -0
  67. package/build/fixedLengthSequenceParser.js +16 -0
  68. package/build/index.d.ts +18 -0
  69. package/build/index.js +17 -0
  70. package/build/index.test.d.ts +1 -0
  71. package/build/index.test.js +2 -0
  72. package/build/inputChunkBuffer.d.ts +15 -0
  73. package/build/inputChunkBuffer.js +40 -0
  74. package/build/inputChunkBuffer.test.d.ts +1 -0
  75. package/build/inputChunkBuffer.test.js +34 -0
  76. package/build/inputCompanion.d.ts +18 -0
  77. package/build/inputCompanion.js +28 -0
  78. package/build/inputReader.d.ts +22 -0
  79. package/build/inputReader.js +105 -0
  80. package/build/inputReader.test.d.ts +1 -0
  81. package/build/inputReader.test.js +174 -0
  82. package/build/invariantDefined.d.ts +1 -0
  83. package/build/invariantDefined.js +5 -0
  84. package/build/invariantIdentity.d.ts +3 -0
  85. package/build/invariantIdentity.js +5 -0
  86. package/build/jsonParser.d.ts +3 -0
  87. package/build/jsonParser.js +133 -0
  88. package/build/jsonParser.test.d.ts +1 -0
  89. package/build/jsonParser.test.js +17 -0
  90. package/build/jsonParser2.d.ts +3 -0
  91. package/build/jsonParser2.js +52 -0
  92. package/build/jsonParser2.test.d.ts +1 -0
  93. package/build/jsonParser2.test.js +22 -0
  94. package/build/listParser.d.ts +2 -0
  95. package/build/listParser.js +34 -0
  96. package/build/negativeLookahead.d.ts +2 -0
  97. package/build/negativeLookahead.js +20 -0
  98. package/build/optionalParser.d.ts +2 -0
  99. package/build/optionalParser.js +23 -0
  100. package/build/parser.d.ts +10 -0
  101. package/build/parser.js +53 -0
  102. package/build/parser.test.d.ts +1 -0
  103. package/build/parser.test.js +126 -0
  104. package/build/parserAccessorParser.d.ts +2 -0
  105. package/build/parserAccessorParser.js +1 -0
  106. package/build/parserCompose.d.ts +3 -0
  107. package/build/parserCompose.js +7 -0
  108. package/build/parserContext.d.ts +48 -0
  109. package/build/parserContext.js +193 -0
  110. package/build/parserContext.test.d.ts +1 -0
  111. package/build/parserContext.test.js +115 -0
  112. package/build/parserCreatorCompose.d.ts +3 -0
  113. package/build/parserCreatorCompose.js +10 -0
  114. package/build/parserError.d.ts +43 -0
  115. package/build/parserError.js +61 -0
  116. package/build/parserImplementationInvariant.d.ts +2 -0
  117. package/build/parserImplementationInvariant.js +5 -0
  118. package/build/parserImplementationInvariantInvariant.d.ts +3 -0
  119. package/build/parserImplementationInvariantInvariant.js +15 -0
  120. package/build/parserInvariant.d.ts +4 -0
  121. package/build/parserInvariant.js +11 -0
  122. package/build/parserParsingInvariant.d.ts +1 -0
  123. package/build/parserParsingInvariant.js +1 -0
  124. package/build/promiseCompose.d.ts +1 -0
  125. package/build/promiseCompose.js +3 -0
  126. package/build/promiseFish.d.ts +1 -0
  127. package/build/promiseFish.js +3 -0
  128. package/build/sequence.d.ts +1 -0
  129. package/build/sequence.js +1 -0
  130. package/build/sequenceBuffer.d.ts +15 -0
  131. package/build/sequenceBuffer.js +40 -0
  132. package/build/sequenceBuffer.test.d.ts +1 -0
  133. package/build/sequenceBuffer.test.js +34 -0
  134. package/build/sequenceParser.d.ts +3 -0
  135. package/build/sequenceParser.js +10 -0
  136. package/build/skipParser.d.ts +2 -0
  137. package/build/skipParser.js +8 -0
  138. package/build/sliceBoundedParser.d.ts +2 -0
  139. package/build/sliceBoundedParser.js +24 -0
  140. package/build/sliceBoundedParser.test.d.ts +1 -0
  141. package/build/sliceBoundedParser.test.js +24 -0
  142. package/build/terminatedArrayParser.d.ts +2 -0
  143. package/build/terminatedArrayParser.js +27 -0
  144. package/build/terminatedSequenceParser.d.ts +2 -0
  145. package/build/terminatedSequenceParser.js +24 -0
  146. package/build/tupleParser.d.ts +11 -0
  147. package/build/tupleParser.js +17 -0
  148. package/build/unionParser.d.ts +2 -0
  149. package/build/unionParser.js +68 -0
  150. package/build/zip.d.ts +31 -0
  151. package/build/zip.js +1 -0
  152. package/build/zipEntry.d.ts +28 -0
  153. package/build/zipEntry.js +1 -0
  154. package/build/zipFile.d.ts +32 -0
  155. package/build/zipFile.js +1 -0
  156. package/build/zipFileEntry.d.ts +6 -0
  157. package/build/zipFileEntry.js +1 -0
  158. package/build/zipParser.d.ts +70 -0
  159. package/build/zipParser.js +255 -0
  160. package/build/zipParser.test.d.ts +1 -0
  161. package/build/zipParser.test.js +22 -0
  162. package/package.json +52 -0
  163. package/readme.md +17 -0
  164. package/renovate.json +6 -0
  165. package/src/allSettledStream.test.ts +59 -0
  166. package/src/allSettledStream.test.ts.md +52 -0
  167. package/src/allSettledStream.test.ts.snap +0 -0
  168. package/src/allSettledStream.ts +44 -0
  169. package/src/apk.ts +16 -0
  170. package/src/apkParser.test.ts +30 -0
  171. package/src/apkParser.test.ts.md +268 -0
  172. package/src/apkParser.test.ts.snap +0 -0
  173. package/src/apkParser.ts +327 -0
  174. package/src/arbitrarilySlicedAsyncInterable.ts +73 -0
  175. package/src/arbitrarilySlicedAsyncInterator.ts +25 -0
  176. package/src/arbitraryDosDateTime.ts +10 -0
  177. package/src/arbitraryFileSystemEntry.ts +36 -0
  178. package/src/arbitraryZip.ts +132 -0
  179. package/src/arbitraryZipPermissions.ts +25 -0
  180. package/src/arbitraryZipStream.ts +60 -0
  181. package/src/arrayParser.test.ts +11 -0
  182. package/src/arrayParser.ts +35 -0
  183. package/src/bsonParser.test.ts +37 -0
  184. package/src/bsonParser.ts +131 -0
  185. package/src/debugLogParser.ts +51 -0
  186. package/src/disjunctionParser.ts +55 -0
  187. package/src/elementParser.ts +4 -0
  188. package/src/endOfInputParser.ts +11 -0
  189. package/src/exactElementParser.ts +20 -0
  190. package/src/exactSequenceParser.ts +27 -0
  191. package/src/fixedLengthSequenceParser.ts +24 -0
  192. package/src/index.test.ts +3 -0
  193. package/src/index.ts +76 -0
  194. package/src/inputCompanion.ts +43 -0
  195. package/src/inputReader.test.ts +238 -0
  196. package/src/inputReader.ts +159 -0
  197. package/src/invariantDefined.ts +6 -0
  198. package/src/invariantIdentity.ts +8 -0
  199. package/src/jsonParser.test.ts +26 -0
  200. package/src/jsonParser.ts +225 -0
  201. package/src/listParser.ts +52 -0
  202. package/src/negativeLookahead.ts +26 -0
  203. package/src/optionalParser.ts +27 -0
  204. package/src/parser.test.ts +176 -0
  205. package/src/parser.test.ts.md +68 -0
  206. package/src/parser.test.ts.snap +0 -0
  207. package/src/parser.ts +103 -0
  208. package/src/parserAccessorParser.ts +3 -0
  209. package/src/parserContext.test.ts +154 -0
  210. package/src/parserContext.ts +316 -0
  211. package/src/parserCreatorCompose.ts +23 -0
  212. package/src/parserError.ts +85 -0
  213. package/src/parserImplementationInvariant.ts +6 -0
  214. package/src/parserInvariant.ts +26 -0
  215. package/src/promiseCompose.ts +7 -0
  216. package/src/sequence.ts +10 -0
  217. package/src/sequenceBuffer.test.ts +50 -0
  218. package/src/sequenceBuffer.ts +58 -0
  219. package/src/skipParser.ts +12 -0
  220. package/src/sliceBoundedParser.test.ts +28 -0
  221. package/src/sliceBoundedParser.ts +30 -0
  222. package/src/terminatedArrayParser.ts +40 -0
  223. package/src/tupleParser.ts +33 -0
  224. package/src/unionParser.ts +104 -0
  225. package/src/zip.ts +48 -0
  226. package/src/zipParser.test.ts +31 -0
  227. package/src/zipParser.ts +501 -0
  228. package/tsconfig.json +109 -0
@@ -0,0 +1,154 @@
1
+ import test from 'ava';
2
+ import { ParserContextImplementation } from './parserContext.js';
3
+ import { stringInputCompanion } from './inputCompanion.js';
4
+ import { InputReaderImplementation } from './inputReader.js';
5
+ import { ParserUnexpectedEndOfInputError } from './parserError.js';
6
+
7
+ const commonParserContextArguments = [
8
+ undefined,
9
+ {
10
+ debugName: 'root',
11
+ errorJoinMode: 'all',
12
+ },
13
+ ] as const;
14
+
15
+ test('parserContext.read', async t => {
16
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function * () {
17
+ yield '';
18
+ yield 'abc';
19
+ yield 'def';
20
+ yield '';
21
+ yield 'gh';
22
+ })()), ...commonParserContextArguments);
23
+
24
+ t.is(await parserContext.read(0), 'a');
25
+ t.is(await parserContext.read(0), 'b');
26
+ t.is(await parserContext.read(5), 'h');
27
+
28
+ await t.throwsAsync(async () => parserContext.read(0), {
29
+ instanceOf: ParserUnexpectedEndOfInputError,
30
+ });
31
+ });
32
+
33
+ test('parserContext.lookahead', async t => {
34
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function * () {
35
+ yield * 'abcdefgh';
36
+ })()), ...commonParserContextArguments);
37
+
38
+ const lookaheadContext1 = parserContext.lookahead();
39
+ const lookaheadContext2 = parserContext.lookahead();
40
+ const lookaheadContext3 = parserContext.lookahead({
41
+ sliceEnd: 3,
42
+ });
43
+
44
+ t.is(await lookaheadContext3.peek(2), 'c');
45
+ t.is(await lookaheadContext3.peek(3), undefined);
46
+ t.is(await lookaheadContext3.read(0), 'a');
47
+ t.is(await lookaheadContext3.read(0), 'b');
48
+ t.is(await lookaheadContext3.read(0), 'c');
49
+ t.is(await lookaheadContext3.peek(0), undefined);
50
+
51
+ t.is(await parserContext.peek(0), 'a');
52
+ t.is(await lookaheadContext1.peek(0), 'a');
53
+ t.is(await lookaheadContext2.peek(0), 'a');
54
+
55
+ t.is(await lookaheadContext1.read(0), 'a');
56
+ t.is(await parserContext.peek(0), 'a');
57
+ t.is(await lookaheadContext1.peek(0), 'b');
58
+ t.is(await lookaheadContext2.peek(0), 'a');
59
+
60
+ t.is(await parserContext.read(0), 'a');
61
+
62
+ t.is(parserContext.position, 1);
63
+ t.is(lookaheadContext1.position, 1);
64
+ t.is(lookaheadContext2.position, 0);
65
+ t.is(lookaheadContext3.position, 3);
66
+ });
67
+
68
+ test('parserContext.unlookahead', async t => {
69
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function * () {
70
+ yield * 'abcdefgh';
71
+ })()), ...commonParserContextArguments);
72
+
73
+ const lookaheadContext = parserContext.lookahead();
74
+
75
+ t.is(await parserContext.peek(0), 'a');
76
+ t.is(await lookaheadContext.peek(0), 'a');
77
+
78
+ t.is(await lookaheadContext.read(0), 'a');
79
+ t.is(await parserContext.peek(0), 'a');
80
+ t.is(await lookaheadContext.peek(0), 'b');
81
+
82
+ lookaheadContext.unlookahead();
83
+
84
+ t.is(await lookaheadContext.read(0), 'b');
85
+ t.is(await lookaheadContext.read(0), 'c');
86
+ });
87
+
88
+ test('parserContext.unlookahead while peeking', async t => {
89
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function * () {
90
+ yield * 'abcdefgh';
91
+ })()), ...commonParserContextArguments);
92
+
93
+ const lookaheadContext = parserContext.lookahead();
94
+
95
+ parserContext.skip(1);
96
+ lookaheadContext.skip(2);
97
+
98
+ const peekPromise = lookaheadContext.peek(0);
99
+
100
+ lookaheadContext.unlookahead();
101
+
102
+ t.is(await peekPromise, 'c');
103
+ });
104
+
105
+ test('parserContext deep unlookahead normal order', async t => {
106
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function * () {
107
+ yield * 'abcdefgh';
108
+ })()), ...commonParserContextArguments);
109
+
110
+ const child = parserContext.lookahead();
111
+
112
+ t.is(await child.read(0), 'a');
113
+
114
+ const grandchild = child.lookahead();
115
+
116
+ t.is(await grandchild.read(0), 'b');
117
+
118
+ grandchild.unlookahead();
119
+
120
+ t.is(await child.read(0), 'c');
121
+
122
+ child.unlookahead();
123
+
124
+ t.is(await parserContext.read(0), 'd');
125
+ });
126
+
127
+ test('parserContext deep unlookahead weird order', async t => {
128
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function * () {
129
+ yield * 'abcdefgh';
130
+ })()), ...commonParserContextArguments);
131
+
132
+ const child = parserContext.lookahead({
133
+ debugName: 'child',
134
+ });
135
+ const grandchild = child.lookahead({
136
+ debugName: 'grandchild',
137
+ });
138
+ const greatGrandchild = grandchild.lookahead({
139
+ debugName: 'greatGrandchild',
140
+ });
141
+
142
+ t.is(await greatGrandchild.read(0), 'a');
143
+
144
+ grandchild.unlookahead();
145
+
146
+ child.unlookahead();
147
+
148
+ greatGrandchild.unlookahead();
149
+
150
+ t.is(await greatGrandchild.read(0), 'b');
151
+ t.is(await grandchild.read(0), 'c');
152
+ t.is(await child.read(0), 'd');
153
+ t.is(await parserContext.read(0), 'e');
154
+ });
@@ -0,0 +1,316 @@
1
+ import invariant from 'invariant';
2
+ import { type InputCompanion } from './inputCompanion.js';
3
+ import { type InputReader } from './inputReader.js';
4
+ import { ParserParsingFailedError, ParserUnexpectedEndOfInputError, ParserParsingInvariantError, ParserParsingJoinNoneError, ParserParsingJoinAllError, ParserParsingJoinDeepestError, ParserParsingJoinFurthestError } from './parserError.js';
5
+ import { RunParserOptions } from './parser.js';
6
+ import { Falsy, parserInvariant, ValueOrAccessor } from './parserInvariant.js';
7
+
8
+ type LookaheadOptions = {
9
+ debugName?: string;
10
+ sliceEnd?: number;
11
+ };
12
+
13
+ type ParserContextOptions<Sequence, Element> =
14
+ & RunParserOptions<unknown, Sequence, Element>
15
+ & LookaheadOptions
16
+ ;
17
+
18
+ export type ParserContext<Sequence, Element> = {
19
+ from(elements: Element[]): Sequence;
20
+ length(sequence: Sequence): number;
21
+ at(sequence: Sequence, index: number): Element | undefined;
22
+
23
+ get position(): number;
24
+ peek(offset: number): Promise<Element | undefined>;
25
+ skip(offset: number): void;
26
+
27
+ read(offset: number): Promise<Element>;
28
+
29
+ lookahead(options?: LookaheadOptions): ParserContext<Sequence, Element>;
30
+ unlookahead(): void;
31
+ dispose(): void;
32
+
33
+ invariant<T>(value: T, format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy>;
34
+ invariantJoin<T>(value: T, childErrors: ParserParsingFailedError[], format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy>;
35
+ };
36
+
37
+ let parserContextId = 0;
38
+
39
+ export class ParserContextImplementation<Sequence, Element> implements ParserContext<Sequence, Element> {
40
+ private readonly _id = parserContextId++;
41
+ private readonly _depth: number;
42
+
43
+ private _exclusiveChildParserContext: ParserContext<Sequence, Element> | undefined = undefined;
44
+
45
+ constructor(
46
+ private readonly _inputCompanion: InputCompanion<Sequence, Element>,
47
+ private _inputReader: InputReader<Sequence, Element>,
48
+ private _parentParserContext: ParserContextImplementation<Sequence, Element> | undefined = undefined,
49
+ private readonly _options: ParserContextOptions<Sequence, Element>,
50
+ ) {
51
+ this._depth = _parentParserContext ? _parentParserContext._depth + 1 : 0;
52
+ }
53
+
54
+ get [Symbol.toStringTag]() {
55
+ return [
56
+ 'ParserContext',
57
+ [
58
+ this._options.debugName,
59
+ '(',
60
+ this._id,
61
+ ')',
62
+ ].join(''),
63
+ this._inputReader.toString(),
64
+ ].join(' ');
65
+ }
66
+
67
+ from(elements: Element[]): Sequence {
68
+ return this._inputCompanion.from(elements);
69
+ }
70
+
71
+ length(sequence: Sequence): number {
72
+ return this._inputCompanion.length(sequence);
73
+ }
74
+
75
+ at(sequence: Sequence, index: number): Element | undefined {
76
+ return this._inputCompanion.at(sequence, index);
77
+ }
78
+
79
+ get position() {
80
+ return this._inputReader.position;
81
+ }
82
+
83
+ async peek(offset: number): Promise<Element | undefined> {
84
+ if (
85
+ this._options.sliceEnd !== undefined
86
+ && (this.position + offset) >= this._options.sliceEnd
87
+ ) {
88
+ return undefined;
89
+ }
90
+
91
+ return this._inputReader.peek(offset);
92
+ }
93
+
94
+ skip(offset: number) {
95
+ this._inputReader.skip(offset);
96
+ }
97
+
98
+ async read(offset: number): Promise<Element> {
99
+ const element = await this.peek(offset);
100
+
101
+ if (element === undefined) {
102
+ throw new ParserUnexpectedEndOfInputError('', this._depth, this.position);
103
+ }
104
+
105
+ this.skip(offset + 1);
106
+
107
+ return element;
108
+ }
109
+
110
+ lookahead(options: LookaheadOptions = {}): ParserContext<Sequence, Element> {
111
+ const lookaheadInputReader = this._inputReader.lookahead();
112
+
113
+ if (this.position !== lookaheadInputReader.position) {
114
+ debugger;
115
+ }
116
+
117
+ invariant(
118
+ this.position === lookaheadInputReader.position,
119
+ 'lookahead this.position (%s) === lookaheadInputReader.position (%s)',
120
+ this.position,
121
+ lookaheadInputReader.position,
122
+ );
123
+
124
+ const lookaheadParserContext = new ParserContextImplementation(
125
+ this._inputCompanion,
126
+ lookaheadInputReader,
127
+ this,
128
+ {
129
+ ...this._options,
130
+ ...options,
131
+ debugName: [
132
+ this._options.debugName,
133
+ '(',
134
+ this._id,
135
+ ')',
136
+ '/',
137
+ options.debugName,
138
+ ].join(''),
139
+ },
140
+ );
141
+
142
+ if (this.position !== lookaheadParserContext.position) {
143
+ debugger;
144
+ }
145
+
146
+ invariant(
147
+ this.position === lookaheadParserContext.position,
148
+ 'lookahead this.position (%s) === lookaheadParserContext.position (%s)',
149
+ this.position,
150
+ lookaheadParserContext.position,
151
+ );
152
+
153
+ return lookaheadParserContext;
154
+ }
155
+
156
+ unlookahead() {
157
+ invariant(this._parentParserContext !== undefined, 'this._parentParserContext !== undefined');
158
+ invariant(
159
+ (
160
+ this._parentParserContext._exclusiveChildParserContext === undefined
161
+ || this._parentParserContext._exclusiveChildParserContext === this
162
+ ),
163
+ [
164
+ 'Parent\'s exclusive child must be undefined or this',
165
+ 'this: %s',
166
+ 'parent: %s',
167
+ 'parent.exclusiveChild: %s',
168
+ ].join('\n'),
169
+ this.toString(),
170
+ this._parentParserContext.toString(),
171
+ this._parentParserContext._exclusiveChildParserContext?.toString(),
172
+ );
173
+ invariant(
174
+ this._parentParserContext.position <= this.position,
175
+ 'unlookahead this._parentParserContext.position (%s) <= this.position (%s)',
176
+ this._parentParserContext.position,
177
+ this.position,
178
+ );
179
+
180
+ const offset = this._inputReader.position - this._parentParserContext._inputReader.position;
181
+
182
+ this._parentParserContext.skip(offset);
183
+
184
+ invariant(
185
+ this._parentParserContext.position === this.position,
186
+ 'unlookahead this._parentParserContext.position (%s) === this.position (%s)',
187
+ this._parentParserContext.position,
188
+ this.position,
189
+ );
190
+
191
+ this._inputReader = this._parentParserContext._inputReader;
192
+ this._parentParserContext._exclusiveChildParserContext = this;
193
+
194
+ if (this._exclusiveChildParserContext) {
195
+ this._exclusiveChildParserContext.unlookahead();
196
+ }
197
+ }
198
+
199
+ dispose() {
200
+ invariant(this._parentParserContext !== undefined, 'this._parentParserContext !== undefined');
201
+ invariant(
202
+ (
203
+ this._parentParserContext._exclusiveChildParserContext === undefined
204
+ || this._parentParserContext._exclusiveChildParserContext === this
205
+ ),
206
+ [
207
+ 'Parent\'s exclusive child must be undefined or this',
208
+ 'this: %s',
209
+ 'parent: %s',
210
+ 'parent.exclusiveChild: %s',
211
+ ].join('\n'),
212
+ this.toString(),
213
+ this._parentParserContext.toString(),
214
+ this._parentParserContext._exclusiveChildParserContext?.toString(),
215
+ );
216
+
217
+ this._parentParserContext._exclusiveChildParserContext = undefined;
218
+ this._parentParserContext = undefined;
219
+ }
220
+
221
+ invariant<T>(value: T, format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy> {
222
+ const parserContext = this;
223
+
224
+ return parserInvariant(function (message: string) {
225
+ return new ParserParsingInvariantError(message, parserContext._depth, parserContext.position);
226
+ }, value, format, ...formatArguments);
227
+ }
228
+
229
+ invariantJoin<T>(value: T, childErrors: ParserParsingFailedError[], format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy> {
230
+ invariant(childErrors.length > 0, 'childErrors.length > 0');
231
+
232
+ const errorJoinMode = this._options.errorJoinMode ?? 'none';
233
+ const parserContext = this;
234
+
235
+ if (errorJoinMode === 'none') {
236
+ return parserInvariant(function (message: string) {
237
+ return new ParserParsingJoinNoneError(message, parserContext._depth, parserContext.position);
238
+ }, value, format, ...formatArguments);
239
+ }
240
+
241
+ if (errorJoinMode === 'furthest') {
242
+ return parserInvariant(function (message: string) {
243
+ let furthestPosition = 0;
244
+ let furthestChildErrors: ParserParsingFailedError[] = [];
245
+
246
+ for (const childError of childErrors) {
247
+ if (childError.position < furthestPosition) {
248
+ continue;
249
+ }
250
+
251
+ if (childError.position > furthestPosition) {
252
+ furthestPosition = childError.position;
253
+ furthestChildErrors = [ childError ];
254
+ continue;
255
+ }
256
+
257
+ furthestChildErrors.push(childError);
258
+ }
259
+
260
+ message += [
261
+ '',
262
+ 'Furthest child error stacks, indented:',
263
+ ...furthestChildErrors.flatMap(furthestChildError => furthestChildError.stack?.split('\n').map(line => ' ' + line)),
264
+ 'End of furthest child error stacks',
265
+ ].join('\n');
266
+
267
+ return new ParserParsingJoinFurthestError(message, parserContext._depth, furthestPosition, furthestChildErrors);
268
+ }, value, format, ...formatArguments);
269
+ }
270
+
271
+ if (errorJoinMode === 'deepest') {
272
+ return parserInvariant(function (message: string) {
273
+ let deepestDepth = 0;
274
+ let deepestChildErrors: ParserParsingFailedError[] = [];
275
+
276
+ for (const childError of childErrors) {
277
+ if (childError.depth < deepestDepth) {
278
+ continue;
279
+ }
280
+
281
+ if (childError.depth > deepestDepth) {
282
+ deepestDepth = childError.depth;
283
+ deepestChildErrors = [ childError ];
284
+ continue;
285
+ }
286
+
287
+ deepestChildErrors.push(childError);
288
+ }
289
+
290
+ message += [
291
+ '',
292
+ 'Deepest child error stacks, indented:',
293
+ ...deepestChildErrors.flatMap(deepestChildError => deepestChildError.stack?.split('\n').map(line => ' ' + line)),
294
+ 'End of deepest child error stacks',
295
+ ].join('\n');
296
+
297
+ return new ParserParsingJoinDeepestError(message, deepestDepth, parserContext.position, deepestChildErrors);
298
+ }, value, format, ...formatArguments);
299
+ }
300
+
301
+ if (errorJoinMode === 'all') {
302
+ return parserInvariant(function (message: string) {
303
+ message += [
304
+ '',
305
+ 'Child error stacks, indented:',
306
+ ...childErrors.flatMap(childError => childError.stack?.split('\n').map(line => ' ' + line)),
307
+ 'End of child error stacks',
308
+ ].join('\n');
309
+
310
+ return new ParserParsingJoinAllError(message, parserContext._depth, parserContext.position, childErrors);
311
+ }, value, format, ...formatArguments);
312
+ }
313
+
314
+ invariant(false, 'Unsupported errorJoinMode: %s', errorJoinMode);
315
+ }
316
+ }
@@ -0,0 +1,23 @@
1
+ import { Parser } from "./parser.js";
2
+ import { DeriveSequenceElement } from "./sequence.js";
3
+
4
+ export function parserCreatorCompose<
5
+ Arguments extends unknown[],
6
+ OutputA,
7
+ OutputB,
8
+ Sequence,
9
+ Element = DeriveSequenceElement<Sequence>,
10
+ >(
11
+ f1: (...args: Arguments) => Parser<OutputA, Sequence, Element>,
12
+ f2: (outputA: OutputA) => Parser<OutputB, Sequence, Element>,
13
+ ): (...args: Arguments) => Parser<OutputB, Sequence, Element> {
14
+ return (...args) => {
15
+ const parserA = f1(...args);
16
+
17
+ return async parserContext => {
18
+ const outputA = await parserA(parserContext);
19
+ const parserB = f2(outputA);
20
+ return parserB(parserContext);
21
+ };
22
+ };
23
+ }
@@ -0,0 +1,85 @@
1
+
2
+ export class ParserError extends Error {
3
+ name = 'ParserError';
4
+ }
5
+
6
+ export class ParserImplementationError extends ParserError {
7
+ name = 'ParserImplementationError';
8
+ }
9
+ export class ParserImplementationInvariantError extends ParserImplementationError {
10
+ name = 'ParserImplementationInvariantError';
11
+ }
12
+
13
+ export class ParserParsingFailedError extends ParserError {
14
+ name = 'ParserParsingFailedError';
15
+
16
+ constructor(
17
+ message: string,
18
+ public readonly depth: number,
19
+ public readonly position: number,
20
+ ) {
21
+ super([
22
+ '(position: ',
23
+ position,
24
+ ') ',
25
+ message,
26
+ ].join(''));
27
+ }
28
+ }
29
+
30
+ export class ParserParsingJoinError extends ParserParsingFailedError {
31
+ name = 'ParserParsingJoinError';
32
+
33
+ public readonly childErrors: ParserParsingFailedError[] = [];
34
+ }
35
+
36
+ export class ParserParsingJoinNoneError extends ParserParsingJoinError {
37
+ name = 'ParserParsingJoinNoneError';
38
+ }
39
+
40
+ export class ParserParsingJoinAllError extends ParserParsingJoinError {
41
+ name = 'ParserParsingJoinAllError';
42
+
43
+ constructor(
44
+ message: string,
45
+ depth: number,
46
+ position: number,
47
+ public readonly childErrors: ParserParsingFailedError[],
48
+ ) {
49
+ super(message, depth, position);
50
+ }
51
+ }
52
+
53
+ export class ParserParsingJoinDeepestError extends ParserParsingJoinError {
54
+ name = 'ParserParsingJoinDeepestError';
55
+
56
+ constructor(
57
+ message: string,
58
+ depth: number,
59
+ position: number,
60
+ public readonly childErrors: ParserParsingFailedError[],
61
+ ) {
62
+ super(message, depth, position);
63
+ }
64
+ }
65
+
66
+ export class ParserParsingJoinFurthestError extends ParserParsingJoinError {
67
+ name = 'ParserParsingJoinFurthestError';
68
+
69
+ constructor(
70
+ message: string,
71
+ depth: number,
72
+ position: number,
73
+ public readonly childErrors: ParserParsingFailedError[],
74
+ ) {
75
+ super(message, depth, position);
76
+ }
77
+ }
78
+
79
+ export class ParserParsingInvariantError extends ParserParsingFailedError {
80
+ name = 'ParserParsingInvariantError';
81
+ }
82
+
83
+ export class ParserUnexpectedEndOfInputError extends ParserParsingFailedError {
84
+ name = 'ParserUnexpectedEndOfInputError';
85
+ }
@@ -0,0 +1,6 @@
1
+ import { ParserImplementationInvariantError } from './parserError.js';
2
+ import { type Falsy, parserInvariant, type ValueOrAccessor } from './parserInvariant.js';
3
+
4
+ export function parserImplementationInvariant<T>(value: T, format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy> {
5
+ return parserInvariant(ParserImplementationInvariantError, value, format, ...formatArguments);
6
+ }
@@ -0,0 +1,26 @@
1
+ import { type Constructor } from 'type-fest';
2
+
3
+ export type Falsy = '' | 0 | false | undefined;
4
+
5
+ export type ValueOrAccessor<T> = T | (() => T);
6
+
7
+ export function parserInvariant<T>(
8
+ ErrorConstructor: Constructor<Error, [message: string]> | ((message: string) => Error),
9
+ value: T,
10
+ formatOrFormatLines: ValueOrAccessor<string | string[]>,
11
+ ...formatArguments: any[]
12
+ ): Exclude<T, Falsy> {
13
+ if (value) {
14
+ return value as any;
15
+ }
16
+
17
+ let format = typeof formatOrFormatLines === 'function' ? formatOrFormatLines() : formatOrFormatLines;
18
+ format = Array.isArray(format) ? format.join('\n') : format;
19
+
20
+ throw new (ErrorConstructor as Constructor<Error>)(
21
+ format.replaceAll('%s', () => {
22
+ const argumentOrAccessor = formatArguments.shift();
23
+ return typeof argumentOrAccessor === 'function' ? argumentOrAccessor() : argumentOrAccessor;
24
+ }),
25
+ );
26
+ }
@@ -0,0 +1,7 @@
1
+
2
+ export function promiseCompose<A, B, C>(
3
+ f1: (a: A) => Promise<B>,
4
+ f2: (b: B) => C | Promise<C>,
5
+ ): (a: A) => Promise<C> {
6
+ return async a => f1(a).then(f2);
7
+ }
@@ -0,0 +1,10 @@
1
+
2
+ export type DeriveSequenceElement<Sequence> = (
3
+ Sequence extends string
4
+ ? string
5
+ : (
6
+ Sequence extends Uint8Array
7
+ ? number
8
+ : never
9
+ )
10
+ );
@@ -0,0 +1,50 @@
1
+ import test from 'ava';
2
+ import { SequenceBufferImplementation } from './sequenceBuffer.js';
3
+ import { stringInputCompanion } from './inputCompanion.js';
4
+
5
+ test('sequenceBuffer', t => {
6
+ const sequenceBuffer = new SequenceBufferImplementation(stringInputCompanion);
7
+
8
+ t.is(sequenceBuffer.peek(0), undefined);
9
+
10
+ sequenceBuffer.push('');
11
+
12
+ t.is(sequenceBuffer.peek(0), undefined);
13
+
14
+ sequenceBuffer.push('abc');
15
+
16
+ t.is(sequenceBuffer.peek(0), 'a');
17
+ t.is(sequenceBuffer.peek(1), 'b');
18
+ t.is(sequenceBuffer.peek(2), 'c');
19
+ t.is(sequenceBuffer.peek(3), undefined);
20
+
21
+ sequenceBuffer.push('def');
22
+
23
+ t.is(sequenceBuffer.peek(0), 'a');
24
+ t.is(sequenceBuffer.peek(3), 'd');
25
+ t.is(sequenceBuffer.peek(6), undefined);
26
+
27
+ sequenceBuffer.push('');
28
+
29
+ t.is(sequenceBuffer.peek(0), 'a');
30
+ t.is(sequenceBuffer.peek(3), 'd');
31
+ t.is(sequenceBuffer.peek(6), undefined);
32
+
33
+ sequenceBuffer.skip(1);
34
+
35
+ t.is(sequenceBuffer.peek(0), 'b');
36
+ t.is(sequenceBuffer.peek(3), 'e');
37
+ t.is(sequenceBuffer.peek(5), undefined);
38
+
39
+ sequenceBuffer.skip(3);
40
+
41
+ t.is(sequenceBuffer.peek(0), 'e');
42
+ t.is(sequenceBuffer.peek(2), undefined);
43
+
44
+ sequenceBuffer.push('gh');
45
+
46
+ t.is(sequenceBuffer.peek(0), 'e');
47
+ t.is(sequenceBuffer.peek(2), 'g');
48
+ t.is(sequenceBuffer.peek(3), 'h');
49
+ t.is(sequenceBuffer.peek(4), undefined);
50
+ });