@thomasfosterau/effect-parse 0.4.1 → 0.5.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 (143) hide show
  1. package/README.md +37 -13
  2. package/dist/Ascii.d.ts +11 -4
  3. package/dist/Ascii.d.ts.map +1 -1
  4. package/dist/Ascii.js +7 -1
  5. package/dist/Ascii.js.map +1 -1
  6. package/dist/Binary.d.ts.map +1 -1
  7. package/dist/Binary.js +64 -35
  8. package/dist/Binary.js.map +1 -1
  9. package/dist/Bits.d.ts.map +1 -1
  10. package/dist/Bits.js +7 -4
  11. package/dist/Bits.js.map +1 -1
  12. package/dist/Compiler.d.ts +74 -2
  13. package/dist/Compiler.d.ts.map +1 -1
  14. package/dist/Compiler.js +78 -1
  15. package/dist/Compiler.js.map +1 -1
  16. package/dist/Expression.d.ts.map +1 -1
  17. package/dist/Expression.js +86 -74
  18. package/dist/Expression.js.map +1 -1
  19. package/dist/Input.d.ts +37 -4
  20. package/dist/Input.d.ts.map +1 -1
  21. package/dist/Input.js +42 -0
  22. package/dist/Input.js.map +1 -1
  23. package/dist/Nom.d.ts +5 -15
  24. package/dist/Nom.d.ts.map +1 -1
  25. package/dist/Nom.js.map +1 -1
  26. package/dist/ParseError.d.ts.map +1 -1
  27. package/dist/ParseError.js.map +1 -1
  28. package/dist/Parser.d.ts +366 -26
  29. package/dist/Parser.d.ts.map +1 -1
  30. package/dist/Parser.js +390 -19
  31. package/dist/Parser.js.map +1 -1
  32. package/dist/ParserSchema.js +1 -1
  33. package/dist/ParserStream.d.ts +3 -2
  34. package/dist/ParserStream.d.ts.map +1 -1
  35. package/dist/ParserStream.js +13 -9
  36. package/dist/ParserStream.js.map +1 -1
  37. package/dist/Syntax.d.ts +23 -5
  38. package/dist/Syntax.d.ts.map +1 -1
  39. package/dist/Syntax.js.map +1 -1
  40. package/dist/Text.d.ts.map +1 -1
  41. package/dist/Text.js +9 -9
  42. package/dist/Text.js.map +1 -1
  43. package/dist/Token.d.ts +55 -10
  44. package/dist/Token.d.ts.map +1 -1
  45. package/dist/Token.js +59 -21
  46. package/dist/Token.js.map +1 -1
  47. package/dist/internal/compiler/closure.d.ts.map +1 -1
  48. package/dist/internal/compiler/closure.js +257 -97
  49. package/dist/internal/compiler/closure.js.map +1 -1
  50. package/dist/internal/compiler/entries.d.ts +3 -1
  51. package/dist/internal/compiler/entries.d.ts.map +1 -1
  52. package/dist/internal/compiler/entries.js +3 -2
  53. package/dist/internal/compiler/entries.js.map +1 -1
  54. package/dist/internal/compiler/first.d.ts.map +1 -1
  55. package/dist/internal/compiler/first.js +7 -1
  56. package/dist/internal/compiler/first.js.map +1 -1
  57. package/dist/internal/compiler/graph.d.ts +17 -0
  58. package/dist/internal/compiler/graph.d.ts.map +1 -0
  59. package/dist/internal/compiler/graph.js +56 -0
  60. package/dist/internal/compiler/graph.js.map +1 -0
  61. package/dist/internal/compiler/jit.d.ts +5 -0
  62. package/dist/internal/compiler/jit.d.ts.map +1 -1
  63. package/dist/internal/compiler/jit.js +185 -96
  64. package/dist/internal/compiler/jit.js.map +1 -1
  65. package/dist/internal/compiler/registry.d.ts +10 -2
  66. package/dist/internal/compiler/registry.d.ts.map +1 -1
  67. package/dist/internal/compiler/registry.js.map +1 -1
  68. package/dist/internal/compiler/search.d.ts +32 -0
  69. package/dist/internal/compiler/search.d.ts.map +1 -0
  70. package/dist/internal/compiler/search.js +68 -0
  71. package/dist/internal/compiler/search.js.map +1 -0
  72. package/dist/internal/compiler/sets.d.ts.map +1 -1
  73. package/dist/internal/compiler/sets.js +1 -1
  74. package/dist/internal/compiler/sets.js.map +1 -1
  75. package/dist/internal/compiler/wasm.d.ts +8 -0
  76. package/dist/internal/compiler/wasm.d.ts.map +1 -0
  77. package/dist/internal/compiler/wasm.js +2769 -0
  78. package/dist/internal/compiler/wasm.js.map +1 -0
  79. package/dist/internal/compiler/wasmAsm.d.ts +199 -0
  80. package/dist/internal/compiler/wasmAsm.d.ts.map +1 -0
  81. package/dist/internal/compiler/wasmAsm.js +427 -0
  82. package/dist/internal/compiler/wasmAsm.js.map +1 -0
  83. package/dist/internal/entries.d.ts +3 -1
  84. package/dist/internal/entries.d.ts.map +1 -1
  85. package/dist/internal/entries.js.map +1 -1
  86. package/dist/internal/node.d.ts +58 -2
  87. package/dist/internal/node.d.ts.map +1 -1
  88. package/dist/internal/node.js +13 -3
  89. package/dist/internal/node.js.map +1 -1
  90. package/dist/internal/numbers.d.ts.map +1 -1
  91. package/dist/internal/numbers.js.map +1 -1
  92. package/dist/internal/run.d.ts +12 -0
  93. package/dist/internal/run.d.ts.map +1 -1
  94. package/dist/internal/run.js +51 -11
  95. package/dist/internal/run.js.map +1 -1
  96. package/dist/internal/stack.d.ts +6 -0
  97. package/dist/internal/stack.d.ts.map +1 -1
  98. package/dist/internal/stack.js +8 -2
  99. package/dist/internal/stack.js.map +1 -1
  100. package/dist/internal/syntax.d.ts +4 -4
  101. package/dist/internal/syntax.d.ts.map +1 -1
  102. package/dist/internal/syntax.js +18 -10
  103. package/dist/internal/syntax.js.map +1 -1
  104. package/dist/internal/text.d.ts +32 -0
  105. package/dist/internal/text.d.ts.map +1 -1
  106. package/dist/internal/text.js +68 -14
  107. package/dist/internal/text.js.map +1 -1
  108. package/dist/internal/tokens.d.ts +13 -0
  109. package/dist/internal/tokens.d.ts.map +1 -1
  110. package/dist/internal/tokens.js +59 -39
  111. package/dist/internal/tokens.js.map +1 -1
  112. package/package.json +5 -4
  113. package/src/Ascii.ts +42 -9
  114. package/src/Binary.ts +151 -71
  115. package/src/Bits.ts +12 -6
  116. package/src/Compiler.ts +101 -10
  117. package/src/Expression.ts +94 -81
  118. package/src/Input.ts +65 -6
  119. package/src/Nom.ts +15 -5
  120. package/src/ParseError.ts +3 -0
  121. package/src/Parser.ts +678 -127
  122. package/src/ParserStream.ts +37 -18
  123. package/src/Syntax.ts +60 -36
  124. package/src/Text.ts +16 -15
  125. package/src/Token.ts +138 -29
  126. package/src/internal/compiler/closure.ts +362 -135
  127. package/src/internal/compiler/entries.ts +4 -2
  128. package/src/internal/compiler/first.ts +10 -0
  129. package/src/internal/compiler/graph.ts +68 -0
  130. package/src/internal/compiler/jit.ts +284 -154
  131. package/src/internal/compiler/registry.ts +10 -2
  132. package/src/internal/compiler/search.ts +68 -0
  133. package/src/internal/compiler/sets.ts +7 -3
  134. package/src/internal/compiler/wasm.ts +3203 -0
  135. package/src/internal/compiler/wasmAsm.ts +484 -0
  136. package/src/internal/entries.ts +8 -2
  137. package/src/internal/node.ts +54 -4
  138. package/src/internal/numbers.ts +3 -1
  139. package/src/internal/run.ts +71 -12
  140. package/src/internal/stack.ts +8 -1
  141. package/src/internal/syntax.ts +39 -18
  142. package/src/internal/text.ts +97 -9
  143. package/src/internal/tokens.ts +96 -14
package/src/Expression.ts CHANGED
@@ -38,7 +38,10 @@ import * as Predicate from "effect/Predicate"
38
38
  import type { Input, State } from "./Input.js"
39
39
  import { Fail } from "./Input.js"
40
40
  import type { Parser } from "./Parser.js"
41
- import { make as makeParser } from "./Parser.js"
41
+ import { combinator } from "./Parser.js"
42
+
43
+ /** A parser's step, interpreted or compiled. */
44
+ type Step = (state: State<any>) => unknown
42
45
  import { TiedFailures } from "./internal/ties.js"
43
46
 
44
47
  /**
@@ -154,101 +157,111 @@ export const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<O
154
157
  readonly operand: Parser<A, E, R, I>
155
158
  readonly operators: Ops
156
159
  }): Parser<A, E | OpError<Ops[number]>, R | OpServices<Ops[number]>, I & OpInput<Ops[number]>> => {
157
- const operand = options.operand.step
158
160
  const prefixes = options.operators.filter((o): o is Prefix<A, any, any, any> => Predicate.isTagged(o, "Prefix"))
159
161
  const postfixes = options.operators.filter((o): o is Postfix<A, any, any, any> => Predicate.isTagged(o, "Postfix"))
160
162
  const infixes = options.operators.filter((o): o is Infix<A, any, any, any> => Predicate.isTagged(o, "Infix"))
163
+ const operators = [...prefixes, ...postfixes, ...infixes]
164
+ const parsers = [options.operand, ...operators.map((o) => o.parser)]
165
+ // Builds the step from the operand's and the operators' steps, in that
166
+ // order: their own steps when interpreted, compiled ones when compiled
167
+ const build = (steps: ReadonlyArray<Step>) => {
168
+ const operand = steps[0]
169
+ const prefixSteps = steps.slice(1, 1 + prefixes.length)
170
+ const postfixSteps = steps.slice(1 + prefixes.length, 1 + prefixes.length + postfixes.length)
171
+ const infixSteps = steps.slice(1 + prefixes.length + postfixes.length)
161
172
 
162
- // Attempts each operator in turn. Returns the index of the first match
163
- // (with its output in `matched`), -1 if none matched, or -2 on a fatal
164
- // failure. Failed attempts are folded into `failures`, merged only when
165
- // read (#44): a round in which an operator matches discards them unmerged.
166
- // Like `matched`, it is shared by nested expressions, which clear it.
167
- let matched: unknown
168
- const failures = new TiedFailures()
169
- const tryOps = (state: State<any>, ops: ReadonlyArray<OperatorBase<any, any, any>>, mustConsume: boolean): number => {
170
- const start = state.pos
171
- for (let i = 0; i < ops.length; i++) {
172
- const out = ops[i].parser.step(state)
173
- if (out !== Fail) {
174
- // A prefix or postfix operator matching nothing would apply forever
175
- if (mustConsume && state.pos === start) {
176
- state.failMessage("Cut", "Assert", "prefix and postfix operators must always consume")
177
- return -2
173
+ // Attempts each operator in turn. Returns the index of the first match
174
+ // (with its output in `matched`), -1 if none matched, or -2 on a fatal
175
+ // failure. Failed attempts are folded into `failures`, merged only when
176
+ // read (#44): a round in which an operator matches discards them unmerged.
177
+ // Like `matched`, it is shared by nested expressions, which clear it.
178
+ let matched: unknown
179
+ const failures = new TiedFailures()
180
+ const tryOps = (state: State<any>, ops: ReadonlyArray<Step>, mustConsume: boolean): number => {
181
+ const start = state.pos
182
+ for (let i = 0; i < ops.length; i++) {
183
+ const out = ops[i](state)
184
+ if (out !== Fail) {
185
+ // A prefix or postfix operator matching nothing would apply forever
186
+ if (mustConsume && state.pos === start) {
187
+ state.failMessage("Cut", "Assert", "prefix and postfix operators must always consume")
188
+ return -2
189
+ }
190
+ matched = out
191
+ return i
178
192
  }
179
- matched = out
180
- return i
193
+ if (state.mode !== "Backtrack") return -2
194
+ state.rewind(start)
195
+ failures.add(state)
181
196
  }
182
- if (state.mode !== "Backtrack") return -2
183
- state.rewind(start)
184
- failures.add(state)
197
+ return -1
185
198
  }
186
- return -1
187
- }
188
199
 
189
- const expr = (state: State<any>, minPower: number): A | Fail => {
190
- let lhs: A | Fail
191
- failures.clear()
192
- const p = tryOps(state, prefixes, true)
193
- if (p === -2) return Fail
194
- if (p >= 0) {
195
- const op = prefixes[p]
196
- const opOut = matched
197
- const operandValue = expr(state, op.precedence * 2)
198
- if (operandValue === Fail) return Fail
199
- lhs = op.fold(opOut, operandValue)
200
- } else {
201
- const prefixFailure = failures.failure
202
- const prefixTie1 = failures.tie1
203
- const prefixTie2 = failures.tie2
204
- lhs = operand(state)
205
- if (lhs === Fail) {
206
- if (prefixFailure !== undefined && state.mode === "Backtrack") {
207
- // The operand may have parsed nested expressions, which reuse `failures`
208
- failures.failure = prefixFailure
209
- failures.tie1 = prefixTie1
210
- failures.tie2 = prefixTie2
211
- failures.add(state)
212
- failures.fail(state)
200
+ const expr = (state: State<any>, minPower: number): A | Fail => {
201
+ let lhs: A | Fail
202
+ failures.clear()
203
+ const p = tryOps(state, prefixSteps, true)
204
+ if (p === -2) return Fail
205
+ if (p >= 0) {
206
+ const op = prefixes[p]
207
+ const opOut = matched
208
+ const operandValue = expr(state, op.precedence * 2)
209
+ if (operandValue === Fail) return Fail
210
+ lhs = op.fold(opOut, operandValue)
211
+ } else {
212
+ const prefixFailure = failures.failure
213
+ const prefixTie1 = failures.tie1
214
+ const prefixTie2 = failures.tie2
215
+ // SAFETY: the operand's step, interpreted or compiled, returns its output (an `A`) or `Fail`
216
+ lhs = operand(state) as A | Fail
217
+ if (lhs === Fail) {
218
+ if (prefixFailure !== undefined && state.mode === "Backtrack") {
219
+ // The operand may have parsed nested expressions, which reuse `failures`
220
+ failures.failure = prefixFailure
221
+ failures.tie1 = prefixTie1
222
+ failures.tie2 = prefixTie2
223
+ failures.add(state)
224
+ failures.fail(state)
225
+ }
226
+ return Fail
213
227
  }
214
- return Fail
215
228
  }
216
- }
217
229
 
218
- while (true) {
219
- const start = state.pos
220
- failures.clear()
221
- const q = tryOps(state, postfixes, true)
222
- if (q === -2) return Fail
223
- if (q >= 0) {
224
- const op = postfixes[q]
225
- if (op.precedence * 2 < minPower) {
230
+ while (true) {
231
+ const start = state.pos
232
+ failures.clear()
233
+ const q = tryOps(state, postfixSteps, true)
234
+ if (q === -2) return Fail
235
+ if (q >= 0) {
236
+ const op = postfixes[q]
237
+ if (op.precedence * 2 < minPower) {
238
+ state.rewind(start)
239
+ break
240
+ }
241
+ lhs = op.fold(lhs, matched)
242
+ continue
243
+ }
244
+ // The infix attempts are folded on top of the postfix ones
245
+ const i = tryOps(state, infixSteps, false)
246
+ if (i === -2) return Fail
247
+ if (i < 0) {
248
+ failures.hint(state)
249
+ break
250
+ }
251
+ const op = infixes[i]
252
+ const leftPower = op.precedence * 2
253
+ if (leftPower < minPower) {
226
254
  state.rewind(start)
227
255
  break
228
256
  }
229
- lhs = op.fold(lhs, matched)
230
- continue
231
- }
232
- // The infix attempts are folded on top of the postfix ones
233
- const i = tryOps(state, infixes, false)
234
- if (i === -2) return Fail
235
- if (i < 0) {
236
- failures.hint(state)
237
- break
257
+ const opOut = matched
258
+ const rhs = expr(state, op.associativity === "left" ? leftPower + 1 : leftPower)
259
+ if (rhs === Fail) return Fail
260
+ lhs = op.fold(lhs, opOut, rhs)
238
261
  }
239
- const op = infixes[i]
240
- const leftPower = op.precedence * 2
241
- if (leftPower < minPower) {
242
- state.rewind(start)
243
- break
244
- }
245
- const opOut = matched
246
- const rhs = expr(state, op.associativity === "left" ? leftPower + 1 : leftPower)
247
- if (rhs === Fail) return Fail
248
- lhs = op.fold(lhs, opOut, rhs)
262
+ return lhs
249
263
  }
250
- return lhs
264
+ return (state: State<any>) => expr(state, 0)
251
265
  }
252
-
253
- return makeParser((state: State<any>) => expr(state, 0), "expression")
266
+ return combinator(parsers, build, "expression")
254
267
  }
package/src/Input.ts CHANGED
@@ -19,6 +19,7 @@ import * as Context from "effect/Context"
19
19
  import type { Encoding } from "./Encoding.js"
20
20
  import type { ErrorKind } from "./ParseError.js"
21
21
  import type { Builder as SyntaxBuilder } from "./internal/syntax.js"
22
+ import type { AsciiRun } from "./internal/text.js"
22
23
 
23
24
  /**
24
25
  * The kinds of input a parser can consume.
@@ -56,6 +57,17 @@ export type BinaryInput = ArrayBufferLike | ArrayBufferView
56
57
  */
57
58
  export type Source<I> = I | ([I] extends [Uint8Array] ? BinaryInput : never)
58
59
 
60
+ /**
61
+ * The overloads of {@link fromSource}.
62
+ *
63
+ * @since 0.5.0
64
+ * @category constructors
65
+ */
66
+ export interface FromSourceFn {
67
+ (source: BinaryInput): Uint8Array
68
+ <I extends Input>(source: Source<I>): I
69
+ }
70
+
59
71
  /**
60
72
  * Converts a {@link Source} to the input parsers read: binary data becomes a
61
73
  * `Uint8Array` view of the same memory, everything else is returned as is.
@@ -70,10 +82,7 @@ export type Source<I> = I | ([I] extends [Uint8Array] ? BinaryInput : never)
70
82
  * @since 0.1.0
71
83
  * @category constructors
72
84
  */
73
- export const fromSource: {
74
- (source: BinaryInput): Uint8Array
75
- <I extends Input>(source: Source<I>): I
76
- } = (source: Input | BinaryInput): any => {
85
+ export const fromSource: FromSourceFn = (source: Input | BinaryInput): any => {
77
86
  if (Predicate.isString(source) || source instanceof Uint8Array || Array.isArray(source)) return source
78
87
  if (ArrayBuffer.isView(source)) return new Uint8Array(source.buffer, source.byteOffset, source.byteLength)
79
88
  // An explicit length fixes the view's size even for a resizable buffer
@@ -292,6 +301,31 @@ export class State<I extends Input = Input> {
292
301
  * @internal
293
302
  */
294
303
  syntax: SyntaxBuilder | undefined = undefined
304
+ /**
305
+ * Where the stop characters of compiled `takeTill`s next occur in this
306
+ * state's input, by search site; created on first use. It lives as long
307
+ * as the state (whose input never changes), and `reset` clears it with
308
+ * the other per-run fields.
309
+ *
310
+ * @internal
311
+ */
312
+ searches: Map<object, Array<number>> | undefined = undefined
313
+ /**
314
+ * A run of ASCII bytes of this state's UTF-8 input, decoded once, from
315
+ * which `Text.utf8` slices the long strings it decodes (see
316
+ * `internal/text.ts`); `reset` clears it with the other per-run fields.
317
+ *
318
+ * @internal
319
+ */
320
+ asciiRun: AsciiRun | undefined = undefined
321
+ /**
322
+ * A `DataView` of this state's byte input, for the `Binary` parsers;
323
+ * created on first use. It lives as long as the state, whose input never
324
+ * changes: one per read cost most of a number's time.
325
+ *
326
+ * @internal
327
+ */
328
+ view: DataView | undefined = undefined
295
329
 
296
330
  constructor(
297
331
  source: I | Source<I>,
@@ -301,7 +335,7 @@ export class State<I extends Input = Input> {
301
335
  readonly offset?: number | undefined
302
336
  }
303
337
  ) {
304
- const input = fromSource(source as Input) as I
338
+ const input = fromSource<I>(source)
305
339
  this.input = input
306
340
  this.end = input.length
307
341
  this.pos = options?.offset ?? 0
@@ -393,6 +427,8 @@ export class State<I extends Input = Input> {
393
427
  this.depth = 0
394
428
  this.encoding = undefined
395
429
  this.resume = undefined
430
+ this.searches = undefined
431
+ this.asciiRun = undefined
396
432
  return this
397
433
  }
398
434
 
@@ -445,7 +481,14 @@ export class State<I extends Input = Input> {
445
481
  * Extracts the slice `[start, end)` of the input.
446
482
  */
447
483
  slice(start: number, end: number): Slice<I> {
448
- const input = this.input as any
484
+ // SAFETY: `inputKind` 1 is a `Uint8Array`, whose `subarray` returns a
485
+ // `Uint8Array` view (its `Slice`); 0 and 2 are a string and an array, whose
486
+ // `slice` returns a string and an array of the same elements (their
487
+ // `Slice`). `subarray` is only called for kind 1
488
+ const input = this.input as {
489
+ slice(start: number, end: number): Slice<I>
490
+ subarray(start: number, end: number): Slice<I>
491
+ } & I
449
492
  switch (this.inputKind) {
450
493
  case 0:
451
494
  return input.slice(start, end)
@@ -598,14 +641,30 @@ export class State<I extends Input = Input> {
598
641
  }
599
642
  }
600
643
 
644
+ /**
645
+ * The last merges {@link mergeExpected} made, as `[a, b, merged]` triples. A
646
+ * parse merges the same few pairs of expectation arrays over and over (a
647
+ * whitespace skipper's hint with a repetition's, then with the failure of
648
+ * the token after them), and expectation arrays are never mutated, so a
649
+ * merge seen recently returns its earlier result, which in turn keeps the
650
+ * next merge's input the same array.
651
+ */
652
+ const merges: Array<ReadonlyArray<string>> = /*#__PURE__*/ new Array(12).fill(empty)
653
+ let mergeSlot = 0
654
+
601
655
  /** @internal */
602
656
  export const mergeExpected = (a: ReadonlyArray<string>, b: ReadonlyArray<string>): ReadonlyArray<string> => {
603
657
  if (Arr.isReadonlyArrayEmpty(a)) return b
604
658
  if (Arr.isReadonlyArrayEmpty(b)) return a
659
+ for (let i = 0; i < 12; i += 3) if (merges[i] === a && merges[i + 1] === b) return merges[i + 2]
605
660
  const out = a.slice()
606
661
  for (const e of b) {
607
662
  if (!out.includes(e)) out.push(e)
608
663
  }
664
+ merges[mergeSlot] = a
665
+ merges[mergeSlot + 1] = b
666
+ merges[mergeSlot + 2] = out
667
+ mergeSlot = mergeSlot === 9 ? 0 : mergeSlot + 3
609
668
  return out
610
669
  }
611
670
 
package/src/Nom.ts CHANGED
@@ -132,7 +132,9 @@ export const take = Token.take
132
132
  */
133
133
  export const takeWhile = <I extends Input = string>(
134
134
  predicate: (token: TokenOf<I>) => boolean
135
- ): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> => Token.takeWhile<I>(predicate as any)
135
+ ): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> =>
136
+ // SAFETY: a predicate over the input's tokens is a member of `TokenSet<I>` for each input kind
137
+ Token.takeWhile<I>(predicate as Token.TokenSet<I>)
136
138
 
137
139
  /**
138
140
  * @since 0.1.0
@@ -140,7 +142,9 @@ export const takeWhile = <I extends Input = string>(
140
142
  */
141
143
  export const takeWhile1 = <I extends Input = string>(
142
144
  predicate: (token: TokenOf<I>) => boolean
143
- ): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> => Token.takeWhile<I>(predicate as any, { min: 1 })
145
+ ): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> =>
146
+ // SAFETY: a predicate over the input's tokens is a member of `TokenSet<I>` for each input kind
147
+ Token.takeWhile<I>(predicate as Token.TokenSet<I>, { min: 1 })
144
148
 
145
149
  /**
146
150
  * @since 0.1.0
@@ -150,7 +154,9 @@ export const takeWhileMN = <I extends Input = string>(
150
154
  m: number,
151
155
  n: number,
152
156
  predicate: (token: TokenOf<I>) => boolean
153
- ): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> => Token.takeWhile<I>(predicate as any, { min: m, max: n })
157
+ ): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> =>
158
+ // SAFETY: a predicate over the input's tokens is a member of `TokenSet<I>` for each input kind
159
+ Token.takeWhile<I>(predicate as Token.TokenSet<I>, { min: m, max: n })
154
160
 
155
161
  /**
156
162
  * @since 0.1.0
@@ -158,7 +164,9 @@ export const takeWhileMN = <I extends Input = string>(
158
164
  */
159
165
  export const takeTill = <I extends Input = string>(
160
166
  predicate: (token: TokenOf<I>) => boolean
161
- ): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> => Token.takeTill<I>(predicate as any)
167
+ ): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> =>
168
+ // SAFETY: a predicate over the input's tokens is a member of `TokenSet<I>` for each input kind
169
+ Token.takeTill<I>(predicate as Token.TokenSet<I>)
162
170
 
163
171
  /**
164
172
  * @since 0.1.0
@@ -166,7 +174,9 @@ export const takeTill = <I extends Input = string>(
166
174
  */
167
175
  export const takeTill1 = <I extends Input = string>(
168
176
  predicate: (token: TokenOf<I>) => boolean
169
- ): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> => Token.takeTill<I>(predicate as any, { min: 1 })
177
+ ): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> =>
178
+ // SAFETY: a predicate over the input's tokens is a member of `TokenSet<I>` for each input kind
179
+ Token.takeTill<I>(predicate as Token.TokenSet<I>, { min: 1 })
170
180
 
171
181
  /**
172
182
  * @since 0.1.0
package/src/ParseError.ts CHANGED
@@ -167,6 +167,9 @@ export const fromFailure = <E = never>(
167
167
  mode,
168
168
  expected: failure.expected,
169
169
  context: failure.context,
170
+ // SAFETY: `E` is the user error type of the parser whose run recorded
171
+ // `failure`; a failure with `hasCause` carries a cause raised by that
172
+ // parser's `fail` / `mapError`
170
173
  cause: failure.hasCause ? (failure.cause as E) : undefined,
171
174
  description: failure.message,
172
175
  encoding: input instanceof Uint8Array ? encoding : undefined