@futpib/parser 1.0.0 → 1.0.2

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