@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,23 @@
1
+ import { getParserName, setParserName } from "./parser.js";
2
+ import { ParserParsingFailedError } from "./parserError.js";
3
+ export const createOptionalParser = (childParser) => {
4
+ const optionalParser = async (parserContext) => {
5
+ const childParserContext = parserContext.lookahead();
6
+ try {
7
+ const value = await childParser(childParserContext);
8
+ childParserContext.unlookahead();
9
+ return value;
10
+ }
11
+ catch (error) {
12
+ if (error instanceof ParserParsingFailedError) {
13
+ return undefined;
14
+ }
15
+ throw error;
16
+ }
17
+ finally {
18
+ childParserContext.dispose();
19
+ }
20
+ };
21
+ setParserName(optionalParser, getParserName(childParser, 'anonymousOptionalChild') + '?');
22
+ return optionalParser;
23
+ };
@@ -0,0 +1,10 @@
1
+ import { type InputCompanion } from './inputCompanion.js';
2
+ import { type ParserContext } from './parserContext.js';
3
+ import { DeriveSequenceElement } from './sequence.js';
4
+ export type Parser<Output, Sequence, Element = DeriveSequenceElement<Sequence>> = (parserContext: ParserContext<Sequence, Element>) => Promise<Output>;
5
+ export declare function getParserName(parser: Parser<any, any, any>, default_?: string): string;
6
+ export declare function setParserName<Output, Sequence, Element = DeriveSequenceElement<Sequence>>(parser: Parser<Output, Sequence, Element>, name: string): Parser<Output, Sequence, Element>;
7
+ export type RunParserOptions<Output, Sequence, Element = DeriveSequenceElement<Sequence>> = {
8
+ errorJoinMode?: 'none' | 'deepest' | 'furthest' | 'all';
9
+ };
10
+ export declare function runParser<Output, Sequence, Element = DeriveSequenceElement<Sequence>>(parser: Parser<Output, Sequence, Element>, input: AsyncIterator<Sequence> | AsyncIterable<Sequence> | Iterable<Sequence> | Sequence, inputCompanion: InputCompanion<Sequence, Element>, options?: RunParserOptions<Output, Sequence, Element>): Promise<Output>;
@@ -0,0 +1,53 @@
1
+ import invariant from 'invariant';
2
+ import { InputReaderImplementation } from './inputReader.js';
3
+ import { ParserContextImplementation } from './parserContext.js';
4
+ export function getParserName(parser, default_ = 'anonymous') {
5
+ return parser.name || default_;
6
+ }
7
+ export function setParserName(parser, name) {
8
+ Object.defineProperty(parser, 'name', {
9
+ value: name,
10
+ });
11
+ return parser;
12
+ }
13
+ function isAsyncIterable(value) {
14
+ return value && typeof value[Symbol.asyncIterator] === 'function';
15
+ }
16
+ function isIterable(value) {
17
+ return value && typeof value[Symbol.iterator] === 'function';
18
+ }
19
+ function isIterator(value) {
20
+ return value && typeof value.next === 'function';
21
+ }
22
+ function iteratorToAsyncIterator(iterator) {
23
+ return {
24
+ next: async () => iterator.next(),
25
+ };
26
+ }
27
+ function toAsyncIterator(value) {
28
+ if (typeof value === 'string'
29
+ || value instanceof Uint8Array) {
30
+ return (async function* () {
31
+ yield value;
32
+ })();
33
+ }
34
+ if (isAsyncIterable(value)) {
35
+ return value[Symbol.asyncIterator]();
36
+ }
37
+ if (isIterable(value)) {
38
+ return iteratorToAsyncIterator(value[Symbol.iterator]());
39
+ }
40
+ if (isIterator(value)) {
41
+ return iteratorToAsyncIterator(value);
42
+ }
43
+ invariant(false, 'Value must be an async iterator, async iterable, iterable or iterator got %s.', value);
44
+ }
45
+ export async function runParser(parser, input, inputCompanion, options = {}) {
46
+ const inputAsyncIterator = toAsyncIterator(input);
47
+ const inputReader = new InputReaderImplementation(inputCompanion, inputAsyncIterator);
48
+ const parserContext = new ParserContextImplementation(inputCompanion, inputReader, undefined, {
49
+ ...options,
50
+ debugName: 'root',
51
+ });
52
+ return parser(parserContext);
53
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,126 @@
1
+ import test from 'ava';
2
+ import { createUnionParser } from './unionParser.js';
3
+ import { runParser } from './parser.js';
4
+ import { stringInputCompanion, uint8ArrayInputCompanion } from './inputCompanion.js';
5
+ import { ParserParsingInvariantError, ParserParsingJoinAllError, ParserParsingJoinDeepestError, ParserParsingJoinError, ParserParsingJoinFurthestError, ParserParsingJoinNoneError } from './parserError.js';
6
+ import { createTupleParser } from './tupleParser.js';
7
+ import { promiseCompose } from './promiseCompose.js';
8
+ import { createDisjunctionParser } from './disjunctionParser.js';
9
+ import invariant from 'invariant';
10
+ import { createExactSequenceParser } from './exactSequenceParser.js';
11
+ import { createArrayParser } from './arrayParser.js';
12
+ import { createElementParser } from './elementParser.js';
13
+ const aUnionParser = createUnionParser([
14
+ createExactSequenceParser('1'),
15
+ createExactSequenceParser('aa'),
16
+ createExactSequenceParser('AAA'),
17
+ ]);
18
+ const abDisjunctionParser = createDisjunctionParser([
19
+ aUnionParser,
20
+ createExactSequenceParser('2'),
21
+ createExactSequenceParser('bb'),
22
+ createExactSequenceParser('BBB'),
23
+ ]);
24
+ const abcUnionParser = createUnionParser([
25
+ abDisjunctionParser,
26
+ createExactSequenceParser('final_3'),
27
+ createExactSequenceParser('final_cc'),
28
+ createExactSequenceParser('final_CCC'),
29
+ ]);
30
+ const sampleParser = promiseCompose(createTupleParser([
31
+ aUnionParser,
32
+ abDisjunctionParser,
33
+ abcUnionParser,
34
+ ]), strings => strings.join(''));
35
+ async function* asyncIteratorFromString(string) {
36
+ yield string;
37
+ }
38
+ function sortChildErrors(error) {
39
+ error.childErrors.sort((a, b) => a.message.localeCompare(b.message));
40
+ for (const childError of error.childErrors) {
41
+ if (childError instanceof ParserParsingJoinError) {
42
+ sortChildErrors(childError);
43
+ }
44
+ }
45
+ }
46
+ function removeStackLocations(errorStack) {
47
+ return errorStack.replace(/((at [^\n]+)[\s\n]+)+(at [^\n]+)/g, 'at [LOCATIONS]');
48
+ }
49
+ test('errorJoinMode: none', async (t) => {
50
+ const error = await t.throwsAsync(runParser(sampleParser, asyncIteratorFromString('1bbfinal_CC!'), stringInputCompanion, {
51
+ errorJoinMode: 'none',
52
+ }), {
53
+ instanceOf: ParserParsingJoinNoneError
54
+ });
55
+ t.is(error.position, 12);
56
+ t.deepEqual(error.childErrors, []);
57
+ t.snapshot(removeStackLocations(error.stack));
58
+ });
59
+ test('errorJoinMode: all', async (t) => {
60
+ const error = await t.throwsAsync(runParser(sampleParser, asyncIteratorFromString('1bbfinal_CC!'), stringInputCompanion, {
61
+ errorJoinMode: 'all',
62
+ }), {
63
+ instanceOf: ParserParsingJoinAllError
64
+ });
65
+ sortChildErrors(error);
66
+ t.snapshot(removeStackLocations(error.stack));
67
+ t.is(error.position, 12, 'error.position');
68
+ t.is(error.childErrors.length, 4);
69
+ const error1 = error.childErrors.at(-1);
70
+ invariant(error1 instanceof ParserParsingJoinAllError, 'error1 instanceof ParserParsingJoinAllError');
71
+ t.is(error1.position, 3, 'error1.position');
72
+ t.is(error1.childErrors.length, 4);
73
+ const error2 = error1.childErrors.at(-1);
74
+ invariant(error2 instanceof ParserParsingJoinAllError, 'error2 instanceof ParserParsingJoinAllError');
75
+ t.is(error2.position, 4, 'error2.position');
76
+ t.is(error2.childErrors.length, 3);
77
+ const error3 = error2.childErrors.at(-1);
78
+ invariant(error3 instanceof ParserParsingInvariantError, 'error3 instanceof ParserParsingInvariantError');
79
+ t.is(error3.position, 4, 'error3.position');
80
+ });
81
+ test('errorJoinMode: deepest', async (t) => {
82
+ const error = await t.throwsAsync(runParser(sampleParser, asyncIteratorFromString('1bbfinal_CC!'), stringInputCompanion, {
83
+ errorJoinMode: 'deepest',
84
+ }), {
85
+ instanceOf: ParserParsingJoinDeepestError,
86
+ });
87
+ sortChildErrors(error);
88
+ t.snapshot(removeStackLocations(error.stack));
89
+ t.is(error.position, 12);
90
+ t.is(error.childErrors.length, 1);
91
+ const error1 = error.childErrors.at(-1);
92
+ invariant(error1 instanceof ParserParsingJoinDeepestError, 'error1 instanceof ParserParsingJoinDeepestError');
93
+ t.is(error1.position, 3);
94
+ t.is(error1.childErrors.length, 1);
95
+ const error2 = error1.childErrors.at(-1);
96
+ invariant(error2 instanceof ParserParsingJoinDeepestError, 'error2 instanceof ParserParsingJoinDeepestError');
97
+ t.is(error2.position, 4);
98
+ t.is(error2.childErrors.length, 3);
99
+ const error3 = error2.childErrors.at(-1);
100
+ invariant(error3 instanceof ParserParsingInvariantError, 'error3 instanceof ParserParsingInvariantError');
101
+ t.is(error3.position, 4);
102
+ });
103
+ test('errorJoinMode: furthest', async (t) => {
104
+ const error = await t.throwsAsync(runParser(sampleParser, asyncIteratorFromString('1bbfinal_CC!'), stringInputCompanion, {
105
+ errorJoinMode: 'furthest',
106
+ }), {
107
+ instanceOf: ParserParsingJoinFurthestError,
108
+ });
109
+ sortChildErrors(error);
110
+ t.snapshot(removeStackLocations(error.stack));
111
+ t.is(error.position, 12);
112
+ t.is(error.childErrors.length, 1);
113
+ const error1 = error.childErrors.at(-1);
114
+ invariant(error1 instanceof ParserParsingInvariantError, 'error1 instanceof ParserParsingInvariantError');
115
+ t.is(error1.position, 12);
116
+ });
117
+ test('throws on inputCompanion type mismatch', async (t) => {
118
+ const anythingParser = createArrayParser(createElementParser());
119
+ await runParser(anythingParser, asyncIteratorFromString('anything'), stringInputCompanion);
120
+ await runParser(anythingParser, 'anything', stringInputCompanion);
121
+ await runParser(anythingParser, Buffer.from('anything'), uint8ArrayInputCompanion);
122
+ await runParser(anythingParser, new Uint8Array([1, 2, 3]), uint8ArrayInputCompanion);
123
+ await t.throwsAsync(runParser(anythingParser, asyncIteratorFromString('anything'), uint8ArrayInputCompanion), {
124
+ message: /input companion/,
125
+ });
126
+ });
@@ -0,0 +1,2 @@
1
+ import { Parser } from "./parser.js";
2
+ export declare const createParserAccessorParser: <Output, Sequence>(parserAccessor: () => Parser<Output, Sequence>) => Parser<Output, Sequence>;
@@ -0,0 +1 @@
1
+ export const createParserAccessorParser = (parserAccessor) => async (parserContext) => parserAccessor()(parserContext);
@@ -0,0 +1,3 @@
1
+ import { Parser } from "./parser.js";
2
+ import { DeriveSequenceElement } from "./sequence.js";
3
+ export declare function parserCreatorCompose<OutputA, OutputB, Sequence, Element = DeriveSequenceElement<Sequence>>(f1: Parser<OutputA, Sequence, Element>, f2: (outputA: OutputA) => Parser<OutputB, Sequence, Element>): Parser<OutputB, Sequence, Element>;
@@ -0,0 +1,7 @@
1
+ export function parserCreatorCompose(f1, f2) {
2
+ return async (parserContext) => {
3
+ const outputA = await f1(parserContext);
4
+ const parserB = f2(outputA);
5
+ return parserB(parserContext);
6
+ };
7
+ }
@@ -0,0 +1,48 @@
1
+ import { type InputCompanion } from './inputCompanion.js';
2
+ import { type InputReader } from './inputReader.js';
3
+ import { ParserParsingFailedError } from './parserError.js';
4
+ import { RunParserOptions } from './parser.js';
5
+ import { Falsy, ValueOrAccessor } from './parserInvariant.js';
6
+ type LookaheadOptions = {
7
+ debugName?: string;
8
+ sliceEnd?: number;
9
+ };
10
+ type ParserContextOptions<Sequence, Element> = RunParserOptions<unknown, Sequence, Element> & LookaheadOptions;
11
+ export type ParserContext<Sequence, Element> = {
12
+ from(elements: Element[]): Sequence;
13
+ length(sequence: Sequence): number;
14
+ at(sequence: Sequence, index: number): Element | undefined;
15
+ get position(): number;
16
+ peek(offset: number): Promise<Element | undefined>;
17
+ skip(offset: number): void;
18
+ read(offset: number): Promise<Element>;
19
+ lookahead(options?: LookaheadOptions): ParserContext<Sequence, Element>;
20
+ unlookahead(): void;
21
+ dispose(): void;
22
+ invariant<T>(value: T, format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy>;
23
+ invariantJoin<T>(value: T, childErrors: ParserParsingFailedError[], format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy>;
24
+ };
25
+ export declare class ParserContextImplementation<Sequence, Element> implements ParserContext<Sequence, Element> {
26
+ private readonly _inputCompanion;
27
+ private _inputReader;
28
+ private _parentParserContext;
29
+ private readonly _options;
30
+ private readonly _id;
31
+ private readonly _depth;
32
+ private _exclusiveChildParserContext;
33
+ constructor(_inputCompanion: InputCompanion<Sequence, Element>, _inputReader: InputReader<Sequence, Element>, _parentParserContext: ParserContextImplementation<Sequence, Element> | undefined, _options: ParserContextOptions<Sequence, Element>);
34
+ get [Symbol.toStringTag](): string;
35
+ from(elements: Element[]): Sequence;
36
+ length(sequence: Sequence): number;
37
+ at(sequence: Sequence, index: number): Element | undefined;
38
+ get position(): number;
39
+ peek(offset: number): Promise<Element | undefined>;
40
+ skip(offset: number): void;
41
+ read(offset: number): Promise<Element>;
42
+ lookahead(options?: LookaheadOptions): ParserContext<Sequence, Element>;
43
+ unlookahead(): void;
44
+ dispose(): void;
45
+ invariant<T>(value: T, format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy>;
46
+ invariantJoin<T>(value: T, childErrors: ParserParsingFailedError[], format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy>;
47
+ }
48
+ export {};
@@ -0,0 +1,193 @@
1
+ import invariant from 'invariant';
2
+ import { ParserUnexpectedEndOfInputError, ParserParsingInvariantError, ParserParsingJoinNoneError, ParserParsingJoinAllError, ParserParsingJoinDeepestError, ParserParsingJoinFurthestError } from './parserError.js';
3
+ import { parserInvariant } from './parserInvariant.js';
4
+ let parserContextId = 0;
5
+ export class ParserContextImplementation {
6
+ _inputCompanion;
7
+ _inputReader;
8
+ _parentParserContext;
9
+ _options;
10
+ _id = parserContextId++;
11
+ _depth;
12
+ _exclusiveChildParserContext = undefined;
13
+ constructor(_inputCompanion, _inputReader, _parentParserContext = undefined, _options) {
14
+ this._inputCompanion = _inputCompanion;
15
+ this._inputReader = _inputReader;
16
+ this._parentParserContext = _parentParserContext;
17
+ this._options = _options;
18
+ this._depth = _parentParserContext ? _parentParserContext._depth + 1 : 0;
19
+ }
20
+ get [Symbol.toStringTag]() {
21
+ return [
22
+ 'ParserContext',
23
+ [
24
+ this._options.debugName,
25
+ '(',
26
+ this._id,
27
+ ')',
28
+ ].join(''),
29
+ this._inputReader.toString(),
30
+ ].join(' ');
31
+ }
32
+ from(elements) {
33
+ return this._inputCompanion.from(elements);
34
+ }
35
+ length(sequence) {
36
+ return this._inputCompanion.length(sequence);
37
+ }
38
+ at(sequence, index) {
39
+ return this._inputCompanion.at(sequence, index);
40
+ }
41
+ get position() {
42
+ return this._inputReader.position;
43
+ }
44
+ async peek(offset) {
45
+ if (this._options.sliceEnd !== undefined
46
+ && (this.position + offset) >= this._options.sliceEnd) {
47
+ return undefined;
48
+ }
49
+ return this._inputReader.peek(offset);
50
+ }
51
+ skip(offset) {
52
+ this._inputReader.skip(offset);
53
+ }
54
+ async read(offset) {
55
+ const element = await this.peek(offset);
56
+ if (element === undefined) {
57
+ throw new ParserUnexpectedEndOfInputError('', this._depth, this.position);
58
+ }
59
+ this.skip(offset + 1);
60
+ return element;
61
+ }
62
+ lookahead(options = {}) {
63
+ const lookaheadInputReader = this._inputReader.lookahead();
64
+ if (this.position !== lookaheadInputReader.position) {
65
+ debugger;
66
+ }
67
+ invariant(this.position === lookaheadInputReader.position, 'lookahead this.position (%s) === lookaheadInputReader.position (%s)', this.position, lookaheadInputReader.position);
68
+ const lookaheadParserContext = new ParserContextImplementation(this._inputCompanion, lookaheadInputReader, this, {
69
+ ...this._options,
70
+ ...options,
71
+ debugName: [
72
+ this._options.debugName,
73
+ '(',
74
+ this._id,
75
+ ')',
76
+ '/',
77
+ options.debugName,
78
+ ].join(''),
79
+ });
80
+ if (this.position !== lookaheadParserContext.position) {
81
+ debugger;
82
+ }
83
+ invariant(this.position === lookaheadParserContext.position, 'lookahead this.position (%s) === lookaheadParserContext.position (%s)', this.position, lookaheadParserContext.position);
84
+ return lookaheadParserContext;
85
+ }
86
+ unlookahead() {
87
+ invariant(this._parentParserContext !== undefined, 'this._parentParserContext !== undefined');
88
+ invariant((this._parentParserContext._exclusiveChildParserContext === undefined
89
+ || this._parentParserContext._exclusiveChildParserContext === this), [
90
+ 'Parent\'s exclusive child must be undefined or this',
91
+ 'this: %s',
92
+ 'parent: %s',
93
+ 'parent.exclusiveChild: %s',
94
+ ].join('\n'), this.toString(), this._parentParserContext.toString(), this._parentParserContext._exclusiveChildParserContext?.toString());
95
+ invariant(this._parentParserContext.position <= this.position, 'unlookahead this._parentParserContext.position (%s) <= this.position (%s)', this._parentParserContext.position, this.position);
96
+ const offset = this._inputReader.position - this._parentParserContext._inputReader.position;
97
+ this._parentParserContext.skip(offset);
98
+ invariant(this._parentParserContext.position === this.position, 'unlookahead this._parentParserContext.position (%s) === this.position (%s)', this._parentParserContext.position, this.position);
99
+ this._inputReader = this._parentParserContext._inputReader;
100
+ this._parentParserContext._exclusiveChildParserContext = this;
101
+ if (this._exclusiveChildParserContext) {
102
+ this._exclusiveChildParserContext.unlookahead();
103
+ }
104
+ }
105
+ dispose() {
106
+ invariant(this._parentParserContext !== undefined, 'this._parentParserContext !== undefined');
107
+ invariant((this._parentParserContext._exclusiveChildParserContext === undefined
108
+ || this._parentParserContext._exclusiveChildParserContext === this), [
109
+ 'Parent\'s exclusive child must be undefined or this',
110
+ 'this: %s',
111
+ 'parent: %s',
112
+ 'parent.exclusiveChild: %s',
113
+ ].join('\n'), this.toString(), this._parentParserContext.toString(), this._parentParserContext._exclusiveChildParserContext?.toString());
114
+ this._parentParserContext._exclusiveChildParserContext = undefined;
115
+ this._parentParserContext = undefined;
116
+ }
117
+ invariant(value, format, ...formatArguments) {
118
+ const parserContext = this;
119
+ return parserInvariant(function (message) {
120
+ return new ParserParsingInvariantError(message, parserContext._depth, parserContext.position);
121
+ }, value, format, ...formatArguments);
122
+ }
123
+ invariantJoin(value, childErrors, format, ...formatArguments) {
124
+ invariant(childErrors.length > 0, 'childErrors.length > 0');
125
+ const errorJoinMode = this._options.errorJoinMode ?? 'none';
126
+ const parserContext = this;
127
+ if (errorJoinMode === 'none') {
128
+ return parserInvariant(function (message) {
129
+ return new ParserParsingJoinNoneError(message, parserContext._depth, parserContext.position);
130
+ }, value, format, ...formatArguments);
131
+ }
132
+ if (errorJoinMode === 'furthest') {
133
+ return parserInvariant(function (message) {
134
+ let furthestPosition = 0;
135
+ let furthestChildErrors = [];
136
+ for (const childError of childErrors) {
137
+ if (childError.position < furthestPosition) {
138
+ continue;
139
+ }
140
+ if (childError.position > furthestPosition) {
141
+ furthestPosition = childError.position;
142
+ furthestChildErrors = [childError];
143
+ continue;
144
+ }
145
+ furthestChildErrors.push(childError);
146
+ }
147
+ message += [
148
+ '',
149
+ 'Furthest child error stacks, indented:',
150
+ ...furthestChildErrors.flatMap(furthestChildError => furthestChildError.stack?.split('\n').map(line => ' ' + line)),
151
+ 'End of furthest child error stacks',
152
+ ].join('\n');
153
+ return new ParserParsingJoinFurthestError(message, parserContext._depth, furthestPosition, furthestChildErrors);
154
+ }, value, format, ...formatArguments);
155
+ }
156
+ if (errorJoinMode === 'deepest') {
157
+ return parserInvariant(function (message) {
158
+ let deepestDepth = 0;
159
+ let deepestChildErrors = [];
160
+ for (const childError of childErrors) {
161
+ if (childError.depth < deepestDepth) {
162
+ continue;
163
+ }
164
+ if (childError.depth > deepestDepth) {
165
+ deepestDepth = childError.depth;
166
+ deepestChildErrors = [childError];
167
+ continue;
168
+ }
169
+ deepestChildErrors.push(childError);
170
+ }
171
+ message += [
172
+ '',
173
+ 'Deepest child error stacks, indented:',
174
+ ...deepestChildErrors.flatMap(deepestChildError => deepestChildError.stack?.split('\n').map(line => ' ' + line)),
175
+ 'End of deepest child error stacks',
176
+ ].join('\n');
177
+ return new ParserParsingJoinDeepestError(message, deepestDepth, parserContext.position, deepestChildErrors);
178
+ }, value, format, ...formatArguments);
179
+ }
180
+ if (errorJoinMode === 'all') {
181
+ return parserInvariant(function (message) {
182
+ message += [
183
+ '',
184
+ 'Child error stacks, indented:',
185
+ ...childErrors.flatMap(childError => childError.stack?.split('\n').map(line => ' ' + line)),
186
+ 'End of child error stacks',
187
+ ].join('\n');
188
+ return new ParserParsingJoinAllError(message, parserContext._depth, parserContext.position, childErrors);
189
+ }, value, format, ...formatArguments);
190
+ }
191
+ invariant(false, 'Unsupported errorJoinMode: %s', errorJoinMode);
192
+ }
193
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,115 @@
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
+ const commonParserContextArguments = [
7
+ undefined,
8
+ {
9
+ debugName: 'root',
10
+ errorJoinMode: 'all',
11
+ },
12
+ ];
13
+ test('parserContext.read', async (t) => {
14
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function* () {
15
+ yield '';
16
+ yield 'abc';
17
+ yield 'def';
18
+ yield '';
19
+ yield 'gh';
20
+ })()), ...commonParserContextArguments);
21
+ t.is(await parserContext.read(0), 'a');
22
+ t.is(await parserContext.read(0), 'b');
23
+ t.is(await parserContext.read(5), 'h');
24
+ await t.throwsAsync(async () => parserContext.read(0), {
25
+ instanceOf: ParserUnexpectedEndOfInputError,
26
+ });
27
+ });
28
+ test('parserContext.lookahead', async (t) => {
29
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function* () {
30
+ yield* 'abcdefgh';
31
+ })()), ...commonParserContextArguments);
32
+ const lookaheadContext1 = parserContext.lookahead();
33
+ const lookaheadContext2 = parserContext.lookahead();
34
+ const lookaheadContext3 = parserContext.lookahead({
35
+ sliceEnd: 3,
36
+ });
37
+ t.is(await lookaheadContext3.peek(2), 'c');
38
+ t.is(await lookaheadContext3.peek(3), undefined);
39
+ t.is(await lookaheadContext3.read(0), 'a');
40
+ t.is(await lookaheadContext3.read(0), 'b');
41
+ t.is(await lookaheadContext3.read(0), 'c');
42
+ t.is(await lookaheadContext3.peek(0), undefined);
43
+ t.is(await parserContext.peek(0), 'a');
44
+ t.is(await lookaheadContext1.peek(0), 'a');
45
+ t.is(await lookaheadContext2.peek(0), 'a');
46
+ t.is(await lookaheadContext1.read(0), 'a');
47
+ t.is(await parserContext.peek(0), 'a');
48
+ t.is(await lookaheadContext1.peek(0), 'b');
49
+ t.is(await lookaheadContext2.peek(0), 'a');
50
+ t.is(await parserContext.read(0), 'a');
51
+ t.is(parserContext.position, 1);
52
+ t.is(lookaheadContext1.position, 1);
53
+ t.is(lookaheadContext2.position, 0);
54
+ t.is(lookaheadContext3.position, 3);
55
+ });
56
+ test('parserContext.unlookahead', async (t) => {
57
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function* () {
58
+ yield* 'abcdefgh';
59
+ })()), ...commonParserContextArguments);
60
+ const lookaheadContext = parserContext.lookahead();
61
+ t.is(await parserContext.peek(0), 'a');
62
+ t.is(await lookaheadContext.peek(0), 'a');
63
+ t.is(await lookaheadContext.read(0), 'a');
64
+ t.is(await parserContext.peek(0), 'a');
65
+ t.is(await lookaheadContext.peek(0), 'b');
66
+ lookaheadContext.unlookahead();
67
+ t.is(await lookaheadContext.read(0), 'b');
68
+ t.is(await lookaheadContext.read(0), 'c');
69
+ });
70
+ test('parserContext.unlookahead while peeking', async (t) => {
71
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function* () {
72
+ yield* 'abcdefgh';
73
+ })()), ...commonParserContextArguments);
74
+ const lookaheadContext = parserContext.lookahead();
75
+ parserContext.skip(1);
76
+ lookaheadContext.skip(2);
77
+ const peekPromise = lookaheadContext.peek(0);
78
+ lookaheadContext.unlookahead();
79
+ t.is(await peekPromise, 'c');
80
+ });
81
+ test('parserContext deep unlookahead normal order', async (t) => {
82
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function* () {
83
+ yield* 'abcdefgh';
84
+ })()), ...commonParserContextArguments);
85
+ const child = parserContext.lookahead();
86
+ t.is(await child.read(0), 'a');
87
+ const grandchild = child.lookahead();
88
+ t.is(await grandchild.read(0), 'b');
89
+ grandchild.unlookahead();
90
+ t.is(await child.read(0), 'c');
91
+ child.unlookahead();
92
+ t.is(await parserContext.read(0), 'd');
93
+ });
94
+ test('parserContext deep unlookahead weird order', async (t) => {
95
+ const parserContext = new ParserContextImplementation(stringInputCompanion, new InputReaderImplementation(stringInputCompanion, (async function* () {
96
+ yield* 'abcdefgh';
97
+ })()), ...commonParserContextArguments);
98
+ const child = parserContext.lookahead({
99
+ debugName: 'child',
100
+ });
101
+ const grandchild = child.lookahead({
102
+ debugName: 'grandchild',
103
+ });
104
+ const greatGrandchild = grandchild.lookahead({
105
+ debugName: 'greatGrandchild',
106
+ });
107
+ t.is(await greatGrandchild.read(0), 'a');
108
+ grandchild.unlookahead();
109
+ child.unlookahead();
110
+ greatGrandchild.unlookahead();
111
+ t.is(await greatGrandchild.read(0), 'b');
112
+ t.is(await grandchild.read(0), 'c');
113
+ t.is(await child.read(0), 'd');
114
+ t.is(await parserContext.read(0), 'e');
115
+ });
@@ -0,0 +1,3 @@
1
+ import { Parser } from "./parser.js";
2
+ import { DeriveSequenceElement } from "./sequence.js";
3
+ export declare function parserCreatorCompose<Arguments extends unknown[], OutputA, OutputB, Sequence, Element = DeriveSequenceElement<Sequence>>(f1: (...args: Arguments) => Parser<OutputA, Sequence, Element>, f2: (outputA: OutputA) => Parser<OutputB, Sequence, Element>): (...args: Arguments) => Parser<OutputB, Sequence, Element>;
@@ -0,0 +1,10 @@
1
+ export function parserCreatorCompose(f1, f2) {
2
+ return (...args) => {
3
+ const parserA = f1(...args);
4
+ return async (parserContext) => {
5
+ const outputA = await parserA(parserContext);
6
+ const parserB = f2(outputA);
7
+ return parserB(parserContext);
8
+ };
9
+ };
10
+ }
@@ -0,0 +1,43 @@
1
+ export declare class ParserError extends Error {
2
+ name: string;
3
+ }
4
+ export declare class ParserImplementationError extends ParserError {
5
+ name: string;
6
+ }
7
+ export declare class ParserImplementationInvariantError extends ParserImplementationError {
8
+ name: string;
9
+ }
10
+ export declare class ParserParsingFailedError extends ParserError {
11
+ readonly depth: number;
12
+ readonly position: number;
13
+ name: string;
14
+ constructor(message: string, depth: number, position: number);
15
+ }
16
+ export declare class ParserParsingJoinError extends ParserParsingFailedError {
17
+ name: string;
18
+ readonly childErrors: ParserParsingFailedError[];
19
+ }
20
+ export declare class ParserParsingJoinNoneError extends ParserParsingJoinError {
21
+ name: string;
22
+ }
23
+ export declare class ParserParsingJoinAllError extends ParserParsingJoinError {
24
+ readonly childErrors: ParserParsingFailedError[];
25
+ name: string;
26
+ constructor(message: string, depth: number, position: number, childErrors: ParserParsingFailedError[]);
27
+ }
28
+ export declare class ParserParsingJoinDeepestError extends ParserParsingJoinError {
29
+ readonly childErrors: ParserParsingFailedError[];
30
+ name: string;
31
+ constructor(message: string, depth: number, position: number, childErrors: ParserParsingFailedError[]);
32
+ }
33
+ export declare class ParserParsingJoinFurthestError extends ParserParsingJoinError {
34
+ readonly childErrors: ParserParsingFailedError[];
35
+ name: string;
36
+ constructor(message: string, depth: number, position: number, childErrors: ParserParsingFailedError[]);
37
+ }
38
+ export declare class ParserParsingInvariantError extends ParserParsingFailedError {
39
+ name: string;
40
+ }
41
+ export declare class ParserUnexpectedEndOfInputError extends ParserParsingFailedError {
42
+ name: string;
43
+ }