@thomasfosterau/effect-parse 0.0.0 → 0.2.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.
- package/README.md +247 -230
- package/dist/Ascii.d.ts +32 -53
- package/dist/Ascii.d.ts.map +1 -1
- package/dist/Ascii.js +576 -571
- package/dist/Ascii.js.map +1 -1
- package/dist/Binary.d.ts +6 -29
- package/dist/Binary.d.ts.map +1 -1
- package/dist/Binary.js +129 -116
- package/dist/Binary.js.map +1 -1
- package/dist/Bits.d.ts +4 -2
- package/dist/Bits.d.ts.map +1 -1
- package/dist/Bits.js +121 -123
- package/dist/Bits.js.map +1 -1
- package/dist/Compiler.d.ts +39 -0
- package/dist/Compiler.d.ts.map +1 -0
- package/dist/Compiler.js +48 -0
- package/dist/Compiler.js.map +1 -0
- package/dist/Encoding.d.ts +29 -46
- package/dist/Encoding.d.ts.map +1 -1
- package/dist/Encoding.js +76 -75
- package/dist/Encoding.js.map +1 -1
- package/dist/Expression.d.ts +15 -49
- package/dist/Expression.d.ts.map +1 -1
- package/dist/Expression.js +143 -131
- package/dist/Expression.js.map +1 -1
- package/dist/Input.d.ts +206 -177
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +317 -299
- package/dist/Input.js.map +1 -1
- package/dist/Nom.d.ts +44 -84
- package/dist/Nom.d.ts.map +1 -1
- package/dist/Nom.js +423 -453
- package/dist/Nom.js.map +1 -1
- package/dist/ParseError.d.ts +54 -49
- package/dist/ParseError.d.ts.map +1 -1
- package/dist/ParseError.js +233 -275
- package/dist/ParseError.js.map +1 -1
- package/dist/Parser.d.ts +345 -313
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +2010 -1802
- package/dist/Parser.js.map +1 -1
- package/dist/ParserSchema.d.ts +8 -7
- package/dist/ParserSchema.d.ts.map +1 -1
- package/dist/ParserSchema.js +49 -49
- package/dist/ParserSchema.js.map +1 -1
- package/dist/ParserStream.d.ts +26 -20
- package/dist/ParserStream.d.ts.map +1 -1
- package/dist/ParserStream.js +267 -255
- package/dist/ParserStream.js.map +1 -1
- package/dist/Syntax.d.ts +401 -0
- package/dist/Syntax.d.ts.map +1 -0
- package/dist/Syntax.js +717 -0
- package/dist/Syntax.js.map +1 -0
- package/dist/Text.d.ts +98 -134
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +534 -496
- package/dist/Text.js.map +1 -1
- package/dist/Token.d.ts +60 -42
- package/dist/Token.d.ts.map +1 -1
- package/dist/Token.js +331 -265
- package/dist/Token.js.map +1 -1
- package/dist/index.d.ts +16 -17
- package/dist/index.js +16 -17
- package/dist/internal/compiler/closure.d.ts +14 -16
- package/dist/internal/compiler/closure.d.ts.map +1 -1
- package/dist/internal/compiler/closure.js +1458 -1637
- package/dist/internal/compiler/closure.js.map +1 -1
- package/dist/internal/compiler/entries.d.ts +11 -11
- package/dist/internal/compiler/entries.d.ts.map +1 -1
- package/dist/internal/compiler/entries.js +36 -26
- package/dist/internal/compiler/entries.js.map +1 -1
- package/dist/internal/compiler/first.d.ts +19 -19
- package/dist/internal/compiler/first.d.ts.map +1 -1
- package/dist/internal/compiler/first.js +251 -227
- package/dist/internal/compiler/first.js.map +1 -1
- package/dist/internal/compiler/jit.d.ts +6 -17
- package/dist/internal/compiler/jit.d.ts.map +1 -1
- package/dist/internal/compiler/jit.js +860 -988
- package/dist/internal/compiler/jit.js.map +1 -1
- package/dist/internal/compiler/registry.d.ts +20 -21
- package/dist/internal/compiler/registry.d.ts.map +1 -1
- package/dist/internal/compiler/registry.js +21 -41
- package/dist/internal/compiler/registry.js.map +1 -1
- package/dist/internal/compiler/sets.d.ts +9 -13
- package/dist/internal/compiler/sets.d.ts.map +1 -1
- package/dist/internal/compiler/sets.js +76 -73
- package/dist/internal/compiler/sets.js.map +1 -1
- package/dist/internal/entries.d.ts +3 -3
- package/dist/internal/entries.d.ts.map +1 -1
- package/dist/internal/entries.js +38 -30
- package/dist/internal/entries.js.map +1 -1
- package/dist/internal/node.d.ts +177 -173
- package/dist/internal/node.d.ts.map +1 -1
- package/dist/internal/node.js +77 -66
- package/dist/internal/node.js.map +1 -1
- package/dist/internal/numbers.d.ts +7 -8
- package/dist/internal/numbers.d.ts.map +1 -1
- package/dist/internal/numbers.js +246 -276
- package/dist/internal/numbers.js.map +1 -1
- package/dist/internal/resume.d.ts +6 -24
- package/dist/internal/resume.d.ts.map +1 -1
- package/dist/internal/resume.js +30 -29
- package/dist/internal/resume.js.map +1 -1
- package/dist/internal/run.d.ts +15 -0
- package/dist/internal/run.d.ts.map +1 -0
- package/dist/internal/run.js +36 -0
- package/dist/internal/run.js.map +1 -0
- package/dist/internal/stack.d.ts +16 -0
- package/dist/internal/stack.d.ts.map +1 -0
- package/dist/internal/stack.js +26 -0
- package/dist/internal/stack.js.map +1 -0
- package/dist/internal/syntax.d.ts +146 -0
- package/dist/internal/syntax.d.ts.map +1 -0
- package/dist/internal/syntax.js +305 -0
- package/dist/internal/syntax.js.map +1 -0
- package/dist/internal/text.d.ts +10 -2
- package/dist/internal/text.d.ts.map +1 -1
- package/dist/internal/text.js +295 -345
- package/dist/internal/text.js.map +1 -1
- package/dist/internal/tokens.d.ts +25 -30
- package/dist/internal/tokens.d.ts.map +1 -1
- package/dist/internal/tokens.js +369 -363
- package/dist/internal/tokens.js.map +1 -1
- package/package.json +42 -28
- package/src/Ascii.ts +278 -187
- package/src/Binary.ts +150 -44
- package/src/Bits.ts +6 -3
- package/src/Compiler.ts +98 -0
- package/src/Expression.ts +10 -5
- package/src/Input.ts +106 -28
- package/src/Nom.ts +4 -3
- package/src/ParseError.ts +48 -51
- package/src/Parser.ts +1163 -795
- package/src/ParserStream.ts +104 -80
- package/src/Syntax.ts +900 -0
- package/src/Text.ts +272 -187
- package/src/Token.ts +180 -87
- package/src/index.ts +2 -0
- package/src/internal/compiler/closure.ts +121 -88
- package/src/internal/compiler/entries.ts +21 -8
- package/src/internal/compiler/first.ts +17 -15
- package/src/internal/compiler/jit.ts +360 -157
- package/src/internal/compiler/registry.ts +12 -33
- package/src/internal/compiler/sets.ts +17 -11
- package/src/internal/entries.ts +4 -2
- package/src/internal/node.ts +51 -37
- package/src/internal/numbers.ts +22 -20
- package/src/internal/resume.ts +8 -4
- package/src/internal/run.ts +41 -0
- package/src/internal/stack.ts +36 -0
- package/src/internal/syntax.ts +421 -0
- package/src/internal/text.ts +32 -25
- package/src/internal/tokens.ts +96 -51
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/src/ParserStream.ts
CHANGED
|
@@ -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
|
|
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 (
|
|
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
|
-
(
|
|
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(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
125
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
150
|
+
const finish = Effect.flatMap(Effect.context<R>(), (context) => Effect.suspend(() => drain(context, false)))
|
|
141
151
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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 (
|
|
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 (
|
|
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
|
|
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
|
-
* `
|
|
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(
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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(
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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>(
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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
|
+
)
|