@thomasfosterau/effect-parse 0.1.0 → 0.3.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 (161) hide show
  1. package/README.md +291 -231
  2. package/dist/Ascii.d.ts +32 -53
  3. package/dist/Ascii.d.ts.map +1 -1
  4. package/dist/Ascii.js +576 -571
  5. package/dist/Ascii.js.map +1 -1
  6. package/dist/Binary.d.ts +6 -29
  7. package/dist/Binary.d.ts.map +1 -1
  8. package/dist/Binary.js +129 -116
  9. package/dist/Binary.js.map +1 -1
  10. package/dist/Bits.d.ts +4 -2
  11. package/dist/Bits.d.ts.map +1 -1
  12. package/dist/Bits.js +121 -123
  13. package/dist/Bits.js.map +1 -1
  14. package/dist/Compiler.d.ts +39 -0
  15. package/dist/Compiler.d.ts.map +1 -0
  16. package/dist/Compiler.js +48 -0
  17. package/dist/Compiler.js.map +1 -0
  18. package/dist/Encoding.d.ts +29 -46
  19. package/dist/Encoding.d.ts.map +1 -1
  20. package/dist/Encoding.js +76 -75
  21. package/dist/Encoding.js.map +1 -1
  22. package/dist/Expression.d.ts +15 -49
  23. package/dist/Expression.d.ts.map +1 -1
  24. package/dist/Expression.js +151 -132
  25. package/dist/Expression.js.map +1 -1
  26. package/dist/Input.d.ts +251 -177
  27. package/dist/Input.d.ts.map +1 -1
  28. package/dist/Input.js +409 -299
  29. package/dist/Input.js.map +1 -1
  30. package/dist/Nom.d.ts +45 -85
  31. package/dist/Nom.d.ts.map +1 -1
  32. package/dist/Nom.js +423 -453
  33. package/dist/Nom.js.map +1 -1
  34. package/dist/ParseError.d.ts +54 -49
  35. package/dist/ParseError.d.ts.map +1 -1
  36. package/dist/ParseError.js +232 -275
  37. package/dist/ParseError.js.map +1 -1
  38. package/dist/Parser.d.ts +345 -313
  39. package/dist/Parser.d.ts.map +1 -1
  40. package/dist/Parser.js +2034 -1802
  41. package/dist/Parser.js.map +1 -1
  42. package/dist/ParserSchema.d.ts +206 -7
  43. package/dist/ParserSchema.d.ts.map +1 -1
  44. package/dist/ParserSchema.js +678 -49
  45. package/dist/ParserSchema.js.map +1 -1
  46. package/dist/ParserStream.d.ts +26 -20
  47. package/dist/ParserStream.d.ts.map +1 -1
  48. package/dist/ParserStream.js +267 -255
  49. package/dist/ParserStream.js.map +1 -1
  50. package/dist/Syntax.d.ts +401 -0
  51. package/dist/Syntax.d.ts.map +1 -0
  52. package/dist/Syntax.js +717 -0
  53. package/dist/Syntax.js.map +1 -0
  54. package/dist/Text.d.ts +98 -134
  55. package/dist/Text.d.ts.map +1 -1
  56. package/dist/Text.js +534 -496
  57. package/dist/Text.js.map +1 -1
  58. package/dist/Token.d.ts +60 -42
  59. package/dist/Token.d.ts.map +1 -1
  60. package/dist/Token.js +331 -265
  61. package/dist/Token.js.map +1 -1
  62. package/dist/index.d.ts +16 -17
  63. package/dist/index.js +16 -17
  64. package/dist/internal/compiler/closure.d.ts +14 -16
  65. package/dist/internal/compiler/closure.d.ts.map +1 -1
  66. package/dist/internal/compiler/closure.js +1458 -1637
  67. package/dist/internal/compiler/closure.js.map +1 -1
  68. package/dist/internal/compiler/entries.d.ts +11 -11
  69. package/dist/internal/compiler/entries.d.ts.map +1 -1
  70. package/dist/internal/compiler/entries.js +36 -26
  71. package/dist/internal/compiler/entries.js.map +1 -1
  72. package/dist/internal/compiler/first.d.ts +19 -19
  73. package/dist/internal/compiler/first.d.ts.map +1 -1
  74. package/dist/internal/compiler/first.js +251 -227
  75. package/dist/internal/compiler/first.js.map +1 -1
  76. package/dist/internal/compiler/jit.d.ts +6 -17
  77. package/dist/internal/compiler/jit.d.ts.map +1 -1
  78. package/dist/internal/compiler/jit.js +860 -988
  79. package/dist/internal/compiler/jit.js.map +1 -1
  80. package/dist/internal/compiler/registry.d.ts +20 -21
  81. package/dist/internal/compiler/registry.d.ts.map +1 -1
  82. package/dist/internal/compiler/registry.js +21 -41
  83. package/dist/internal/compiler/registry.js.map +1 -1
  84. package/dist/internal/compiler/sets.d.ts +9 -13
  85. package/dist/internal/compiler/sets.d.ts.map +1 -1
  86. package/dist/internal/compiler/sets.js +76 -73
  87. package/dist/internal/compiler/sets.js.map +1 -1
  88. package/dist/internal/entries.d.ts +3 -3
  89. package/dist/internal/entries.d.ts.map +1 -1
  90. package/dist/internal/entries.js +38 -30
  91. package/dist/internal/entries.js.map +1 -1
  92. package/dist/internal/node.d.ts +177 -173
  93. package/dist/internal/node.d.ts.map +1 -1
  94. package/dist/internal/node.js +77 -66
  95. package/dist/internal/node.js.map +1 -1
  96. package/dist/internal/numbers.d.ts +7 -8
  97. package/dist/internal/numbers.d.ts.map +1 -1
  98. package/dist/internal/numbers.js +246 -276
  99. package/dist/internal/numbers.js.map +1 -1
  100. package/dist/internal/resume.d.ts +6 -24
  101. package/dist/internal/resume.d.ts.map +1 -1
  102. package/dist/internal/resume.js +30 -29
  103. package/dist/internal/resume.js.map +1 -1
  104. package/dist/internal/run.d.ts +15 -0
  105. package/dist/internal/run.d.ts.map +1 -0
  106. package/dist/internal/run.js +36 -0
  107. package/dist/internal/run.js.map +1 -0
  108. package/dist/internal/stack.d.ts +16 -0
  109. package/dist/internal/stack.d.ts.map +1 -0
  110. package/dist/internal/stack.js +36 -0
  111. package/dist/internal/stack.js.map +1 -0
  112. package/dist/internal/syntax.d.ts +147 -0
  113. package/dist/internal/syntax.d.ts.map +1 -0
  114. package/dist/internal/syntax.js +309 -0
  115. package/dist/internal/syntax.js.map +1 -0
  116. package/dist/internal/text.d.ts +10 -2
  117. package/dist/internal/text.d.ts.map +1 -1
  118. package/dist/internal/text.js +295 -345
  119. package/dist/internal/text.js.map +1 -1
  120. package/dist/internal/ties.d.ts +30 -0
  121. package/dist/internal/ties.d.ts.map +1 -0
  122. package/dist/internal/ties.js +67 -0
  123. package/dist/internal/ties.js.map +1 -0
  124. package/dist/internal/tokens.d.ts +25 -30
  125. package/dist/internal/tokens.d.ts.map +1 -1
  126. package/dist/internal/tokens.js +369 -363
  127. package/dist/internal/tokens.js.map +1 -1
  128. package/package.json +42 -28
  129. package/src/Ascii.ts +278 -187
  130. package/src/Binary.ts +150 -44
  131. package/src/Bits.ts +6 -3
  132. package/src/Compiler.ts +98 -0
  133. package/src/Expression.ts +24 -16
  134. package/src/Input.ts +210 -35
  135. package/src/Nom.ts +4 -3
  136. package/src/ParseError.ts +49 -52
  137. package/src/Parser.ts +1199 -799
  138. package/src/ParserSchema.ts +982 -23
  139. package/src/ParserStream.ts +104 -80
  140. package/src/Syntax.ts +900 -0
  141. package/src/Text.ts +272 -187
  142. package/src/Token.ts +180 -87
  143. package/src/index.ts +2 -0
  144. package/src/internal/compiler/closure.ts +121 -88
  145. package/src/internal/compiler/entries.ts +21 -8
  146. package/src/internal/compiler/first.ts +17 -15
  147. package/src/internal/compiler/jit.ts +360 -157
  148. package/src/internal/compiler/registry.ts +12 -33
  149. package/src/internal/compiler/sets.ts +17 -11
  150. package/src/internal/entries.ts +4 -2
  151. package/src/internal/node.ts +51 -37
  152. package/src/internal/numbers.ts +22 -20
  153. package/src/internal/resume.ts +8 -4
  154. package/src/internal/run.ts +41 -0
  155. package/src/internal/stack.ts +41 -0
  156. package/src/internal/syntax.ts +426 -0
  157. package/src/internal/text.ts +32 -25
  158. package/src/internal/ties.ts +83 -0
  159. package/src/internal/tokens.ts +96 -51
  160. package/dist/index.d.ts.map +0 -1
  161. package/dist/index.js.map +0 -1
@@ -23,6 +23,7 @@
23
23
  *
24
24
  * @since 0.1.0
25
25
  */
26
+ import * as Predicate from "effect/Predicate"
26
27
  import type * as Context from "effect/Context"
27
28
  import * as Data from "effect/Data"
28
29
  import * as Effect from "effect/Effect"
@@ -31,8 +32,10 @@ import * as Stream from "effect/Stream"
31
32
  import type { BinaryInput, Input, Source } from "./Input.js"
32
33
  import { Fail, Failure, fromSource, State } from "./Input.js"
33
34
  import * as ParseError from "./ParseError.js"
34
- import * as Compiler from "./internal/compiler/registry.js"
35
+ import * as Registry from "./internal/compiler/registry.js"
35
36
  import type * as Resume from "./internal/resume.js"
37
+ import * as Run from "./internal/run.js"
38
+ import * as Stack from "./internal/stack.js"
36
39
  import type { Parser } from "./Parser.js"
37
40
 
38
41
  /**
@@ -44,7 +47,7 @@ import type { Parser } from "./Parser.js"
44
47
  export type Chunkable = string | Uint8Array | ReadonlyArray<unknown>
45
48
 
46
49
  const concat = <I extends Chunkable>(a: I, b: I): I => {
47
- if (typeof a === "string") return (a + (b as string)) as I
50
+ if (Predicate.isString(a)) return (a + (b as string)) as I
48
51
  if (a instanceof Uint8Array) {
49
52
  if (a.length === 0) return b
50
53
  const out = new Uint8Array(a.length + (b as Uint8Array).length)
@@ -56,7 +59,7 @@ const concat = <I extends Chunkable>(a: I, b: I): I => {
56
59
  }
57
60
 
58
61
  const sliceFrom = <I extends Chunkable>(input: I, offset: number): I =>
59
- (typeof input === "string" ? input.slice(offset) : input.slice(offset)) as I
62
+ (Predicate.isString(input) ? input.slice(offset) : input.slice(offset)) as I
60
63
 
61
64
  const noProgress = (input: Input, offset: number) =>
62
65
  ParseError.fromFailure<never>(
@@ -84,6 +87,11 @@ export interface ParseManyOptions<I> {
84
87
  * Error offsets are relative to the internal buffer of unconsumed input,
85
88
  * which is also the `input` of the reported `ParseError`.
86
89
  *
90
+ * A parser compiled with the `Compiler` module runs compiled, with the
91
+ * build that handles partial input (see `Parser.run`); a value that fails
92
+ * or needs more input is parsed again interpreted, so errors and
93
+ * `Incomplete` are the interpreter's.
94
+ *
87
95
  * @since 0.1.0
88
96
  * @category combinators
89
97
  */
@@ -97,54 +105,57 @@ export const parseMany: {
97
105
  parser: Parser<A, E, R, I>,
98
106
  options?: ParseManyOptions<I>
99
107
  ): Stream.Stream<A, E0 | ParseError.ParseError<E>, R0 | R>
100
- } = dual((args) => Stream.isStream(args[0]), <I extends Chunkable, E0, R0, A, E, R>(
101
- self: Stream.Stream<Source<I>, E0, R0>,
102
- parser: Parser<A, E, R, I>,
103
- options?: ParseManyOptions<I>
104
- ): Stream.Stream<A, E0 | ParseError.ParseError<E>, R0 | R> =>
105
- Stream.suspend(() => {
106
- const step = parser.step
107
- let buffer: I | undefined = options?.empty === undefined ? undefined : fromSource<I>(options.empty)
108
+ } = /*#__PURE__*/ dual(
109
+ (args) => Stream.isStream(args[0]),
110
+ <I extends Chunkable, E0, R0, A, E, R>(
111
+ self: Stream.Stream<Source<I>, E0, R0>,
112
+ parser: Parser<A, E, R, I>,
113
+ options?: ParseManyOptions<I>
114
+ ): Stream.Stream<A, E0 | ParseError.ParseError<E>, R0 | R> =>
115
+ Stream.suspend(() => {
116
+ const step = parser.step
117
+ let buffer: I | undefined = options?.empty === undefined ? undefined : fromSource<I>(options.empty)
108
118
 
109
- const drain = (
110
- context: any,
111
- partial: boolean
112
- ): Effect.Effect<Array<A>, ParseError.ParseError<E>> => {
113
- const out: Array<A> = []
114
- if (buffer === undefined) return Effect.succeed(out)
115
- const input = buffer
116
- let offset = 0
117
- while (offset < input.length) {
118
- const state = new State(input, { partial, context, offset })
119
- const a = step(state)
120
- if (a === Fail) {
121
- if (partial && state.mode === "Incomplete") break
122
- return Effect.fail(ParseError.fromFailure<E>(input, state.reportedFailure(), state.mode, state.encoding))
119
+ const drain = (context: any, partial: boolean): Effect.Effect<Array<A>, ParseError.ParseError<E>> => {
120
+ const out: Array<A> = []
121
+ if (buffer === undefined) return Effect.succeed(out)
122
+ const input = buffer
123
+ // One state for the whole buffer, reset before each value
124
+ const state = new State(input)
125
+ let offset = 0
126
+ while (offset < input.length) {
127
+ state.reset(offset, { partial, context })
128
+ const a = Run.runOn(parser, step, state)
129
+ if (a === Fail) {
130
+ if (partial && state.mode === "Incomplete") break
131
+ return Effect.fail(ParseError.fromFailure<E>(input, state.reportedFailure(), state.mode, state.encoding))
132
+ }
133
+ if (state.pos === offset) return Effect.fail(noProgress(input, offset))
134
+ out.push(a)
135
+ offset = state.pos
123
136
  }
124
- if (state.pos === offset) return Effect.fail(noProgress(input, offset))
125
- out.push(a)
126
- offset = state.pos
137
+ buffer = sliceFrom(input, offset)
138
+ return Effect.succeed(out)
127
139
  }
128
- buffer = sliceFrom(input, offset)
129
- return Effect.succeed(out)
130
- }
131
140
 
132
- const feed = (source: Source<I>) =>
133
- Effect.flatMap(Effect.context<R>(), (context) =>
134
- Effect.suspend(() => {
135
- const chunk = fromSource<I>(source)
136
- buffer = buffer === undefined ? chunk : concat(buffer, chunk)
137
- return drain(context, true)
138
- }))
141
+ const feed = (source: Source<I>) =>
142
+ Effect.flatMap(Effect.context<R>(), (context) =>
143
+ Effect.suspend(() => {
144
+ const chunk = fromSource<I>(source)
145
+ buffer = buffer === undefined ? chunk : concat(buffer, chunk)
146
+ return drain(context, true)
147
+ })
148
+ )
139
149
 
140
- const finish = Effect.flatMap(Effect.context<R>(), (context) => Effect.suspend(() => drain(context, false)))
150
+ const finish = Effect.flatMap(Effect.context<R>(), (context) => Effect.suspend(() => drain(context, false)))
141
151
 
142
- return self.pipe(
143
- Stream.mapEffect(feed),
144
- Stream.flattenIterable,
145
- Stream.concat(Stream.unwrap(Effect.map(finish, Stream.fromIterable)))
146
- )
147
- }))
152
+ return self.pipe(
153
+ Stream.mapEffect(feed),
154
+ Stream.flattenIterable,
155
+ Stream.concat(Stream.unwrap(Effect.map(finish, Stream.fromIterable)))
156
+ )
157
+ })
158
+ )
148
159
 
149
160
  /**
150
161
  * Parses a stream of chunks incrementally, as one input. Chunks are parsed
@@ -175,7 +186,7 @@ class Incremental<A, E, I extends Chunkable> {
175
186
  }
176
187
 
177
188
  private append(chunk: I): void {
178
- if (typeof chunk === "string") {
189
+ if (Predicate.isString(chunk)) {
179
190
  this.kind ??= 0
180
191
  this.text += chunk
181
192
  this.length += chunk.length
@@ -225,7 +236,7 @@ class Incremental<A, E, I extends Chunkable> {
225
236
 
226
237
  /** The step attempts run: the parser's resumable compiled code if it was compiled, else the interpreter. */
227
238
  private step(state: State<I>): unknown {
228
- return (Compiler.stepFor(this.parser, state, true) ?? this.parser.step)(state)
239
+ return Stack.run(Registry.stepFor(this.parser, state, true) ?? this.parser.step, state)
229
240
  }
230
241
 
231
242
  private attempt(): void {
@@ -257,7 +268,7 @@ class Incremental<A, E, I extends Chunkable> {
257
268
  // same as if the input had been parsed in one go
258
269
  const all = this.input()
259
270
  const state = new State(all, { context: this.context })
260
- const a = this.parser.step(state)
271
+ const a = Stack.run(this.parser.step, state)
261
272
  if (a !== Fail && state.pos === state.end) return Effect.succeed(a)
262
273
  if (a !== Fail) state.backtrack("Eof", ["end of input"])
263
274
  return Effect.fail(ParseError.fromFailure<E>(all, state.reportedFailure(), state.mode, state.encoding))
@@ -277,8 +288,8 @@ class Incremental<A, E, I extends Chunkable> {
277
288
  *
278
289
  * The result and any `ParseError` are those of parsing the whole input at
279
290
  * once: errors are reported once the stream has ended, by an ordinary
280
- * interpreted parse of the whole input. A parser compiled with
281
- * `Parser.compile` streams compiled too (with a build that handles partial
291
+ * interpreted parse of the whole input. A parser compiled with the
292
+ * `Compiler` module streams compiled too (with a build that handles partial
282
293
  * input), which is several times faster. As with compiled parsers,
283
294
  * callbacks should be pure: the elements parsed before a checkpoint are
284
295
  * not parsed again, and on failure everything is parsed again.
@@ -296,20 +307,24 @@ export const parseAll: {
296
307
  parser: Parser<A, E, R, I>,
297
308
  options?: ParseManyOptions<I>
298
309
  ): Effect.Effect<A, E0 | ParseError.ParseError<E>, R0 | R>
299
- } = dual((args) => Stream.isStream(args[0]), <I extends Chunkable, E0, R0, A, E, R>(
300
- self: Stream.Stream<Source<I>, E0, R0>,
301
- parser: Parser<A, E, R, I>,
302
- options?: ParseManyOptions<I>
303
- ): Effect.Effect<A, E0 | ParseError.ParseError<E>, R0 | R> =>
304
- Effect.flatMap(Effect.context<R>(), (context) =>
305
- Effect.suspend(() => {
306
- const empty = options?.empty === undefined ? undefined : fromSource<I>(options.empty)
307
- const incremental = new Incremental(parser, context as Context.Context<never>, empty)
308
- return Effect.flatMap(
309
- Stream.runForEach(self, (chunk) => Effect.sync(() => incremental.push(fromSource<I>(chunk)))),
310
- () => Effect.suspend(() => incremental.finish())
311
- )
312
- })))
310
+ } = /*#__PURE__*/ dual(
311
+ (args) => Stream.isStream(args[0]),
312
+ <I extends Chunkable, E0, R0, A, E, R>(
313
+ self: Stream.Stream<Source<I>, E0, R0>,
314
+ parser: Parser<A, E, R, I>,
315
+ options?: ParseManyOptions<I>
316
+ ): Effect.Effect<A, E0 | ParseError.ParseError<E>, R0 | R> =>
317
+ Effect.flatMap(Effect.context<R>(), (context) =>
318
+ Effect.suspend(() => {
319
+ const empty = options?.empty === undefined ? undefined : fromSource<I>(options.empty)
320
+ const incremental = new Incremental(parser, context as Context.Context<never>, empty)
321
+ return Effect.flatMap(
322
+ Stream.runForEach(self, (chunk) => Effect.sync(() => incremental.push(fromSource<I>(chunk)))),
323
+ () => Effect.suspend(() => incremental.finish())
324
+ )
325
+ })
326
+ )
327
+ )
313
328
 
314
329
  /**
315
330
  * An error reading a `ReadableStream` given to {@link parseReadable} or
@@ -318,7 +333,7 @@ export const parseAll: {
318
333
  * @since 0.1.0
319
334
  * @category errors
320
335
  */
321
- export class ReadError extends Data.TaggedError("ReadError")<{ readonly cause: unknown }> {}
336
+ export class ReadError extends /*#__PURE__*/ Data.TaggedError("ReadError")<{ readonly cause: unknown }> {}
322
337
 
323
338
  /**
324
339
  * Parses a web `ReadableStream` of bytes, such as the body of a `fetch`
@@ -349,15 +364,18 @@ export const parseReadable: {
349
364
  self: ReadableStream<BinaryInput>,
350
365
  parser: Parser<A, E, R, Uint8Array>
351
366
  ): Effect.Effect<A, ParseError.ParseError<E> | ReadError, R>
352
- } = dual(2, <A, E, R>(
353
- self: ReadableStream<BinaryInput>,
354
- parser: Parser<A, E, R, Uint8Array>
355
- ): Effect.Effect<A, ParseError.ParseError<E> | ReadError, R> =>
356
- parseAll(
357
- Stream.fromReadableStream({ evaluate: () => self, onError: (cause) => new ReadError({ cause }) }),
358
- parser,
359
- { empty: new Uint8Array(0) }
360
- ))
367
+ } = /*#__PURE__*/ dual(
368
+ 2,
369
+ <A, E, R>(
370
+ self: ReadableStream<BinaryInput>,
371
+ parser: Parser<A, E, R, Uint8Array>
372
+ ): Effect.Effect<A, ParseError.ParseError<E> | ReadError, R> =>
373
+ parseAll(
374
+ Stream.fromReadableStream({ evaluate: () => self, onError: (cause) => new ReadError({ cause }) }),
375
+ parser,
376
+ { empty: new Uint8Array(0) }
377
+ )
378
+ )
361
379
 
362
380
  /**
363
381
  * Parses the body of a `fetch` `Response` incrementally, as it downloads
@@ -382,9 +400,15 @@ export const parseResponse: {
382
400
  <A, E, R>(
383
401
  parser: Parser<A, E, R, Uint8Array>
384
402
  ): (self: Response) => Effect.Effect<A, ParseError.ParseError<E> | ReadError, R>
385
- <A, E, R>(self: Response, parser: Parser<A, E, R, Uint8Array>): Effect.Effect<A, ParseError.ParseError<E> | ReadError, R>
386
- } = dual(2, <A, E, R>(
387
- self: Response,
388
- parser: Parser<A, E, R, Uint8Array>
389
- ): Effect.Effect<A, ParseError.ParseError<E> | ReadError, R> =>
390
- parseReadable(self.body ?? new ReadableStream<Uint8Array>({ start: (c) => c.close() }), parser))
403
+ <A, E, R>(
404
+ self: Response,
405
+ parser: Parser<A, E, R, Uint8Array>
406
+ ): Effect.Effect<A, ParseError.ParseError<E> | ReadError, R>
407
+ } = /*#__PURE__*/ dual(
408
+ 2,
409
+ <A, E, R>(
410
+ self: Response,
411
+ parser: Parser<A, E, R, Uint8Array>
412
+ ): Effect.Effect<A, ParseError.ParseError<E> | ReadError, R> =>
413
+ parseReadable(self.body ?? new ReadableStream<Uint8Array>({ start: (c) => c.close() }), parser)
414
+ )