@thomasfosterau/effect-parse 0.1.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/Parser.ts
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
*
|
|
30
30
|
* @since 0.1.0
|
|
31
31
|
*/
|
|
32
|
+
import * as Predicate from "effect/Predicate"
|
|
32
33
|
import * as Context from "effect/Context"
|
|
33
34
|
import * as Effect from "effect/Effect"
|
|
34
35
|
import { dual } from "effect/Function"
|
|
@@ -42,9 +43,11 @@ import type { ErrMode, Input, Slice, Source, TraceEvent } from "./Input.js"
|
|
|
42
43
|
import { Fail, Failure, mergeExpected, mergeFailures, State } from "./Input.js"
|
|
43
44
|
import type { ErrorKind } from "./ParseError.js"
|
|
44
45
|
import * as ParseError from "./ParseError.js"
|
|
45
|
-
import * as
|
|
46
|
+
import * as Registry from "./internal/compiler/registry.js"
|
|
46
47
|
import * as Entries from "./internal/entries.js"
|
|
47
48
|
import * as Resume from "./internal/resume.js"
|
|
49
|
+
import * as Run from "./internal/run.js"
|
|
50
|
+
import * as Stack from "./internal/stack.js"
|
|
48
51
|
import type { Node } from "./internal/node.js"
|
|
49
52
|
import { bounds, NodeId } from "./internal/node.js"
|
|
50
53
|
|
|
@@ -56,7 +59,7 @@ import { bounds, NodeId } from "./internal/node.js"
|
|
|
56
59
|
* @since 0.1.0
|
|
57
60
|
* @category type ids
|
|
58
61
|
*/
|
|
59
|
-
export const TypeId
|
|
62
|
+
export const TypeId = "~effect-parse/Parser" as const
|
|
60
63
|
|
|
61
64
|
/**
|
|
62
65
|
* A parser that consumes input of type `I`, producing a value of type `A`,
|
|
@@ -134,9 +137,11 @@ export declare namespace Parser {
|
|
|
134
137
|
*
|
|
135
138
|
* @since 0.1.0
|
|
136
139
|
*/
|
|
137
|
-
export type InputOf<P> = [P] extends [never]
|
|
138
|
-
|
|
139
|
-
:
|
|
140
|
+
export type InputOf<P> = [P] extends [never]
|
|
141
|
+
? Input
|
|
142
|
+
: [P] extends [Parser<infer _A, infer _E, infer _R, infer I>]
|
|
143
|
+
? I
|
|
144
|
+
: never
|
|
140
145
|
}
|
|
141
146
|
|
|
142
147
|
/**
|
|
@@ -158,10 +163,19 @@ export type Range = number | { readonly min?: number | undefined; readonly max?:
|
|
|
158
163
|
* @since 0.1.0
|
|
159
164
|
* @category models
|
|
160
165
|
*/
|
|
161
|
-
export type Repeated<A, Rg> = Rg extends number
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
166
|
+
export type Repeated<A, Rg> = Rg extends number
|
|
167
|
+
? number extends Rg
|
|
168
|
+
? Array<A>
|
|
169
|
+
: Rg extends 0
|
|
170
|
+
? Array<A>
|
|
171
|
+
: NonEmpty<A>
|
|
172
|
+
: Rg extends { readonly min: infer M extends number }
|
|
173
|
+
? number extends M
|
|
174
|
+
? Array<A>
|
|
175
|
+
: M extends 0
|
|
176
|
+
? Array<A>
|
|
177
|
+
: NonEmpty<A>
|
|
178
|
+
: Array<A>
|
|
165
179
|
|
|
166
180
|
type NonEmpty<A> = [A, ...Array<A>]
|
|
167
181
|
|
|
@@ -241,7 +255,7 @@ class ParserImpl<A, E, R, I extends Input> implements Parser<A, E, R, I> {
|
|
|
241
255
|
* @category guards
|
|
242
256
|
*/
|
|
243
257
|
export const isParser = (u: unknown): u is Parser<unknown, unknown, unknown, never> =>
|
|
244
|
-
|
|
258
|
+
Predicate.isObjectOrArray(u) && TypeId in u
|
|
245
259
|
|
|
246
260
|
const isParserArg = (args: IArguments) => isParser(args[0])
|
|
247
261
|
const isTwoParserArgs = (args: IArguments) => isParser(args[0]) && isParser(args[1])
|
|
@@ -306,8 +320,11 @@ const nodeOfParser = (p: Parser.Any): Node | undefined => (p as any)[NodeId]
|
|
|
306
320
|
export const named: {
|
|
307
321
|
(name: string): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
308
322
|
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, name: string): Parser<A, E, R, I>
|
|
309
|
-
} = dual(
|
|
310
|
-
|
|
323
|
+
} = /*#__PURE__*/ dual(
|
|
324
|
+
2,
|
|
325
|
+
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, name: string): Parser<A, E, R, I> =>
|
|
326
|
+
new ParserImpl(self.step, name, nodeOfParser(self))
|
|
327
|
+
)
|
|
311
328
|
|
|
312
329
|
/**
|
|
313
330
|
* A parser that consumes nothing and succeeds with the given value.
|
|
@@ -334,7 +351,7 @@ export const sync = <A>(evaluate: () => A): Parser<A, never, never, Input> =>
|
|
|
334
351
|
* @since 0.1.0
|
|
335
352
|
* @category constructors
|
|
336
353
|
*/
|
|
337
|
-
export const empty: Parser<void, never, never, Input> = described(() => undefined, "empty", {
|
|
354
|
+
export const empty: Parser<void, never, never, Input> = /*#__PURE__*/ described(() => undefined, "empty", {
|
|
338
355
|
_tag: "Succeed",
|
|
339
356
|
value: undefined
|
|
340
357
|
})
|
|
@@ -374,7 +391,7 @@ const failBacktrack: Node = { _tag: "Fail", mode: "Backtrack" }
|
|
|
374
391
|
* @since 0.1.0
|
|
375
392
|
* @category constructors
|
|
376
393
|
*/
|
|
377
|
-
export const reject: Parser<never, never, never, Input> = described<never, never, never, Input>(
|
|
394
|
+
export const reject: Parser<never, never, never, Input> = /*#__PURE__*/ described<never, never, never, Input>(
|
|
378
395
|
(state) => state.backtrack("Fail"),
|
|
379
396
|
"reject",
|
|
380
397
|
failBacktrack
|
|
@@ -400,7 +417,7 @@ export const failMessage = (message: string): Parser<never, never, never, Input>
|
|
|
400
417
|
* @since 0.1.0
|
|
401
418
|
* @category constructors
|
|
402
419
|
*/
|
|
403
|
-
export const todo: Parser<never, never, never, Input> = described<never, never, never, Input>(
|
|
420
|
+
export const todo: Parser<never, never, never, Input> = /*#__PURE__*/ described<never, never, never, Input>(
|
|
404
421
|
(state) => state.failMessage("Cut", "Assert", "`todo` parser reached"),
|
|
405
422
|
"todo",
|
|
406
423
|
{ _tag: "Fail", mode: "Cut" }
|
|
@@ -410,6 +427,11 @@ export const todo: Parser<never, never, never, Input> = described<never, never,
|
|
|
410
427
|
* Lazily constructs a parser, which is needed to define recursive grammars.
|
|
411
428
|
* The thunk is evaluated once, on first use.
|
|
412
429
|
*
|
|
430
|
+
* Each level of recursion uses some of the call stack, interpreted or
|
|
431
|
+
* compiled, so input nested a few thousand levels deep exhausts it. The
|
|
432
|
+
* runners catch the overflow and fail with an unrecoverable `ParseError` of
|
|
433
|
+
* kind `"TooDeep"` at the offset reached, instead of throwing.
|
|
434
|
+
*
|
|
413
435
|
* @example
|
|
414
436
|
* ```ts
|
|
415
437
|
* import { Parser, Token } from "@thomasfosterau/effect-parse"
|
|
@@ -431,7 +453,7 @@ export const suspend = <A, E = never, R = never, I extends Input = string>(
|
|
|
431
453
|
let parser: Parser<A, E, R, I> | undefined
|
|
432
454
|
return described((state) => (parser ??= evaluate()).step(state), "suspend", {
|
|
433
455
|
_tag: "Suspend",
|
|
434
|
-
resolve: () => parser ??= evaluate()
|
|
456
|
+
resolve: () => (parser ??= evaluate())
|
|
435
457
|
})
|
|
436
458
|
}
|
|
437
459
|
|
|
@@ -441,7 +463,7 @@ export const suspend = <A, E = never, R = never, I extends Input = string>(
|
|
|
441
463
|
* @since 0.1.0
|
|
442
464
|
* @category constructors
|
|
443
465
|
*/
|
|
444
|
-
export const location: Parser<number, never, never, Input> = described((state) => state.pos, "location", {
|
|
466
|
+
export const location: Parser<number, never, never, Input> = /*#__PURE__*/ described((state) => state.pos, "location", {
|
|
445
467
|
_tag: "Location"
|
|
446
468
|
})
|
|
447
469
|
|
|
@@ -453,11 +475,15 @@ export const location: Parser<number, never, never, Input> = described((state) =
|
|
|
453
475
|
* @since 0.1.0
|
|
454
476
|
* @category constructors
|
|
455
477
|
*/
|
|
456
|
-
export const eof: Parser<void, never, never, Input> = described(
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
478
|
+
export const eof: Parser<void, never, never, Input> = /*#__PURE__*/ described(
|
|
479
|
+
(state) => {
|
|
480
|
+
if (state.pos < state.end) return state.backtrack("Eof", expectedEof)
|
|
481
|
+
if (state.partial) return state.incomplete(1, expectedEof)
|
|
482
|
+
return undefined
|
|
483
|
+
},
|
|
484
|
+
"eof",
|
|
485
|
+
{ _tag: "Eof" }
|
|
486
|
+
)
|
|
461
487
|
|
|
462
488
|
const expectedEof = ["end of input"]
|
|
463
489
|
|
|
@@ -474,13 +500,20 @@ const expectedEof = ["end of input"]
|
|
|
474
500
|
export const map: {
|
|
475
501
|
<A, B>(f: (a: A) => B): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<B, E, R, I>
|
|
476
502
|
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, f: (a: A) => B): Parser<B, E, R, I>
|
|
477
|
-
} = dual(
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
const
|
|
481
|
-
return
|
|
482
|
-
|
|
483
|
-
|
|
503
|
+
} = /*#__PURE__*/ dual(
|
|
504
|
+
2,
|
|
505
|
+
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, f: (a: A) => B): Parser<B, E, R, I> => {
|
|
506
|
+
const step = self.step
|
|
507
|
+
return described(
|
|
508
|
+
(state) => {
|
|
509
|
+
const a = step(state)
|
|
510
|
+
return a === Fail ? Fail : f(a)
|
|
511
|
+
},
|
|
512
|
+
self.name,
|
|
513
|
+
{ _tag: "Map", self, f }
|
|
514
|
+
)
|
|
515
|
+
}
|
|
516
|
+
)
|
|
484
517
|
|
|
485
518
|
/**
|
|
486
519
|
* Builds an object from the `[key, value]` entries a parser returns, as
|
|
@@ -518,9 +551,9 @@ export const fromEntries = <K extends PropertyKey, V, E, R, I extends Input>(
|
|
|
518
551
|
export const as: {
|
|
519
552
|
<B>(value: B): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<B, E, R, I>
|
|
520
553
|
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, value: B): Parser<B, E, R, I>
|
|
521
|
-
} = dual(2, <A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, value: B): Parser<B, E, R, I> => {
|
|
554
|
+
} = /*#__PURE__*/ dual(2, <A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, value: B): Parser<B, E, R, I> => {
|
|
522
555
|
const step = self.step
|
|
523
|
-
return described((state) => step(state) === Fail ? Fail : value, self.name, { _tag: "As", self, value })
|
|
556
|
+
return described((state) => (step(state) === Fail ? Fail : value), self.name, { _tag: "As", self, value })
|
|
524
557
|
})
|
|
525
558
|
|
|
526
559
|
/**
|
|
@@ -529,8 +562,7 @@ export const as: {
|
|
|
529
562
|
* @since 0.1.0
|
|
530
563
|
* @category mapping
|
|
531
564
|
*/
|
|
532
|
-
export const asVoid = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<void, E, R, I> =>
|
|
533
|
-
as(self, undefined)
|
|
565
|
+
export const asVoid = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<void, E, R, I> => as(self, undefined)
|
|
534
566
|
|
|
535
567
|
/**
|
|
536
568
|
* Replaces the output of a parser with `Option.some(output)`.
|
|
@@ -550,14 +582,21 @@ export const asSome = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Pars
|
|
|
550
582
|
export const tap: {
|
|
551
583
|
<A>(f: (a: A) => void): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
552
584
|
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, f: (a: A) => void): Parser<A, E, R, I>
|
|
553
|
-
} = dual(
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
585
|
+
} = /*#__PURE__*/ dual(
|
|
586
|
+
2,
|
|
587
|
+
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, f: (a: A) => void): Parser<A, E, R, I> => {
|
|
588
|
+
const step = self.step
|
|
589
|
+
return described(
|
|
590
|
+
(state) => {
|
|
591
|
+
const a = step(state)
|
|
592
|
+
if (a !== Fail) f(a)
|
|
593
|
+
return a
|
|
594
|
+
},
|
|
595
|
+
self.name,
|
|
596
|
+
{ _tag: "Tap", self, f }
|
|
597
|
+
)
|
|
598
|
+
}
|
|
599
|
+
)
|
|
561
600
|
|
|
562
601
|
/**
|
|
563
602
|
* Uses the output of a parser to choose the parser that consumes the rest
|
|
@@ -574,16 +613,23 @@ export const flatMap: {
|
|
|
574
613
|
self: Parser<A, E, R, I>,
|
|
575
614
|
f: (a: A) => Parser<B, E2, R2, I2>
|
|
576
615
|
): Parser<B, E | E2, R | R2, I & I2>
|
|
577
|
-
} = dual(
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
const
|
|
584
|
-
return
|
|
585
|
-
|
|
586
|
-
|
|
616
|
+
} = /*#__PURE__*/ dual(
|
|
617
|
+
2,
|
|
618
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
619
|
+
self: Parser<A, E, R, I>,
|
|
620
|
+
f: (a: A) => Parser<B, E2, R2, I2>
|
|
621
|
+
): Parser<B, E | E2, R | R2, I & I2> => {
|
|
622
|
+
const step = self.step
|
|
623
|
+
return described(
|
|
624
|
+
(state) => {
|
|
625
|
+
const a = step(state)
|
|
626
|
+
return a === Fail ? Fail : f(a).step(state)
|
|
627
|
+
},
|
|
628
|
+
undefined,
|
|
629
|
+
{ _tag: "FlatMap", self, f }
|
|
630
|
+
)
|
|
631
|
+
}
|
|
632
|
+
)
|
|
587
633
|
|
|
588
634
|
/**
|
|
589
635
|
* Applies a second parser to the *output* of the first (winnow's
|
|
@@ -613,34 +659,37 @@ export const mapParser: {
|
|
|
613
659
|
self: Parser<A, E, R, I>,
|
|
614
660
|
inner: Parser<B, E2, R2, A>
|
|
615
661
|
): Parser<B, E | E2, R | R2, I>
|
|
616
|
-
} = dual(
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
const
|
|
632
|
-
if (
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
662
|
+
} = /*#__PURE__*/ dual(
|
|
663
|
+
2,
|
|
664
|
+
<A extends Input, E, R, I extends Input, B, E2, R2>(
|
|
665
|
+
self: Parser<A, E, R, I>,
|
|
666
|
+
inner: Parser<B, E2, R2, A>
|
|
667
|
+
): Parser<B, E | E2, R | R2, I> => {
|
|
668
|
+
const step = self.step
|
|
669
|
+
return make((state) => {
|
|
670
|
+
const start = state.pos
|
|
671
|
+
const a = step(state)
|
|
672
|
+
if (a === Fail) return Fail
|
|
673
|
+
const sub = new State(a, { context: state.context })
|
|
674
|
+
sub.tracer = state.tracer
|
|
675
|
+
sub.depth = state.depth
|
|
676
|
+
sub.recovered = state.recovered
|
|
677
|
+
const b = inner.step(sub)
|
|
678
|
+
if (b === Fail) {
|
|
679
|
+
const f = sub.failure
|
|
680
|
+
if (sub.encoding !== undefined) state.encoding = sub.encoding
|
|
681
|
+
// The inner input is usually a slice ending where the outer parser stopped
|
|
682
|
+
const base = Math.max(start, state.pos - a.length)
|
|
683
|
+
const offset = Math.min(base + f.offset, state.pos)
|
|
684
|
+
return state.failWith(
|
|
685
|
+
sub.mode === "Incomplete" ? "Backtrack" : sub.mode,
|
|
686
|
+
new Failure(offset, f.kind, f.expected, f.context, f.hasCause, f.cause, f.message, 0)
|
|
687
|
+
)
|
|
688
|
+
}
|
|
689
|
+
return b
|
|
690
|
+
})
|
|
691
|
+
}
|
|
692
|
+
)
|
|
644
693
|
|
|
645
694
|
/**
|
|
646
695
|
* Transforms the output of a parser with a function that may fail with a
|
|
@@ -659,21 +708,28 @@ export const tryMap: {
|
|
|
659
708
|
self: Parser<A, E, R, I>,
|
|
660
709
|
f: (a: A) => Result.Result<B, E2>
|
|
661
710
|
): Parser<B, E | E2, R, I>
|
|
662
|
-
} = dual(
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
const
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
711
|
+
} = /*#__PURE__*/ dual(
|
|
712
|
+
2,
|
|
713
|
+
<A, E, R, I extends Input, B, E2>(
|
|
714
|
+
self: Parser<A, E, R, I>,
|
|
715
|
+
f: (a: A) => Result.Result<B, E2>
|
|
716
|
+
): Parser<B, E | E2, R, I> => {
|
|
717
|
+
const step = self.step
|
|
718
|
+
return described(
|
|
719
|
+
(state) => {
|
|
720
|
+
const start = state.pos
|
|
721
|
+
const a = step(state)
|
|
722
|
+
if (a === Fail) return Fail
|
|
723
|
+
const r = f(a)
|
|
724
|
+
if (Result.isSuccess(r)) return r.success
|
|
725
|
+
state.pos = start
|
|
726
|
+
return state.failCause("Backtrack", "Verify", r.failure)
|
|
727
|
+
},
|
|
728
|
+
self.name,
|
|
729
|
+
{ _tag: "TryMap", self, f }
|
|
730
|
+
)
|
|
731
|
+
}
|
|
732
|
+
)
|
|
677
733
|
|
|
678
734
|
/**
|
|
679
735
|
* Like {@link tryMap}, but the function may throw. Thrown values become the
|
|
@@ -685,14 +741,18 @@ export const tryMap: {
|
|
|
685
741
|
export const tryMapUnknown: {
|
|
686
742
|
<A, B>(f: (a: A) => B): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<B, E | unknown, R, I>
|
|
687
743
|
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, f: (a: A) => B): Parser<B, E | unknown, R, I>
|
|
688
|
-
} = dual(
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
744
|
+
} = /*#__PURE__*/ dual(
|
|
745
|
+
2,
|
|
746
|
+
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, f: (a: A) => B): Parser<B, unknown, R, I> =>
|
|
747
|
+
tryMap(self, (a) => {
|
|
748
|
+
try {
|
|
749
|
+
return Result.succeed(f(a))
|
|
750
|
+
} catch (e) {
|
|
751
|
+
if (Stack.isStackOverflow(e)) throw e
|
|
752
|
+
return Result.fail(e)
|
|
753
|
+
}
|
|
754
|
+
})
|
|
755
|
+
)
|
|
696
756
|
|
|
697
757
|
/**
|
|
698
758
|
* Transforms the output of a parser with a function returning an `Option`;
|
|
@@ -705,21 +765,25 @@ export const tryMapUnknown: {
|
|
|
705
765
|
export const filterMap: {
|
|
706
766
|
<A, B>(f: (a: A) => Option.Option<B>): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<B, E, R, I>
|
|
707
767
|
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, f: (a: A) => Option.Option<B>): Parser<B, E, R, I>
|
|
708
|
-
} = dual(
|
|
709
|
-
|
|
710
|
-
f: (a: A) => Option.Option<B>
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
768
|
+
} = /*#__PURE__*/ dual(
|
|
769
|
+
2,
|
|
770
|
+
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, f: (a: A) => Option.Option<B>): Parser<B, E, R, I> => {
|
|
771
|
+
const step = self.step
|
|
772
|
+
return described(
|
|
773
|
+
(state) => {
|
|
774
|
+
const start = state.pos
|
|
775
|
+
const a = step(state)
|
|
776
|
+
if (a === Fail) return Fail
|
|
777
|
+
const o = f(a)
|
|
778
|
+
if (Option.isSome(o)) return o.value
|
|
779
|
+
state.pos = start
|
|
780
|
+
return state.backtrack("Verify")
|
|
781
|
+
},
|
|
782
|
+
self.name,
|
|
783
|
+
{ _tag: "FilterMap", self, f }
|
|
784
|
+
)
|
|
785
|
+
}
|
|
786
|
+
)
|
|
723
787
|
|
|
724
788
|
/**
|
|
725
789
|
* Keeps the output of a parser only if it satisfies a predicate, otherwise
|
|
@@ -735,16 +799,20 @@ export const filter: {
|
|
|
735
799
|
<A>(predicate: (a: NoInfer<A>) => boolean): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
736
800
|
<A, E, R, I extends Input, B extends A>(self: Parser<A, E, R, I>, refinement: (a: A) => a is B): Parser<B, E, R, I>
|
|
737
801
|
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, predicate: (a: A) => boolean): Parser<A, E, R, I>
|
|
738
|
-
} = dual(2, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, predicate: (a: A) => boolean) => {
|
|
802
|
+
} = /*#__PURE__*/ dual(2, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, predicate: (a: A) => boolean) => {
|
|
739
803
|
const step = self.step
|
|
740
|
-
return described<A, E, R, I>(
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
804
|
+
return described<A, E, R, I>(
|
|
805
|
+
(state) => {
|
|
806
|
+
const start = state.pos
|
|
807
|
+
const a = step(state)
|
|
808
|
+
if (a === Fail) return Fail
|
|
809
|
+
if (predicate(a)) return a
|
|
810
|
+
state.pos = start
|
|
811
|
+
return state.backtrack("Verify")
|
|
812
|
+
},
|
|
813
|
+
self.name,
|
|
814
|
+
{ _tag: "Filter", self, predicate }
|
|
815
|
+
)
|
|
748
816
|
})
|
|
749
817
|
|
|
750
818
|
/**
|
|
@@ -773,21 +841,24 @@ export const filterOrFail: {
|
|
|
773
841
|
predicate: (a: A) => boolean,
|
|
774
842
|
orFailWith: (a: A) => E2
|
|
775
843
|
): Parser<A, E | E2, R, I>
|
|
776
|
-
} = dual(
|
|
777
|
-
|
|
778
|
-
predicate: (a: A) => boolean,
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
}
|
|
844
|
+
} = /*#__PURE__*/ dual(
|
|
845
|
+
3,
|
|
846
|
+
<A, E, R, I extends Input, E2>(self: Parser<A, E, R, I>, predicate: (a: A) => boolean, orFailWith: (a: A) => E2) => {
|
|
847
|
+
const step = self.step
|
|
848
|
+
return described<A, E | E2, R, I>(
|
|
849
|
+
(state) => {
|
|
850
|
+
const start = state.pos
|
|
851
|
+
const a = step(state)
|
|
852
|
+
if (a === Fail) return Fail
|
|
853
|
+
if (predicate(a)) return a
|
|
854
|
+
state.pos = start
|
|
855
|
+
return state.failCause("Backtrack", "Verify", orFailWith(a))
|
|
856
|
+
},
|
|
857
|
+
self.name,
|
|
858
|
+
{ _tag: "Filter", self, predicate }
|
|
859
|
+
)
|
|
860
|
+
}
|
|
861
|
+
)
|
|
791
862
|
|
|
792
863
|
// -----------------------------------------------------------------------------
|
|
793
864
|
// Consumed input
|
|
@@ -802,10 +873,14 @@ export const filterOrFail: {
|
|
|
802
873
|
*/
|
|
803
874
|
export const taken = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<Slice<I>, E, R, I> => {
|
|
804
875
|
const step = self.step
|
|
805
|
-
return described(
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
876
|
+
return described(
|
|
877
|
+
(state) => {
|
|
878
|
+
const start = state.pos
|
|
879
|
+
return step(state) === Fail ? Fail : state.slice(start, state.pos)
|
|
880
|
+
},
|
|
881
|
+
self.name,
|
|
882
|
+
{ _tag: "Taken", self, encoding: undefined }
|
|
883
|
+
)
|
|
809
884
|
}
|
|
810
885
|
|
|
811
886
|
/**
|
|
@@ -819,11 +894,15 @@ export const withTaken = <A, E, R, I extends Input>(
|
|
|
819
894
|
self: Parser<A, E, R, I>
|
|
820
895
|
): Parser<[output: A, taken: Slice<I>], E, R, I> => {
|
|
821
896
|
const step = self.step
|
|
822
|
-
return described(
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
897
|
+
return described(
|
|
898
|
+
(state) => {
|
|
899
|
+
const start = state.pos
|
|
900
|
+
const a = step(state)
|
|
901
|
+
return a === Fail ? Fail : [a, state.slice(start, state.pos)]
|
|
902
|
+
},
|
|
903
|
+
self.name,
|
|
904
|
+
{ _tag: "WithTaken", self }
|
|
905
|
+
)
|
|
827
906
|
}
|
|
828
907
|
|
|
829
908
|
/**
|
|
@@ -835,10 +914,14 @@ export const withTaken = <A, E, R, I extends Input>(
|
|
|
835
914
|
*/
|
|
836
915
|
export const span = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<Span, E, R, I> => {
|
|
837
916
|
const step = self.step
|
|
838
|
-
return described(
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
917
|
+
return described(
|
|
918
|
+
(state) => {
|
|
919
|
+
const start = state.pos
|
|
920
|
+
return step(state) === Fail ? Fail : { start, end: state.pos }
|
|
921
|
+
},
|
|
922
|
+
self.name,
|
|
923
|
+
{ _tag: "Span", self }
|
|
924
|
+
)
|
|
842
925
|
}
|
|
843
926
|
|
|
844
927
|
/**
|
|
@@ -848,13 +931,19 @@ export const span = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser
|
|
|
848
931
|
* @since 0.1.0
|
|
849
932
|
* @category consumed input
|
|
850
933
|
*/
|
|
851
|
-
export const withSpan = <A, E, R, I extends Input>(
|
|
934
|
+
export const withSpan = <A, E, R, I extends Input>(
|
|
935
|
+
self: Parser<A, E, R, I>
|
|
936
|
+
): Parser<[output: A, span: Span], E, R, I> => {
|
|
852
937
|
const step = self.step
|
|
853
|
-
return described(
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
938
|
+
return described(
|
|
939
|
+
(state) => {
|
|
940
|
+
const start = state.pos
|
|
941
|
+
const a = step(state)
|
|
942
|
+
return a === Fail ? Fail : [a, { start, end: state.pos }]
|
|
943
|
+
},
|
|
944
|
+
self.name,
|
|
945
|
+
{ _tag: "WithSpan", self }
|
|
946
|
+
)
|
|
858
947
|
}
|
|
859
948
|
|
|
860
949
|
// -----------------------------------------------------------------------------
|
|
@@ -867,11 +956,15 @@ const changeMode = <A, E, R, I extends Input>(
|
|
|
867
956
|
to: ErrMode
|
|
868
957
|
): Parser<A, E, R, I> => {
|
|
869
958
|
const step = self.step
|
|
870
|
-
return described(
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
959
|
+
return described(
|
|
960
|
+
(state) => {
|
|
961
|
+
const a = step(state)
|
|
962
|
+
if (a === Fail && state.mode === from) state.mode = to
|
|
963
|
+
return a
|
|
964
|
+
},
|
|
965
|
+
self.name,
|
|
966
|
+
{ _tag: "Mode", self, from, to }
|
|
967
|
+
)
|
|
875
968
|
}
|
|
876
969
|
|
|
877
970
|
/**
|
|
@@ -890,8 +983,29 @@ const changeMode = <A, E, R, I extends Input>(
|
|
|
890
983
|
* @since 0.1.0
|
|
891
984
|
* @category error management
|
|
892
985
|
*/
|
|
893
|
-
export const cut = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> =>
|
|
894
|
-
|
|
986
|
+
export const cut = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> => {
|
|
987
|
+
const step = self.step
|
|
988
|
+
return described(
|
|
989
|
+
(state) => {
|
|
990
|
+
// A committed failure is reported where it happened (winnow's
|
|
991
|
+
// `cut_err`): only failures recorded inside `self` can outrank it as the
|
|
992
|
+
// furthest failure, not ones from abandoned branches or lookaheads before
|
|
993
|
+
// the commit.
|
|
994
|
+
const deepest = state.deepest
|
|
995
|
+
state.deepest = undefined
|
|
996
|
+
const a = step(state)
|
|
997
|
+
if (a === Fail && state.mode !== "Incomplete") {
|
|
998
|
+
state.mode = "Cut"
|
|
999
|
+
return a
|
|
1000
|
+
}
|
|
1001
|
+
const inner = state.deepest as Failure | undefined
|
|
1002
|
+
if (deepest !== undefined && (inner === undefined || deepest.offset > inner.offset)) state.deepest = deepest
|
|
1003
|
+
return a
|
|
1004
|
+
},
|
|
1005
|
+
self.name,
|
|
1006
|
+
{ _tag: "Mode", self, from: "Backtrack", to: "Cut" }
|
|
1007
|
+
)
|
|
1008
|
+
}
|
|
895
1009
|
|
|
896
1010
|
/**
|
|
897
1011
|
* Turns unrecoverable failures back into recoverable ones (winnow's
|
|
@@ -912,15 +1026,19 @@ export const backtrack = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): P
|
|
|
912
1026
|
*/
|
|
913
1027
|
export const complete = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> => {
|
|
914
1028
|
const step = self.step
|
|
915
|
-
return described(
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
state.
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1029
|
+
return described(
|
|
1030
|
+
(state) => {
|
|
1031
|
+
const start = state.pos
|
|
1032
|
+
const a = step(state)
|
|
1033
|
+
if (a === Fail && state.mode === "Incomplete") {
|
|
1034
|
+
state.pos = start
|
|
1035
|
+
return state.backtrack("Complete")
|
|
1036
|
+
}
|
|
1037
|
+
return a
|
|
1038
|
+
},
|
|
1039
|
+
self.name,
|
|
1040
|
+
{ _tag: "Mode", self, from: "Incomplete", to: "Backtrack" }
|
|
1041
|
+
)
|
|
924
1042
|
}
|
|
925
1043
|
|
|
926
1044
|
/**
|
|
@@ -934,25 +1052,22 @@ export const complete = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Pa
|
|
|
934
1052
|
export const context: {
|
|
935
1053
|
(label: string): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
936
1054
|
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, label: string): Parser<A, E, R, I>
|
|
937
|
-
} = dual(2, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, label: string): Parser<A, E, R, I> => {
|
|
1055
|
+
} = /*#__PURE__*/ dual(2, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, label: string): Parser<A, E, R, I> => {
|
|
938
1056
|
const step = self.step
|
|
939
|
-
return described(
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
}
|
|
954
|
-
return a
|
|
955
|
-
}, self.name ?? label, { _tag: "Context", self, label })
|
|
1057
|
+
return described(
|
|
1058
|
+
(state) => {
|
|
1059
|
+
const a = step(state)
|
|
1060
|
+
if (a === Fail && state.mode !== "Incomplete") {
|
|
1061
|
+
const f = state.failure
|
|
1062
|
+
state.replaceFailure(
|
|
1063
|
+
new Failure(f.offset, f.kind, f.expected, [...f.context, label], f.hasCause, f.cause, f.message, f.needed)
|
|
1064
|
+
)
|
|
1065
|
+
}
|
|
1066
|
+
return a
|
|
1067
|
+
},
|
|
1068
|
+
self.name ?? label,
|
|
1069
|
+
{ _tag: "Context", self, label }
|
|
1070
|
+
)
|
|
956
1071
|
})
|
|
957
1072
|
|
|
958
1073
|
/**
|
|
@@ -967,22 +1082,31 @@ export const context: {
|
|
|
967
1082
|
export const expected: {
|
|
968
1083
|
(description: string): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
969
1084
|
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, description: string): Parser<A, E, R, I>
|
|
970
|
-
} = dual(
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
const
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1085
|
+
} = /*#__PURE__*/ dual(
|
|
1086
|
+
2,
|
|
1087
|
+
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, description: string): Parser<A, E, R, I> => {
|
|
1088
|
+
const step = self.step
|
|
1089
|
+
const desc = [description]
|
|
1090
|
+
return described(
|
|
1091
|
+
(state) => {
|
|
1092
|
+
const start = state.pos
|
|
1093
|
+
const hintOffset = state.hintOffset
|
|
1094
|
+
const hintExpected = state.hintExpected
|
|
1095
|
+
const a = step(state)
|
|
1096
|
+
if (a === Fail && state.failure.offset === start) {
|
|
1097
|
+
const f = state.failure
|
|
1098
|
+
const expected = hintOffset === start ? mergeExpected(hintExpected, desc) : desc
|
|
1099
|
+
state.replaceFailure(
|
|
1100
|
+
new Failure(f.offset, f.kind, expected, f.context, f.hasCause, f.cause, f.message, f.needed)
|
|
1101
|
+
)
|
|
1102
|
+
}
|
|
1103
|
+
return a
|
|
1104
|
+
},
|
|
1105
|
+
description,
|
|
1106
|
+
{ _tag: "Expected", self, description }
|
|
1107
|
+
)
|
|
1108
|
+
}
|
|
1109
|
+
)
|
|
986
1110
|
|
|
987
1111
|
/**
|
|
988
1112
|
* Transforms the user error (cause) of a parser's failures.
|
|
@@ -993,17 +1117,26 @@ export const expected: {
|
|
|
993
1117
|
export const mapError: {
|
|
994
1118
|
<E, E2>(f: (e: E) => E2): <A, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E2, R, I>
|
|
995
1119
|
<A, E, R, I extends Input, E2>(self: Parser<A, E, R, I>, f: (e: E) => E2): Parser<A, E2, R, I>
|
|
996
|
-
} = dual(
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
const
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1120
|
+
} = /*#__PURE__*/ dual(
|
|
1121
|
+
2,
|
|
1122
|
+
<A, E, R, I extends Input, E2>(self: Parser<A, E, R, I>, f: (e: E) => E2): Parser<A, E2, R, I> => {
|
|
1123
|
+
const step = self.step
|
|
1124
|
+
return described(
|
|
1125
|
+
(state) => {
|
|
1126
|
+
const a = step(state)
|
|
1127
|
+
if (a === Fail && state.failure.hasCause) {
|
|
1128
|
+
const x = state.failure
|
|
1129
|
+
state.replaceFailure(
|
|
1130
|
+
new Failure(x.offset, x.kind, x.expected, x.context, true, f(x.cause as E), x.message, x.needed)
|
|
1131
|
+
)
|
|
1132
|
+
}
|
|
1133
|
+
return a
|
|
1134
|
+
},
|
|
1135
|
+
self.name,
|
|
1136
|
+
{ _tag: "MapError", self }
|
|
1137
|
+
)
|
|
1138
|
+
}
|
|
1139
|
+
)
|
|
1007
1140
|
|
|
1008
1141
|
/**
|
|
1009
1142
|
* Replaces any failure of a parser with the given user error, keeping the
|
|
@@ -1015,18 +1148,25 @@ export const mapError: {
|
|
|
1015
1148
|
export const orFail: {
|
|
1016
1149
|
<E2>(error: () => E2): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E2, R, I>
|
|
1017
1150
|
<A, E, R, I extends Input, E2>(self: Parser<A, E, R, I>, error: () => E2): Parser<A, E2, R, I>
|
|
1018
|
-
} = dual(
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
const
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
}
|
|
1151
|
+
} = /*#__PURE__*/ dual(
|
|
1152
|
+
2,
|
|
1153
|
+
<A, E, R, I extends Input, E2>(self: Parser<A, E, R, I>, error: () => E2): Parser<A, E2, R, I> => {
|
|
1154
|
+
const step = self.step
|
|
1155
|
+
return described(
|
|
1156
|
+
(state) => {
|
|
1157
|
+
const start = state.pos
|
|
1158
|
+
const a = step(state)
|
|
1159
|
+
if (a === Fail && state.mode !== "Incomplete") {
|
|
1160
|
+
const x = state.failure
|
|
1161
|
+
state.replaceFailure(new Failure(start, x.kind, [], x.context, true, error(), undefined, 0))
|
|
1162
|
+
}
|
|
1163
|
+
return a
|
|
1164
|
+
},
|
|
1165
|
+
self.name,
|
|
1166
|
+
{ _tag: "OrFail", self }
|
|
1167
|
+
)
|
|
1168
|
+
}
|
|
1169
|
+
)
|
|
1030
1170
|
|
|
1031
1171
|
/**
|
|
1032
1172
|
* If the parser fails recoverably, tries `that` from the same position.
|
|
@@ -1043,10 +1183,13 @@ export const orElse: {
|
|
|
1043
1183
|
self: Parser<A, E, R, I>,
|
|
1044
1184
|
that: () => Parser<B, E2, R2, I2>
|
|
1045
1185
|
): Parser<A | B, E | E2, R | R2, I & I2>
|
|
1046
|
-
} = dual(
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1186
|
+
} = /*#__PURE__*/ dual(
|
|
1187
|
+
2,
|
|
1188
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
1189
|
+
self: Parser<A, E, R, I>,
|
|
1190
|
+
that: () => Parser<B, E2, R2, I2>
|
|
1191
|
+
): Parser<A | B, E | E2, R | R2, I & I2> => alt(self, suspend(that))
|
|
1192
|
+
)
|
|
1050
1193
|
|
|
1051
1194
|
/**
|
|
1052
1195
|
* If the parser fails recoverably, succeeds with the given value without
|
|
@@ -1058,17 +1201,24 @@ export const orElse: {
|
|
|
1058
1201
|
export const orElseSucceed: {
|
|
1059
1202
|
<B>(value: () => B): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A | B, E, R, I>
|
|
1060
1203
|
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, value: () => B): Parser<A | B, E, R, I>
|
|
1061
|
-
} = dual(
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
const
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1204
|
+
} = /*#__PURE__*/ dual(
|
|
1205
|
+
2,
|
|
1206
|
+
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, value: () => B): Parser<A | B, E, R, I> => {
|
|
1207
|
+
const step = self.step
|
|
1208
|
+
return described(
|
|
1209
|
+
(state) => {
|
|
1210
|
+
const start = state.pos
|
|
1211
|
+
const a = step(state)
|
|
1212
|
+
if (a !== Fail) return a
|
|
1213
|
+
if (state.mode !== "Backtrack") return Fail
|
|
1214
|
+
recover(state, start)
|
|
1215
|
+
return value()
|
|
1216
|
+
},
|
|
1217
|
+
self.name,
|
|
1218
|
+
{ _tag: "OrElseSucceed", self, value }
|
|
1219
|
+
)
|
|
1220
|
+
}
|
|
1221
|
+
)
|
|
1072
1222
|
|
|
1073
1223
|
/** Rewinds after a recoverable failure, remembering it as a hint. */
|
|
1074
1224
|
const recover = (state: State<any>, start: number): void => {
|
|
@@ -1093,14 +1243,18 @@ const recover = (state: State<any>, start: number): void => {
|
|
|
1093
1243
|
*/
|
|
1094
1244
|
export const opt = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<Option.Option<A>, E, R, I> => {
|
|
1095
1245
|
const step = self.step
|
|
1096
|
-
return described(
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1246
|
+
return described(
|
|
1247
|
+
(state) => {
|
|
1248
|
+
const start = state.pos
|
|
1249
|
+
const a = step(state)
|
|
1250
|
+
if (a !== Fail) return Option.some(a)
|
|
1251
|
+
if (state.mode !== "Backtrack") return Fail
|
|
1252
|
+
recover(state, start)
|
|
1253
|
+
return Option.none()
|
|
1254
|
+
},
|
|
1255
|
+
self.name,
|
|
1256
|
+
{ _tag: "Opt", self }
|
|
1257
|
+
)
|
|
1104
1258
|
}
|
|
1105
1259
|
|
|
1106
1260
|
/**
|
|
@@ -1122,7 +1276,7 @@ export const optional = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Pa
|
|
|
1122
1276
|
export const cond = <A, E, R, I extends Input>(
|
|
1123
1277
|
condition: boolean,
|
|
1124
1278
|
self: Parser<A, E, R, I>
|
|
1125
|
-
): Parser<Option.Option<A>, E, R, I> => condition ? asSome(self) : succeed(Option.none())
|
|
1279
|
+
): Parser<Option.Option<A>, E, R, I> => (condition ? asSome(self) : succeed(Option.none()))
|
|
1126
1280
|
|
|
1127
1281
|
/**
|
|
1128
1282
|
* Runs a parser without consuming input (winnow's and nom's `peek`).
|
|
@@ -1132,18 +1286,26 @@ export const cond = <A, E, R, I extends Input>(
|
|
|
1132
1286
|
*/
|
|
1133
1287
|
export const peek = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> => {
|
|
1134
1288
|
const step = self.step
|
|
1135
|
-
return described(
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1289
|
+
return described(
|
|
1290
|
+
(state) => {
|
|
1291
|
+
const start = state.pos
|
|
1292
|
+
const hintOffset = state.hintOffset
|
|
1293
|
+
const hintExpected = state.hintExpected
|
|
1294
|
+
const deepest = state.deepest
|
|
1295
|
+
const a = step(state)
|
|
1296
|
+
if (a !== Fail) {
|
|
1297
|
+
// Failures inside a lookahead that succeeded are about input that was
|
|
1298
|
+
// never consumed, so they are not reported as the furthest failure
|
|
1299
|
+
state.pos = start
|
|
1300
|
+
state.hintOffset = hintOffset
|
|
1301
|
+
state.hintExpected = hintExpected
|
|
1302
|
+
state.deepest = deepest
|
|
1303
|
+
}
|
|
1304
|
+
return a
|
|
1305
|
+
},
|
|
1306
|
+
self.name,
|
|
1307
|
+
{ _tag: "Peek", self }
|
|
1308
|
+
)
|
|
1147
1309
|
}
|
|
1148
1310
|
|
|
1149
1311
|
/**
|
|
@@ -1155,21 +1317,29 @@ export const peek = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser
|
|
|
1155
1317
|
*/
|
|
1156
1318
|
export const not = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<void, E, R, I> => {
|
|
1157
1319
|
const step = self.step
|
|
1158
|
-
return described(
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1320
|
+
return described(
|
|
1321
|
+
(state) => {
|
|
1322
|
+
const start = state.pos
|
|
1323
|
+
const hintOffset = state.hintOffset
|
|
1324
|
+
const hintExpected = state.hintExpected
|
|
1325
|
+
const deepest = state.deepest
|
|
1326
|
+
const a = step(state)
|
|
1327
|
+
if (a !== Fail) {
|
|
1328
|
+
// The failures inside `self` are not this parser's failure
|
|
1329
|
+
state.pos = start
|
|
1330
|
+
state.deepest = deepest
|
|
1331
|
+
return state.backtrack("Not")
|
|
1332
|
+
}
|
|
1333
|
+
if (state.mode !== "Backtrack") return Fail
|
|
1164
1334
|
state.pos = start
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1335
|
+
state.hintOffset = hintOffset
|
|
1336
|
+
state.hintExpected = hintExpected
|
|
1337
|
+
state.deepest = deepest
|
|
1338
|
+
return undefined
|
|
1339
|
+
},
|
|
1340
|
+
self.name,
|
|
1341
|
+
{ _tag: "Not", self }
|
|
1342
|
+
)
|
|
1173
1343
|
}
|
|
1174
1344
|
|
|
1175
1345
|
/**
|
|
@@ -1202,15 +1372,19 @@ export const seq = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1202
1372
|
> => {
|
|
1203
1373
|
const steps = parsers.map((p) => p.step)
|
|
1204
1374
|
const n = steps.length
|
|
1205
|
-
return described(
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1375
|
+
return described(
|
|
1376
|
+
(state: State<any>) => {
|
|
1377
|
+
const out = new Array(n)
|
|
1378
|
+
for (let i = 0; i < n; i++) {
|
|
1379
|
+
const a = steps[i](state)
|
|
1380
|
+
if (a === Fail) return Fail
|
|
1381
|
+
out[i] = a
|
|
1382
|
+
}
|
|
1383
|
+
return out as any
|
|
1384
|
+
},
|
|
1385
|
+
"seq",
|
|
1386
|
+
{ _tag: "Seq", parsers, output: "tuple" }
|
|
1387
|
+
)
|
|
1214
1388
|
}
|
|
1215
1389
|
|
|
1216
1390
|
/**
|
|
@@ -1230,17 +1404,21 @@ export const struct = <const Fields extends Readonly<Record<string, Parser.Any>>
|
|
|
1230
1404
|
Parser.InputOf<Fields[keyof Fields]>
|
|
1231
1405
|
> => {
|
|
1232
1406
|
const keys = Object.keys(fields)
|
|
1233
|
-
const steps = keys.map((k) => fields[k]
|
|
1407
|
+
const steps = keys.map((k) => fields[k].step)
|
|
1234
1408
|
const n = keys.length
|
|
1235
|
-
return described(
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1409
|
+
return described(
|
|
1410
|
+
(state: State<any>) => {
|
|
1411
|
+
const out: Record<string, unknown> = {}
|
|
1412
|
+
for (let i = 0; i < n; i++) {
|
|
1413
|
+
const a = steps[i](state)
|
|
1414
|
+
if (a === Fail) return Fail
|
|
1415
|
+
out[keys[i]] = a
|
|
1416
|
+
}
|
|
1417
|
+
return out as any
|
|
1418
|
+
},
|
|
1419
|
+
"struct",
|
|
1420
|
+
{ _tag: "Struct", keys, parsers: keys.map((k) => fields[k]) }
|
|
1421
|
+
)
|
|
1244
1422
|
}
|
|
1245
1423
|
|
|
1246
1424
|
/**
|
|
@@ -1257,10 +1435,13 @@ export const zip: {
|
|
|
1257
1435
|
self: Parser<A, E, R, I>,
|
|
1258
1436
|
that: Parser<B, E2, R2, I2>
|
|
1259
1437
|
): Parser<[A, B], E | E2, R | R2, I & I2>
|
|
1260
|
-
} = dual(
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1438
|
+
} = /*#__PURE__*/ dual(
|
|
1439
|
+
2,
|
|
1440
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
1441
|
+
self: Parser<A, E, R, I>,
|
|
1442
|
+
that: Parser<B, E2, R2, I2>
|
|
1443
|
+
): Parser<[A, B], E | E2, R | R2, I & I2> => zipWith(self, that, (a, b) => [a, b])
|
|
1444
|
+
)
|
|
1264
1445
|
|
|
1265
1446
|
/**
|
|
1266
1447
|
* Runs two parsers in sequence and combines their outputs.
|
|
@@ -1278,21 +1459,28 @@ export const zipWith: {
|
|
|
1278
1459
|
that: Parser<B, E2, R2, I2>,
|
|
1279
1460
|
f: (a: A, b: B) => C
|
|
1280
1461
|
): Parser<C, E | E2, R | R2, I & I2>
|
|
1281
|
-
} = dual(
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
const
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1462
|
+
} = /*#__PURE__*/ dual(
|
|
1463
|
+
3,
|
|
1464
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input, C>(
|
|
1465
|
+
self: Parser<A, E, R, I>,
|
|
1466
|
+
that: Parser<B, E2, R2, I2>,
|
|
1467
|
+
f: (a: A, b: B) => C
|
|
1468
|
+
): Parser<C, E | E2, R | R2, I & I2> => {
|
|
1469
|
+
const s1 = self.step
|
|
1470
|
+
const s2 = that.step
|
|
1471
|
+
return described(
|
|
1472
|
+
(state) => {
|
|
1473
|
+
const a = s1(state)
|
|
1474
|
+
if (a === Fail) return Fail
|
|
1475
|
+
const b = s2(state)
|
|
1476
|
+
if (b === Fail) return Fail
|
|
1477
|
+
return f(a, b)
|
|
1478
|
+
},
|
|
1479
|
+
undefined,
|
|
1480
|
+
{ _tag: "ZipWith", self, that, f }
|
|
1481
|
+
)
|
|
1482
|
+
}
|
|
1483
|
+
)
|
|
1296
1484
|
|
|
1297
1485
|
/**
|
|
1298
1486
|
* Runs two parsers in sequence, keeping the output of the first.
|
|
@@ -1308,10 +1496,13 @@ export const zipLeft: {
|
|
|
1308
1496
|
self: Parser<A, E, R, I>,
|
|
1309
1497
|
that: Parser<B, E2, R2, I2>
|
|
1310
1498
|
): Parser<A, E | E2, R | R2, I & I2>
|
|
1311
|
-
} = dual(
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1499
|
+
} = /*#__PURE__*/ dual(
|
|
1500
|
+
2,
|
|
1501
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
1502
|
+
self: Parser<A, E, R, I>,
|
|
1503
|
+
that: Parser<B, E2, R2, I2>
|
|
1504
|
+
): Parser<A, E | E2, R | R2, I & I2> => terminated(self, that)
|
|
1505
|
+
)
|
|
1315
1506
|
|
|
1316
1507
|
/**
|
|
1317
1508
|
* Runs two parsers in sequence, keeping the output of the second.
|
|
@@ -1327,10 +1518,13 @@ export const zipRight: {
|
|
|
1327
1518
|
self: Parser<A, E, R, I>,
|
|
1328
1519
|
that: Parser<B, E2, R2, I2>
|
|
1329
1520
|
): Parser<B, E | E2, R | R2, I & I2>
|
|
1330
|
-
} = dual(
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1521
|
+
} = /*#__PURE__*/ dual(
|
|
1522
|
+
2,
|
|
1523
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
1524
|
+
self: Parser<A, E, R, I>,
|
|
1525
|
+
that: Parser<B, E2, R2, I2>
|
|
1526
|
+
): Parser<B, E | E2, R | R2, I & I2> => preceded(self, that)
|
|
1527
|
+
)
|
|
1334
1528
|
|
|
1335
1529
|
/**
|
|
1336
1530
|
* Runs `prefix` then `parser`, keeping the output of `parser` (winnow's and
|
|
@@ -1345,7 +1539,7 @@ export const preceded = <A1, E1, R1, I1 extends Input, A2, E2, R2, I2 extends In
|
|
|
1345
1539
|
): Parser<A2, E1 | E2, R1 | R2, I1 & I2> => {
|
|
1346
1540
|
const s1 = prefix.step
|
|
1347
1541
|
const s2 = parser.step
|
|
1348
|
-
return described((state) => s1(state) === Fail ? Fail : s2(state), parser.name, {
|
|
1542
|
+
return described((state) => (s1(state) === Fail ? Fail : s2(state)), parser.name, {
|
|
1349
1543
|
_tag: "Seq",
|
|
1350
1544
|
parsers: [prefix, parser],
|
|
1351
1545
|
output: 1
|
|
@@ -1365,11 +1559,15 @@ export const terminated = <A1, E1, R1, I1 extends Input, A2, E2, R2, I2 extends
|
|
|
1365
1559
|
): Parser<A1, E1 | E2, R1 | R2, I1 & I2> => {
|
|
1366
1560
|
const s1 = parser.step
|
|
1367
1561
|
const s2 = suffix.step
|
|
1368
|
-
return described(
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1562
|
+
return described(
|
|
1563
|
+
(state) => {
|
|
1564
|
+
const a = s1(state)
|
|
1565
|
+
if (a === Fail) return Fail
|
|
1566
|
+
return s2(state) === Fail ? Fail : a
|
|
1567
|
+
},
|
|
1568
|
+
parser.name,
|
|
1569
|
+
{ _tag: "Seq", parsers: [parser, suffix], output: 0 }
|
|
1570
|
+
)
|
|
1373
1571
|
}
|
|
1374
1572
|
|
|
1375
1573
|
/**
|
|
@@ -1379,20 +1577,7 @@ export const terminated = <A1, E1, R1, I1 extends Input, A2, E2, R2, I2 extends
|
|
|
1379
1577
|
* @since 0.1.0
|
|
1380
1578
|
* @category sequencing
|
|
1381
1579
|
*/
|
|
1382
|
-
export const delimited = <
|
|
1383
|
-
A1,
|
|
1384
|
-
E1,
|
|
1385
|
-
R1,
|
|
1386
|
-
I1 extends Input,
|
|
1387
|
-
A2,
|
|
1388
|
-
E2,
|
|
1389
|
-
R2,
|
|
1390
|
-
I2 extends Input,
|
|
1391
|
-
A3,
|
|
1392
|
-
E3,
|
|
1393
|
-
R3,
|
|
1394
|
-
I3 extends Input
|
|
1395
|
-
>(
|
|
1580
|
+
export const delimited = <A1, E1, R1, I1 extends Input, A2, E2, R2, I2 extends Input, A3, E3, R3, I3 extends Input>(
|
|
1396
1581
|
open: Parser<A1, E1, R1, I1>,
|
|
1397
1582
|
parser: Parser<A2, E2, R2, I2>,
|
|
1398
1583
|
close: Parser<A3, E3, R3, I3>
|
|
@@ -1400,12 +1585,16 @@ export const delimited = <
|
|
|
1400
1585
|
const s1 = open.step
|
|
1401
1586
|
const s2 = parser.step
|
|
1402
1587
|
const s3 = close.step
|
|
1403
|
-
return described(
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1588
|
+
return described(
|
|
1589
|
+
(state) => {
|
|
1590
|
+
if (s1(state) === Fail) return Fail
|
|
1591
|
+
const a = s2(state)
|
|
1592
|
+
if (a === Fail) return Fail
|
|
1593
|
+
return s3(state) === Fail ? Fail : a
|
|
1594
|
+
},
|
|
1595
|
+
parser.name,
|
|
1596
|
+
{ _tag: "Seq", parsers: [open, parser, close], output: 1 }
|
|
1597
|
+
)
|
|
1409
1598
|
}
|
|
1410
1599
|
|
|
1411
1600
|
/**
|
|
@@ -1415,20 +1604,7 @@ export const delimited = <
|
|
|
1415
1604
|
* @since 0.1.0
|
|
1416
1605
|
* @category sequencing
|
|
1417
1606
|
*/
|
|
1418
|
-
export const separatedPair = <
|
|
1419
|
-
A1,
|
|
1420
|
-
E1,
|
|
1421
|
-
R1,
|
|
1422
|
-
I1 extends Input,
|
|
1423
|
-
A2,
|
|
1424
|
-
E2,
|
|
1425
|
-
R2,
|
|
1426
|
-
I2 extends Input,
|
|
1427
|
-
A3,
|
|
1428
|
-
E3,
|
|
1429
|
-
R3,
|
|
1430
|
-
I3 extends Input
|
|
1431
|
-
>(
|
|
1607
|
+
export const separatedPair = <A1, E1, R1, I1 extends Input, A2, E2, R2, I2 extends Input, A3, E3, R3, I3 extends Input>(
|
|
1432
1608
|
first: Parser<A1, E1, R1, I1>,
|
|
1433
1609
|
separator: Parser<A2, E2, R2, I2>,
|
|
1434
1610
|
second: Parser<A3, E3, R3, I3>
|
|
@@ -1436,13 +1612,17 @@ export const separatedPair = <
|
|
|
1436
1612
|
const s1 = first.step
|
|
1437
1613
|
const s2 = separator.step
|
|
1438
1614
|
const s3 = second.step
|
|
1439
|
-
return described(
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1615
|
+
return described(
|
|
1616
|
+
(state) => {
|
|
1617
|
+
const a = s1(state)
|
|
1618
|
+
if (a === Fail) return Fail
|
|
1619
|
+
if (s2(state) === Fail) return Fail
|
|
1620
|
+
const b = s3(state)
|
|
1621
|
+
return b === Fail ? Fail : [a, b]
|
|
1622
|
+
},
|
|
1623
|
+
undefined,
|
|
1624
|
+
{ _tag: "Seq", parsers: [first, separator, second], output: [0, 2] }
|
|
1625
|
+
)
|
|
1446
1626
|
}
|
|
1447
1627
|
|
|
1448
1628
|
/**
|
|
@@ -1461,6 +1641,23 @@ export const separatedPair = <
|
|
|
1461
1641
|
* })
|
|
1462
1642
|
* ```
|
|
1463
1643
|
*
|
|
1644
|
+
* The body runs on every parse, so parsers created inside it, like
|
|
1645
|
+
* `Token.literal("=")` above, are rebuilt on every run. On hot paths, build
|
|
1646
|
+
* them once outside the body:
|
|
1647
|
+
*
|
|
1648
|
+
* ```ts
|
|
1649
|
+
* import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
1650
|
+
*
|
|
1651
|
+
* const equals = Token.literal("=")
|
|
1652
|
+
*
|
|
1653
|
+
* const keyValue = Parser.gen(function*() {
|
|
1654
|
+
* const key = yield* Ascii.alpha1
|
|
1655
|
+
* yield* equals
|
|
1656
|
+
* const value = yield* Ascii.decInt
|
|
1657
|
+
* return [key, value] as const
|
|
1658
|
+
* })
|
|
1659
|
+
* ```
|
|
1660
|
+
*
|
|
1464
1661
|
* @since 0.1.0
|
|
1465
1662
|
* @category sequencing
|
|
1466
1663
|
*/
|
|
@@ -1498,7 +1695,7 @@ export const gen = <Eff extends Parser.Any, AEff>(
|
|
|
1498
1695
|
* @since 0.1.0
|
|
1499
1696
|
* @category do notation
|
|
1500
1697
|
*/
|
|
1501
|
-
export const Do: Parser<
|
|
1698
|
+
export const Do: Parser<Record<never, never>, never, never, Input> = /*#__PURE__*/ succeed({})
|
|
1502
1699
|
|
|
1503
1700
|
/**
|
|
1504
1701
|
* Binds the output of a parser to a field of the Do record.
|
|
@@ -1518,8 +1715,9 @@ export const bind: {
|
|
|
1518
1715
|
name: Exclude<N, keyof A>,
|
|
1519
1716
|
f: (a: NoInfer<A>) => Parser<B, E2, R2, I2>
|
|
1520
1717
|
): Parser<Simplify<Omit<A, N> & { [K in N]: B }>, E | E2, R | R2, I & I2>
|
|
1521
|
-
} = dual(3, (self: Parser.Any, name: string, f: (a: any) => Parser.Any): Parser.Any =>
|
|
1522
|
-
flatMap(self, (a) => map(f(a), (b) => ({ ...a, [name]: b })))
|
|
1718
|
+
} = /*#__PURE__*/ dual(3, (self: Parser.Any, name: string, f: (a: any) => Parser.Any): Parser.Any =>
|
|
1719
|
+
flatMap(self, (a) => map(f(a), (b) => ({ ...a, [name]: b })))
|
|
1720
|
+
)
|
|
1523
1721
|
|
|
1524
1722
|
/**
|
|
1525
1723
|
* Wraps the output of a parser in a record with a single field.
|
|
@@ -1530,7 +1728,7 @@ export const bind: {
|
|
|
1530
1728
|
export const bindTo: {
|
|
1531
1729
|
<N extends string>(name: N): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<{ [K in N]: A }, E, R, I>
|
|
1532
1730
|
<A, E, R, I extends Input, N extends string>(self: Parser<A, E, R, I>, name: N): Parser<{ [K in N]: A }, E, R, I>
|
|
1533
|
-
} = dual(2, (self: Parser.Any, name: string): Parser.Any => map(self, (a) => ({ [name]: a })))
|
|
1731
|
+
} = /*#__PURE__*/ dual(2, (self: Parser.Any, name: string): Parser.Any => map(self, (a) => ({ [name]: a })))
|
|
1534
1732
|
|
|
1535
1733
|
const let_: {
|
|
1536
1734
|
<N extends string, A extends object, B>(
|
|
@@ -1542,8 +1740,9 @@ const let_: {
|
|
|
1542
1740
|
name: Exclude<N, keyof A>,
|
|
1543
1741
|
f: (a: NoInfer<A>) => B
|
|
1544
1742
|
): Parser<Simplify<Omit<A, N> & { [K in N]: B }>, E, R, I>
|
|
1545
|
-
} = dual(3, (self: Parser.Any, name: string, f: (a: any) => unknown): Parser.Any =>
|
|
1546
|
-
map(self, (a) => ({ ...a, [name]: f(a) }))
|
|
1743
|
+
} = /*#__PURE__*/ dual(3, (self: Parser.Any, name: string, f: (a: any) => unknown): Parser.Any =>
|
|
1744
|
+
map(self, (a) => ({ ...a, [name]: f(a) }))
|
|
1745
|
+
)
|
|
1547
1746
|
|
|
1548
1747
|
export {
|
|
1549
1748
|
/**
|
|
@@ -1582,22 +1781,27 @@ export const alt = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1582
1781
|
const steps = parsers.map((p) => p.step)
|
|
1583
1782
|
const n = steps.length
|
|
1584
1783
|
if (n === 0) return reject as any
|
|
1585
|
-
if (n === 1) return parsers[0]
|
|
1586
|
-
return described(
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
if (
|
|
1593
|
-
|
|
1784
|
+
if (n === 1) return parsers[0]
|
|
1785
|
+
return described(
|
|
1786
|
+
(state: State<any>) => {
|
|
1787
|
+
const start = state.pos
|
|
1788
|
+
let failure: Failure | undefined
|
|
1789
|
+
for (let i = 0; i < n; i++) {
|
|
1790
|
+
const a = steps[i](state)
|
|
1791
|
+
if (a !== Fail) {
|
|
1792
|
+
if (failure !== undefined && failure.offset === state.pos) state.setHint(failure.offset, failure.expected)
|
|
1793
|
+
return a
|
|
1794
|
+
}
|
|
1795
|
+
if (state.mode !== "Backtrack") return Fail
|
|
1796
|
+
failure = failure === undefined ? state.failure : mergeFailures(failure, state.failure)
|
|
1797
|
+
state.pos = start
|
|
1594
1798
|
}
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1799
|
+
// `failure` is set: there are at least two alternatives, and each one that fails sets it
|
|
1800
|
+
return state.failWith("Backtrack", failure ?? state.failure)
|
|
1801
|
+
},
|
|
1802
|
+
"alt",
|
|
1803
|
+
{ _tag: "Alt", parsers }
|
|
1804
|
+
)
|
|
1601
1805
|
}
|
|
1602
1806
|
|
|
1603
1807
|
/**
|
|
@@ -1609,6 +1813,11 @@ export const alt = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1609
1813
|
* an optional `otherwise` parser for unlisted keys, like winnow's `_ =>`
|
|
1610
1814
|
* arm), or as a function returning a parser (or `undefined` for no match).
|
|
1611
1815
|
*
|
|
1816
|
+
* Prefer a record where the keys are known. Compiled code (see the
|
|
1817
|
+
* `Compiler` module) switches on the key and runs every case compiled; the
|
|
1818
|
+
* parser a function returns always runs interpreted, and one the function
|
|
1819
|
+
* builds (`(c) => Parser.cut(p)`) is rebuilt on every run.
|
|
1820
|
+
*
|
|
1612
1821
|
* @example
|
|
1613
1822
|
* ```ts
|
|
1614
1823
|
* import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
@@ -1656,26 +1865,31 @@ export const dispatch: {
|
|
|
1656
1865
|
cases: ((key: any) => Parser.Any | undefined) | Record<PropertyKey, Parser.Any>,
|
|
1657
1866
|
otherwise?: Parser.Any
|
|
1658
1867
|
) => {
|
|
1659
|
-
const choose =
|
|
1660
|
-
|
|
1868
|
+
const choose = Predicate.isFunction(cases)
|
|
1869
|
+
? cases
|
|
1870
|
+
: (key: PropertyKey) => (Object.prototype.hasOwnProperty.call(cases, key) ? cases[key] : otherwise)
|
|
1661
1871
|
const step = selector.step
|
|
1662
|
-
return described(
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1872
|
+
return described(
|
|
1873
|
+
(state: State<any>) => {
|
|
1874
|
+
const start = state.pos
|
|
1875
|
+
const key = step(state)
|
|
1876
|
+
if (key === Fail) return Fail
|
|
1877
|
+
const parser = choose(key)
|
|
1878
|
+
if (parser === undefined) {
|
|
1879
|
+
state.pos = start
|
|
1880
|
+
return state.backtrack("Dispatch")
|
|
1881
|
+
}
|
|
1882
|
+
return parser.step(state)
|
|
1883
|
+
},
|
|
1884
|
+
"dispatch",
|
|
1885
|
+
{
|
|
1886
|
+
_tag: "Dispatch",
|
|
1887
|
+
selector,
|
|
1888
|
+
cases: Predicate.isFunction(cases) ? undefined : cases,
|
|
1889
|
+
otherwise: Predicate.isFunction(cases) ? undefined : otherwise,
|
|
1890
|
+
choose
|
|
1670
1891
|
}
|
|
1671
|
-
|
|
1672
|
-
}, "dispatch", {
|
|
1673
|
-
_tag: "Dispatch",
|
|
1674
|
-
selector,
|
|
1675
|
-
cases: typeof cases === "function" ? undefined : cases,
|
|
1676
|
-
otherwise: typeof cases === "function" ? undefined : otherwise,
|
|
1677
|
-
choose
|
|
1678
|
-
})
|
|
1892
|
+
)
|
|
1679
1893
|
}
|
|
1680
1894
|
|
|
1681
1895
|
/**
|
|
@@ -1706,7 +1920,7 @@ export const permutation = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1706
1920
|
for (let i = 0; i < n; i++) {
|
|
1707
1921
|
if (done[i]) continue
|
|
1708
1922
|
const start = state.pos
|
|
1709
|
-
const a = steps[i]
|
|
1923
|
+
const a = steps[i](state)
|
|
1710
1924
|
if (a !== Fail) {
|
|
1711
1925
|
out[i] = a
|
|
1712
1926
|
done[i] = true
|
|
@@ -1718,7 +1932,8 @@ export const permutation = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1718
1932
|
failure = failure === undefined ? state.failure : mergeFailures(failure, state.failure)
|
|
1719
1933
|
state.pos = start
|
|
1720
1934
|
}
|
|
1721
|
-
|
|
1935
|
+
// `failure` is set: some parser is not done yet, and each one that fails sets it
|
|
1936
|
+
if (!matched) return state.failWith("Backtrack", failure ?? state.failure)
|
|
1722
1937
|
}
|
|
1723
1938
|
return out as any
|
|
1724
1939
|
}, "permutation")
|
|
@@ -1730,7 +1945,7 @@ export const permutation = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1730
1945
|
|
|
1731
1946
|
const normalizeRange = (range: Range | undefined): [min: number, max: number] => {
|
|
1732
1947
|
if (range === undefined) return [0, Infinity]
|
|
1733
|
-
if (
|
|
1948
|
+
if (Predicate.isNumber(range)) return [range, range]
|
|
1734
1949
|
const min = range.min ?? 0
|
|
1735
1950
|
const max = range.max ?? Infinity
|
|
1736
1951
|
if (min > max) throw new RangeError(`invalid range: min (${min}) > max (${max})`)
|
|
@@ -1757,44 +1972,50 @@ const foldImpl = <A, B, E, R, I extends Input>(
|
|
|
1757
1972
|
init: () => B,
|
|
1758
1973
|
f: (acc: B, a: A) => B,
|
|
1759
1974
|
name: string,
|
|
1760
|
-
node?: Node
|
|
1975
|
+
node?: Node,
|
|
1976
|
+
cond?: (acc: B) => boolean
|
|
1761
1977
|
): Parser<B, E, R, I> => {
|
|
1762
1978
|
const [min, max] = normalizeRange(range)
|
|
1763
1979
|
const step = self.step
|
|
1764
1980
|
const checkLoop = max === Infinity
|
|
1765
1981
|
const key = {}
|
|
1766
|
-
return described(
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1982
|
+
return described(
|
|
1983
|
+
(state) => {
|
|
1984
|
+
const entry = state.pos
|
|
1985
|
+
let acc: B
|
|
1986
|
+
let count = 0
|
|
1987
|
+
const resumed = state.resume === undefined ? undefined : (Resume.take(state, key, entry) as FoldCheckpoint<B>)
|
|
1988
|
+
if (resumed instanceof Resume.Done) {
|
|
1989
|
+
state.pos = resumed.pos
|
|
1990
|
+
return resumed.value as B
|
|
1991
|
+
}
|
|
1992
|
+
if (resumed !== undefined) {
|
|
1993
|
+
acc = resumed.acc
|
|
1994
|
+
count = resumed.count
|
|
1995
|
+
state.pos = resumed.pos
|
|
1996
|
+
} else {
|
|
1997
|
+
acc = init()
|
|
1998
|
+
}
|
|
1999
|
+
for (; count < max; count++) {
|
|
2000
|
+
if (cond !== undefined && count >= min && !cond(acc)) break
|
|
2001
|
+
const start = state.pos
|
|
2002
|
+
const a = step(state)
|
|
2003
|
+
if (a === Fail) {
|
|
2004
|
+
if (state.mode === "Incomplete" && state.resume !== undefined) {
|
|
2005
|
+
Resume.save(state, key, entry, { acc, count, pos: start } satisfies FoldCheckpoint<B>)
|
|
2006
|
+
}
|
|
2007
|
+
if (state.mode !== "Backtrack" || count < min) return Fail
|
|
2008
|
+
recover(state, start)
|
|
2009
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
1788
2010
|
}
|
|
1789
|
-
if (state.
|
|
1790
|
-
|
|
1791
|
-
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
2011
|
+
if (checkLoop && state.pos === start) return assertConsumes(state, name)
|
|
2012
|
+
acc = f(acc, a)
|
|
1792
2013
|
}
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
2014
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
2015
|
+
},
|
|
2016
|
+
name,
|
|
2017
|
+
node ?? { _tag: "Fold", self, init, f, while: cond, name, ...bounds(range) }
|
|
2018
|
+
)
|
|
1798
2019
|
}
|
|
1799
2020
|
|
|
1800
2021
|
/**
|
|
@@ -1828,17 +2049,43 @@ export const repeat: {
|
|
|
1828
2049
|
self: Parser<A, E, R, I>,
|
|
1829
2050
|
range?: Rg
|
|
1830
2051
|
): Parser<Repeated<A, Rg>, E, R, I>
|
|
1831
|
-
} = dual(isParserArg, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, range?: Range) =>
|
|
1832
|
-
foldImpl<A, Array<A>, E, R, I>(
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
2052
|
+
} = /*#__PURE__*/ dual(isParserArg, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, range?: Range) =>
|
|
2053
|
+
foldImpl<A, Array<A>, E, R, I>(
|
|
2054
|
+
self,
|
|
2055
|
+
range,
|
|
2056
|
+
() => [],
|
|
2057
|
+
(acc, a) => {
|
|
2058
|
+
acc.push(a)
|
|
2059
|
+
return acc
|
|
2060
|
+
},
|
|
2061
|
+
"repeat",
|
|
2062
|
+
{ _tag: "Repeat", self, ...bounds(range) }
|
|
2063
|
+
)
|
|
2064
|
+
)
|
|
1836
2065
|
|
|
1837
2066
|
/**
|
|
1838
2067
|
* Applies a parser repeatedly, folding the outputs into an accumulator
|
|
1839
2068
|
* (winnow's `repeat(..).fold(..)`, nom's `fold_many0`/`fold_many1`/
|
|
1840
2069
|
* `fold_many_m_n`).
|
|
1841
2070
|
*
|
|
2071
|
+
* With `while`, the repetition also stops, successfully and without
|
|
2072
|
+
* consuming more input, as soon as the predicate is false of the
|
|
2073
|
+
* accumulator. It is checked before each element once `range.min` elements
|
|
2074
|
+
* have been folded, so `min` still holds.
|
|
2075
|
+
*
|
|
2076
|
+
* @example
|
|
2077
|
+
* ```ts
|
|
2078
|
+
* import { Parser, Token } from "@thomasfosterau/effect-parse"
|
|
2079
|
+
*
|
|
2080
|
+
* // Keeps the first two digits, leaving the rest unparsed
|
|
2081
|
+
* const two = Parser.fold(Token.oneOf("0123456789"), {
|
|
2082
|
+
* init: () => "",
|
|
2083
|
+
* f: (acc, d) => acc + d,
|
|
2084
|
+
* while: (acc) => acc.length < 2
|
|
2085
|
+
* })
|
|
2086
|
+
* Parser.parsePeek(two, "1234") // Result.succeed(["34", "12"])
|
|
2087
|
+
* ```
|
|
2088
|
+
*
|
|
1842
2089
|
* @since 0.1.0
|
|
1843
2090
|
* @category repetition
|
|
1844
2091
|
*/
|
|
@@ -1847,17 +2094,29 @@ export const fold: {
|
|
|
1847
2094
|
readonly init: () => B
|
|
1848
2095
|
readonly f: (acc: B, a: A) => B
|
|
1849
2096
|
readonly range?: Range | undefined
|
|
2097
|
+
readonly while?: ((acc: B) => boolean) | undefined
|
|
1850
2098
|
}): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<B, E, R, I>
|
|
1851
|
-
<A, E, R, I extends Input, B>(
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
}
|
|
2099
|
+
<A, E, R, I extends Input, B>(
|
|
2100
|
+
self: Parser<A, E, R, I>,
|
|
2101
|
+
options: {
|
|
2102
|
+
readonly init: () => B
|
|
2103
|
+
readonly f: (acc: B, a: A) => B
|
|
2104
|
+
readonly range?: Range | undefined
|
|
2105
|
+
readonly while?: ((acc: B) => boolean) | undefined
|
|
2106
|
+
}
|
|
2107
|
+
): Parser<B, E, R, I>
|
|
2108
|
+
} = /*#__PURE__*/ dual(
|
|
2109
|
+
2,
|
|
2110
|
+
<A, E, R, I extends Input, B>(
|
|
2111
|
+
self: Parser<A, E, R, I>,
|
|
2112
|
+
options: {
|
|
2113
|
+
readonly init: () => B
|
|
2114
|
+
readonly f: (acc: B, a: A) => B
|
|
2115
|
+
readonly range?: Range | undefined
|
|
2116
|
+
readonly while?: ((acc: B) => boolean) | undefined
|
|
2117
|
+
}
|
|
2118
|
+
): Parser<B, E, R, I> => foldImpl(self, options.range, options.init, options.f, "fold", undefined, options.while)
|
|
2119
|
+
)
|
|
1861
2120
|
|
|
1862
2121
|
/**
|
|
1863
2122
|
* Applies `self` repeatedly until `end` succeeds, returning the collected
|
|
@@ -1871,47 +2130,58 @@ export const repeatTill: {
|
|
|
1871
2130
|
<B, E2, R2, I2 extends Input, const Rg extends Range = { readonly min: 0 }>(
|
|
1872
2131
|
end: Parser<B, E2, R2, I2>,
|
|
1873
2132
|
range?: Rg
|
|
1874
|
-
): <A, E, R, I extends Input>(
|
|
1875
|
-
self: Parser<A, E, R, I>
|
|
1876
|
-
) => Parser<[Repeated<A, Rg>, B], E | E2, R | R2, I & I2>
|
|
2133
|
+
): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<[Repeated<A, Rg>, B], E | E2, R | R2, I & I2>
|
|
1877
2134
|
<A, E, R, I extends Input, B, E2, R2, I2 extends Input, const Rg extends Range = { readonly min: 0 }>(
|
|
1878
2135
|
self: Parser<A, E, R, I>,
|
|
1879
2136
|
end: Parser<B, E2, R2, I2>,
|
|
1880
2137
|
range?: Rg
|
|
1881
2138
|
): Parser<[Repeated<A, Rg>, B], E | E2, R | R2, I & I2>
|
|
1882
|
-
} = dual(
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
const
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
2139
|
+
} = /*#__PURE__*/ dual(
|
|
2140
|
+
isTwoParserArgs,
|
|
2141
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
2142
|
+
self: Parser<A, E, R, I>,
|
|
2143
|
+
end: Parser<B, E2, R2, I2>,
|
|
2144
|
+
range?: Range
|
|
2145
|
+
): Parser<[Array<A>, B], E | E2, R | R2, I & I2> => {
|
|
2146
|
+
const [min, max] = normalizeRange(range)
|
|
2147
|
+
const step = self.step
|
|
2148
|
+
const endStep = end.step
|
|
2149
|
+
return described(
|
|
2150
|
+
(state) => {
|
|
2151
|
+
const acc: Array<A> = []
|
|
2152
|
+
while (true) {
|
|
2153
|
+
const start = state.pos
|
|
2154
|
+
let endFailure: Failure | undefined
|
|
2155
|
+
if (acc.length >= min) {
|
|
2156
|
+
const b = endStep(state)
|
|
2157
|
+
if (b !== Fail) return [acc, b]
|
|
2158
|
+
if (state.mode !== "Backtrack") return Fail
|
|
2159
|
+
endFailure = state.failure
|
|
2160
|
+
state.pos = start
|
|
2161
|
+
if (acc.length >= max) return Fail
|
|
2162
|
+
}
|
|
2163
|
+
const a = step(state)
|
|
2164
|
+
if (a === Fail) {
|
|
2165
|
+
if (endFailure !== undefined && state.mode === "Backtrack") {
|
|
2166
|
+
state.failWith("Backtrack", mergeFailures(endFailure, state.failure))
|
|
2167
|
+
}
|
|
2168
|
+
return Fail
|
|
2169
|
+
}
|
|
2170
|
+
if (state.pos === start) return assertConsumes(state, "repeatTill")
|
|
2171
|
+
acc.push(a)
|
|
1907
2172
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
2173
|
+
},
|
|
2174
|
+
"repeatTill",
|
|
2175
|
+
{ _tag: "RepeatTill", self, end, ...bounds(range) }
|
|
2176
|
+
)
|
|
2177
|
+
}
|
|
2178
|
+
)
|
|
2179
|
+
|
|
2180
|
+
/** How far `separated` got: the elements so far, and where the next separator starts. */
|
|
2181
|
+
interface SeparatedCheckpoint<A> {
|
|
2182
|
+
readonly acc: Array<A>
|
|
2183
|
+
readonly pos: number
|
|
2184
|
+
}
|
|
1915
2185
|
|
|
1916
2186
|
/**
|
|
1917
2187
|
* Applies `self` repeatedly, separated by `separator`, collecting the
|
|
@@ -1929,12 +2199,6 @@ export const repeatTill: {
|
|
|
1929
2199
|
* @since 0.1.0
|
|
1930
2200
|
* @category repetition
|
|
1931
2201
|
*/
|
|
1932
|
-
/** How far `separated` got: the elements so far, and where the next separator starts. */
|
|
1933
|
-
interface SeparatedCheckpoint<A> {
|
|
1934
|
-
readonly acc: Array<A>
|
|
1935
|
-
readonly pos: number
|
|
1936
|
-
}
|
|
1937
|
-
|
|
1938
2202
|
export const separated: {
|
|
1939
2203
|
<S, E2, R2, I2 extends Input, const Rg extends Range = { readonly min: 0 }>(
|
|
1940
2204
|
separator: Parser<S, E2, R2, I2>,
|
|
@@ -1945,64 +2209,72 @@ export const separated: {
|
|
|
1945
2209
|
separator: Parser<S, E2, R2, I2>,
|
|
1946
2210
|
range?: Rg
|
|
1947
2211
|
): Parser<Repeated<A, Rg>, E | E2, R | R2, I & I2>
|
|
1948
|
-
} = dual(
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
const
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
} else {
|
|
1970
|
-
acc = []
|
|
1971
|
-
if (max === 0) return acc
|
|
1972
|
-
const start = state.pos
|
|
1973
|
-
const first = step(state)
|
|
1974
|
-
if (first === Fail) {
|
|
1975
|
-
if (state.mode !== "Backtrack" || min > 0) return Fail
|
|
1976
|
-
recover(state, start)
|
|
1977
|
-
return acc
|
|
1978
|
-
}
|
|
1979
|
-
acc.push(first)
|
|
1980
|
-
}
|
|
1981
|
-
while (acc.length < max) {
|
|
1982
|
-
const start = state.pos
|
|
1983
|
-
if (sepStep(state) === Fail) {
|
|
1984
|
-
if (state.mode === "Incomplete" && state.resume !== undefined) {
|
|
1985
|
-
Resume.save(state, key, entry, { acc, pos: start } satisfies SeparatedCheckpoint<A>)
|
|
2212
|
+
} = /*#__PURE__*/ dual(
|
|
2213
|
+
isTwoParserArgs,
|
|
2214
|
+
<A, E, R, I extends Input, S, E2, R2, I2 extends Input>(
|
|
2215
|
+
self: Parser<A, E, R, I>,
|
|
2216
|
+
separator: Parser<S, E2, R2, I2>,
|
|
2217
|
+
range?: Range
|
|
2218
|
+
): Parser<Array<A>, E | E2, R | R2, I & I2> => {
|
|
2219
|
+
const [min, max] = normalizeRange(range)
|
|
2220
|
+
const step = self.step
|
|
2221
|
+
const sepStep = separator.step
|
|
2222
|
+
const checkLoop = max === Infinity
|
|
2223
|
+
const key = {}
|
|
2224
|
+
return described(
|
|
2225
|
+
(state) => {
|
|
2226
|
+
const entry = state.pos
|
|
2227
|
+
let acc: Array<A>
|
|
2228
|
+
const resumed =
|
|
2229
|
+
state.resume === undefined ? undefined : (Resume.take(state, key, entry) as SeparatedCheckpoint<A>)
|
|
2230
|
+
if (resumed instanceof Resume.Done) {
|
|
2231
|
+
state.pos = resumed.pos
|
|
2232
|
+
return resumed.value as Array<A>
|
|
1986
2233
|
}
|
|
1987
|
-
if (
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2234
|
+
if (resumed !== undefined) {
|
|
2235
|
+
acc = resumed.acc
|
|
2236
|
+
state.pos = resumed.pos
|
|
2237
|
+
} else {
|
|
2238
|
+
acc = []
|
|
2239
|
+
if (max === 0) return acc
|
|
2240
|
+
const start = state.pos
|
|
2241
|
+
const first = step(state)
|
|
2242
|
+
if (first === Fail) {
|
|
2243
|
+
if (state.mode !== "Backtrack" || min > 0) return Fail
|
|
2244
|
+
recover(state, start)
|
|
2245
|
+
return acc
|
|
2246
|
+
}
|
|
2247
|
+
acc.push(first)
|
|
2248
|
+
}
|
|
2249
|
+
while (acc.length < max) {
|
|
2250
|
+
const start = state.pos
|
|
2251
|
+
if (sepStep(state) === Fail) {
|
|
2252
|
+
if (state.mode === "Incomplete" && state.resume !== undefined) {
|
|
2253
|
+
Resume.save(state, key, entry, { acc, pos: start } satisfies SeparatedCheckpoint<A>)
|
|
2254
|
+
}
|
|
2255
|
+
if (state.mode !== "Backtrack" || acc.length < min) return Fail
|
|
2256
|
+
recover(state, start)
|
|
2257
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
2258
|
+
}
|
|
2259
|
+
if (checkLoop && state.pos === start) return assertConsumes(state, "separated")
|
|
2260
|
+
const a = step(state)
|
|
2261
|
+
if (a === Fail) {
|
|
2262
|
+
if (state.mode === "Incomplete" && state.resume !== undefined) {
|
|
2263
|
+
Resume.save(state, key, entry, { acc, pos: start } satisfies SeparatedCheckpoint<A>)
|
|
2264
|
+
}
|
|
2265
|
+
if (state.mode !== "Backtrack" || acc.length < min) return Fail
|
|
2266
|
+
state.pos = start
|
|
2267
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
2268
|
+
}
|
|
2269
|
+
acc.push(a)
|
|
1996
2270
|
}
|
|
1997
|
-
if (state.mode !== "Backtrack" || acc.length < min) return Fail
|
|
1998
|
-
state.pos = start
|
|
1999
2271
|
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
2000
|
-
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
}
|
|
2005
|
-
|
|
2272
|
+
},
|
|
2273
|
+
"separated",
|
|
2274
|
+
{ _tag: "Separated", self, separator, ...bounds(range) }
|
|
2275
|
+
)
|
|
2276
|
+
}
|
|
2277
|
+
)
|
|
2006
2278
|
|
|
2007
2279
|
/**
|
|
2008
2280
|
* Parses one or more `self` separated by `separator`, folding them from the
|
|
@@ -2033,41 +2305,45 @@ export const separatedFoldl1 = <A, E, R, I extends Input, S, E2, R2, I2 extends
|
|
|
2033
2305
|
const step = self.step
|
|
2034
2306
|
const sepStep = separator.step
|
|
2035
2307
|
const key = {}
|
|
2036
|
-
return described(
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
if (resumed !== undefined) {
|
|
2045
|
-
acc = resumed.acc
|
|
2046
|
-
state.pos = resumed.pos
|
|
2047
|
-
} else {
|
|
2048
|
-
acc = step(state)
|
|
2049
|
-
if (acc === Fail) return Fail
|
|
2050
|
-
}
|
|
2051
|
-
while (true) {
|
|
2052
|
-
const start = state.pos
|
|
2053
|
-
const s = sepStep(state)
|
|
2054
|
-
if (s === Fail) {
|
|
2055
|
-
if (state.mode === "Incomplete" && state.resume !== undefined) saveFold(state, key, entry, acc, start)
|
|
2056
|
-
if (state.mode !== "Backtrack") return Fail
|
|
2057
|
-
recover(state, start)
|
|
2058
|
-
return Resume.done(state, key, entry, resumed !== undefined, acc as A)
|
|
2308
|
+
return described(
|
|
2309
|
+
(state) => {
|
|
2310
|
+
const entry = state.pos
|
|
2311
|
+
const resumed = state.resume === undefined ? undefined : (Resume.take(state, key, entry) as FoldCheckpoint<A>)
|
|
2312
|
+
let acc: A | Fail
|
|
2313
|
+
if (resumed instanceof Resume.Done) {
|
|
2314
|
+
state.pos = resumed.pos
|
|
2315
|
+
return resumed.value as A
|
|
2059
2316
|
}
|
|
2060
|
-
if (
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
return Resume.done(state, key, entry, resumed !== undefined, acc as A)
|
|
2317
|
+
if (resumed !== undefined) {
|
|
2318
|
+
acc = resumed.acc
|
|
2319
|
+
state.pos = resumed.pos
|
|
2320
|
+
} else {
|
|
2321
|
+
acc = step(state)
|
|
2322
|
+
if (acc === Fail) return Fail
|
|
2067
2323
|
}
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2324
|
+
while (true) {
|
|
2325
|
+
const start = state.pos
|
|
2326
|
+
const s = sepStep(state)
|
|
2327
|
+
if (s === Fail) {
|
|
2328
|
+
if (state.mode === "Incomplete" && state.resume !== undefined) saveFold(state, key, entry, acc, start)
|
|
2329
|
+
if (state.mode !== "Backtrack") return Fail
|
|
2330
|
+
recover(state, start)
|
|
2331
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc as A)
|
|
2332
|
+
}
|
|
2333
|
+
if (state.pos === start) return assertConsumes(state, "separatedFoldl1")
|
|
2334
|
+
const a = step(state)
|
|
2335
|
+
if (a === Fail) {
|
|
2336
|
+
if (state.mode === "Incomplete" && state.resume !== undefined) saveFold(state, key, entry, acc, start)
|
|
2337
|
+
if (state.mode !== "Backtrack") return Fail
|
|
2338
|
+
state.pos = start
|
|
2339
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc as A)
|
|
2340
|
+
}
|
|
2341
|
+
acc = op(acc, s, a)
|
|
2342
|
+
}
|
|
2343
|
+
},
|
|
2344
|
+
"separatedFoldl1",
|
|
2345
|
+
{ _tag: "SeparatedFold", self, separator, op, right: false }
|
|
2346
|
+
)
|
|
2071
2347
|
}
|
|
2072
2348
|
|
|
2073
2349
|
/**
|
|
@@ -2086,35 +2362,39 @@ export const separatedFoldr1 = <A, E, R, I extends Input, S, E2, R2, I2 extends
|
|
|
2086
2362
|
): Parser<A, E | E2, R | R2, I & I2> => {
|
|
2087
2363
|
const step = self.step
|
|
2088
2364
|
const sepStep = separator.step
|
|
2089
|
-
return described(
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
if (
|
|
2099
|
-
|
|
2100
|
-
|
|
2365
|
+
return described(
|
|
2366
|
+
(state) => {
|
|
2367
|
+
const first = step(state)
|
|
2368
|
+
if (first === Fail) return Fail
|
|
2369
|
+
const values: Array<A> = [first]
|
|
2370
|
+
const seps: Array<S> = []
|
|
2371
|
+
while (true) {
|
|
2372
|
+
const start = state.pos
|
|
2373
|
+
const s = sepStep(state)
|
|
2374
|
+
if (s === Fail) {
|
|
2375
|
+
if (state.mode !== "Backtrack") return Fail
|
|
2376
|
+
recover(state, start)
|
|
2377
|
+
break
|
|
2378
|
+
}
|
|
2379
|
+
if (state.pos === start) return assertConsumes(state, "separatedFoldr1")
|
|
2380
|
+
const a = step(state)
|
|
2381
|
+
if (a === Fail) {
|
|
2382
|
+
if (state.mode !== "Backtrack") return Fail
|
|
2383
|
+
state.pos = start
|
|
2384
|
+
break
|
|
2385
|
+
}
|
|
2386
|
+
seps.push(s)
|
|
2387
|
+
values.push(a)
|
|
2101
2388
|
}
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
if (state.mode !== "Backtrack") return Fail
|
|
2106
|
-
state.pos = start
|
|
2107
|
-
break
|
|
2389
|
+
let acc = values[values.length - 1] as A
|
|
2390
|
+
for (let i = seps.length - 1; i >= 0; i--) {
|
|
2391
|
+
acc = op(values[i] as A, seps[i] as S, acc)
|
|
2108
2392
|
}
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
acc = op(values[i] as A, seps[i] as S, acc)
|
|
2115
|
-
}
|
|
2116
|
-
return acc
|
|
2117
|
-
}, "separatedFoldr1", { _tag: "SeparatedFold", self, separator, op, right: true })
|
|
2393
|
+
return acc
|
|
2394
|
+
},
|
|
2395
|
+
"separatedFoldr1",
|
|
2396
|
+
{ _tag: "SeparatedFold", self, separator, op, right: true }
|
|
2397
|
+
)
|
|
2118
2398
|
}
|
|
2119
2399
|
|
|
2120
2400
|
// -----------------------------------------------------------------------------
|
|
@@ -2173,22 +2453,29 @@ export const provideService: {
|
|
|
2173
2453
|
key: Context.Key<Id, S>,
|
|
2174
2454
|
service: NoInfer<S>
|
|
2175
2455
|
): Parser<A, E, Exclude<R, Id>, I>
|
|
2176
|
-
} = dual(
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
const
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2456
|
+
} = /*#__PURE__*/ dual(
|
|
2457
|
+
3,
|
|
2458
|
+
<A, E, R, I extends Input, Id, S>(
|
|
2459
|
+
self: Parser<A, E, R, I>,
|
|
2460
|
+
key: Context.Key<Id, S>,
|
|
2461
|
+
service: S
|
|
2462
|
+
): Parser<A, E, Exclude<R, Id>, I> => {
|
|
2463
|
+
const step = self.step
|
|
2464
|
+
return described(
|
|
2465
|
+
(state) => {
|
|
2466
|
+
const prev = state.context
|
|
2467
|
+
state.context = Context.add(prev, key, service) as Context.Context<never>
|
|
2468
|
+
try {
|
|
2469
|
+
return step(state)
|
|
2470
|
+
} finally {
|
|
2471
|
+
state.context = prev
|
|
2472
|
+
}
|
|
2473
|
+
},
|
|
2474
|
+
self.name,
|
|
2475
|
+
{ _tag: "Provide", self }
|
|
2476
|
+
)
|
|
2477
|
+
}
|
|
2478
|
+
)
|
|
2192
2479
|
|
|
2193
2480
|
/**
|
|
2194
2481
|
* Provides a context of services to a parser.
|
|
@@ -2204,21 +2491,28 @@ export const provide: {
|
|
|
2204
2491
|
self: Parser<A, E, R, I>,
|
|
2205
2492
|
context: Context.Context<R2>
|
|
2206
2493
|
): Parser<A, E, Exclude<R, R2>, I>
|
|
2207
|
-
} = dual(
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
const
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2494
|
+
} = /*#__PURE__*/ dual(
|
|
2495
|
+
2,
|
|
2496
|
+
<A, E, R, I extends Input, R2>(
|
|
2497
|
+
self: Parser<A, E, R, I>,
|
|
2498
|
+
context: Context.Context<R2>
|
|
2499
|
+
): Parser<A, E, Exclude<R, R2>, I> => {
|
|
2500
|
+
const step = self.step
|
|
2501
|
+
return described(
|
|
2502
|
+
(state) => {
|
|
2503
|
+
const prev = state.context
|
|
2504
|
+
state.context = Context.merge(prev, context) as Context.Context<never>
|
|
2505
|
+
try {
|
|
2506
|
+
return step(state)
|
|
2507
|
+
} finally {
|
|
2508
|
+
state.context = prev
|
|
2509
|
+
}
|
|
2510
|
+
},
|
|
2511
|
+
self.name,
|
|
2512
|
+
{ _tag: "Provide", self }
|
|
2513
|
+
)
|
|
2514
|
+
}
|
|
2515
|
+
)
|
|
2222
2516
|
|
|
2223
2517
|
// -----------------------------------------------------------------------------
|
|
2224
2518
|
// Error recovery
|
|
@@ -2242,25 +2536,33 @@ export const resumeAfter: {
|
|
|
2242
2536
|
self: Parser<A, E, R, I>,
|
|
2243
2537
|
recover: Parser<B, E2, R2, I2>
|
|
2244
2538
|
): Parser<Option.Option<A>, E | E2, R | R2, I & I2>
|
|
2245
|
-
} = dual(
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
const
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2539
|
+
} = /*#__PURE__*/ dual(
|
|
2540
|
+
2,
|
|
2541
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
2542
|
+
self: Parser<A, E, R, I>,
|
|
2543
|
+
recover: Parser<B, E2, R2, I2>
|
|
2544
|
+
): Parser<Option.Option<A>, E | E2, R | R2, I & I2> => {
|
|
2545
|
+
const step = self.step
|
|
2546
|
+
const recoverStep = recover.step
|
|
2547
|
+
return described(
|
|
2548
|
+
(state) => {
|
|
2549
|
+
const start = state.pos
|
|
2550
|
+
const a = step(state)
|
|
2551
|
+
if (a !== Fail) return Option.some(a)
|
|
2552
|
+
if (state.recovered === undefined || state.mode === "Incomplete") return Fail
|
|
2553
|
+
const failure = state.failure
|
|
2554
|
+
const mode = state.mode
|
|
2555
|
+
state.pos = start
|
|
2556
|
+
if (recoverStep(state) === Fail) return state.failWith(mode, failure)
|
|
2557
|
+
state.recovered.push(failure)
|
|
2558
|
+
state.syntax?.skipped(start, failure, mode)
|
|
2559
|
+
return Option.none()
|
|
2560
|
+
},
|
|
2561
|
+
self.name,
|
|
2562
|
+
{ _tag: "ResumeAfter", self, recover }
|
|
2563
|
+
)
|
|
2564
|
+
}
|
|
2565
|
+
)
|
|
2264
2566
|
|
|
2265
2567
|
/**
|
|
2266
2568
|
* Error recovery: if the parser fails, record the failure, skip input with
|
|
@@ -2280,26 +2582,34 @@ export const retryAfter: {
|
|
|
2280
2582
|
self: Parser<A, E, R, I>,
|
|
2281
2583
|
recover: Parser<B, E2, R2, I2>
|
|
2282
2584
|
): Parser<A, E | E2, R | R2, I & I2>
|
|
2283
|
-
} = dual(
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2585
|
+
} = /*#__PURE__*/ dual(
|
|
2586
|
+
2,
|
|
2587
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
2588
|
+
self: Parser<A, E, R, I>,
|
|
2589
|
+
recover: Parser<B, E2, R2, I2>
|
|
2590
|
+
): Parser<A, E | E2, R | R2, I & I2> => {
|
|
2591
|
+
const step = self.step
|
|
2592
|
+
const recoverStep = recover.step
|
|
2593
|
+
return described(
|
|
2594
|
+
(state) => {
|
|
2595
|
+
while (true) {
|
|
2596
|
+
const start = state.pos
|
|
2597
|
+
const a = step(state)
|
|
2598
|
+
if (a !== Fail) return a
|
|
2599
|
+
if (state.recovered === undefined || state.mode === "Incomplete") return Fail
|
|
2600
|
+
const failure = state.failure
|
|
2601
|
+
const mode = state.mode
|
|
2602
|
+
state.pos = start
|
|
2603
|
+
if (recoverStep(state) === Fail || state.pos === start) return state.failWith(mode, failure)
|
|
2604
|
+
state.recovered.push(failure)
|
|
2605
|
+
state.syntax?.skipped(start, failure, mode)
|
|
2606
|
+
}
|
|
2607
|
+
},
|
|
2608
|
+
self.name,
|
|
2609
|
+
{ _tag: "RetryAfter", self, recover }
|
|
2610
|
+
)
|
|
2611
|
+
}
|
|
2612
|
+
)
|
|
2303
2613
|
|
|
2304
2614
|
// -----------------------------------------------------------------------------
|
|
2305
2615
|
// Debugging
|
|
@@ -2317,33 +2627,37 @@ export const retryAfter: {
|
|
|
2317
2627
|
export const trace: {
|
|
2318
2628
|
(name: string): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
2319
2629
|
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, name: string): Parser<A, E, R, I>
|
|
2320
|
-
} = dual(2, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, name: string): Parser<A, E, R, I> => {
|
|
2630
|
+
} = /*#__PURE__*/ dual(2, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, name: string): Parser<A, E, R, I> => {
|
|
2321
2631
|
const step = self.step
|
|
2322
|
-
return described(
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2632
|
+
return described(
|
|
2633
|
+
(state) => {
|
|
2634
|
+
const tracer = state.tracer
|
|
2635
|
+
if (tracer === undefined) return step(state)
|
|
2636
|
+
const start = state.pos
|
|
2637
|
+
const depth = state.depth
|
|
2638
|
+
tracer({ _tag: "Enter", name, depth, offset: start, state })
|
|
2639
|
+
state.depth = depth + 1
|
|
2640
|
+
const a = step(state)
|
|
2641
|
+
state.depth = depth
|
|
2642
|
+
tracer({
|
|
2643
|
+
_tag: "Exit",
|
|
2644
|
+
name,
|
|
2645
|
+
depth,
|
|
2646
|
+
offset: start,
|
|
2647
|
+
endOffset: state.pos,
|
|
2648
|
+
result: a === Fail ? state.mode : "Ok",
|
|
2649
|
+
state
|
|
2650
|
+
})
|
|
2651
|
+
return a
|
|
2652
|
+
},
|
|
2653
|
+
name,
|
|
2654
|
+
{ _tag: "Trace", self, name }
|
|
2655
|
+
)
|
|
2342
2656
|
})
|
|
2343
2657
|
|
|
2344
2658
|
const preview = (state: State<any>, offset: number): string => {
|
|
2345
2659
|
const input = state.input
|
|
2346
|
-
if (
|
|
2660
|
+
if (Predicate.isString(input)) {
|
|
2347
2661
|
const s = input.slice(offset, offset + 24)
|
|
2348
2662
|
return JSON.stringify(s) + (offset + 24 < input.length ? "…" : "∅")
|
|
2349
2663
|
}
|
|
@@ -2371,88 +2685,28 @@ export const consoleTracer = (event: TraceEvent): void => {
|
|
|
2371
2685
|
}
|
|
2372
2686
|
|
|
2373
2687
|
// -----------------------------------------------------------------------------
|
|
2374
|
-
//
|
|
2688
|
+
// Compiled parsers
|
|
2375
2689
|
// -----------------------------------------------------------------------------
|
|
2376
2690
|
|
|
2377
|
-
/**
|
|
2378
|
-
* Options for {@link compile}.
|
|
2379
|
-
*
|
|
2380
|
-
* @since 0.1.0
|
|
2381
|
-
* @category compilation
|
|
2382
|
-
*/
|
|
2383
|
-
export interface CompileOptions {
|
|
2384
|
-
/**
|
|
2385
|
-
* Which compiler to use:
|
|
2386
|
-
*
|
|
2387
|
-
* - `"auto"` (the default): generated code (a JIT) where `new Function`
|
|
2388
|
-
* is allowed, otherwise specialized closures
|
|
2389
|
-
* - `"closure"`: specialized closures only. It never generates code, so
|
|
2390
|
-
* it is the choice under a Content Security Policy, where even probing
|
|
2391
|
-
* for `new Function` is reported as a violation.
|
|
2392
|
-
*/
|
|
2393
|
-
readonly backend?: "auto" | "closure" | undefined
|
|
2394
|
-
}
|
|
2395
|
-
|
|
2396
|
-
/**
|
|
2397
|
-
* Compiles a parser into fused, specialized code, and returns the same
|
|
2398
|
-
* parser. Grammars are written as usual; compilation only makes
|
|
2399
|
-
* {@link parse}, {@link parseSync}, {@link parsePeek} and
|
|
2400
|
-
* {@link parseEffect} faster. Compile the root of a grammar once, where it
|
|
2401
|
-
* is defined:
|
|
2402
|
-
*
|
|
2403
|
-
* ```ts
|
|
2404
|
-
* import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
2405
|
-
*
|
|
2406
|
-
* export const list = Parser.compile(
|
|
2407
|
-
* Parser.separated(Ascii.decInt, Token.literal(","))
|
|
2408
|
-
* )
|
|
2409
|
-
* Parser.parse(list, "1,2,3") // Result.succeed([1, 2, 3]), compiled
|
|
2410
|
-
* ```
|
|
2411
|
-
*
|
|
2412
|
-
* The code is generated lazily on the first run, for each kind of input
|
|
2413
|
-
* (string, bytes or array), and cached with the parser.
|
|
2414
|
-
*
|
|
2415
|
-
* **Results and errors are unchanged.** Compiled code records no
|
|
2416
|
-
* diagnostics. When it fails, the parser runs again, interpreted, from the
|
|
2417
|
-
* start, so every `ParseError` (offset, expected, context, cause and
|
|
2418
|
-
* message) is exactly the one the interpreter reports.
|
|
2419
|
-
*
|
|
2420
|
-
* **Callbacks should be pure.** On an input that fails, the callbacks given
|
|
2421
|
-
* to `map`, `filter`, `tryMap`, `tap`, `fold`, ... may run twice, once
|
|
2422
|
-
* compiled and once interpreted. Callbacks whose results are discarded
|
|
2423
|
-
* (a `map` inside `taken` or `preceded`, for example) may not run at all,
|
|
2424
|
-
* nor those of a branch that is certain to fail, and token-set predicates
|
|
2425
|
-
* may be called once per character code and cached.
|
|
2426
|
-
*
|
|
2427
|
-
* Runs on partial input ({@link parsePartial}, `ParserStream`), with
|
|
2428
|
-
* {@link parseRecoverable} or with the `trace` option are always
|
|
2429
|
-
* interpreted. Parsers that can't be described, such as {@link make} and
|
|
2430
|
-
* {@link gen}, run interpreted inside compiled code.
|
|
2431
|
-
*
|
|
2432
|
-
* @since 0.1.0
|
|
2433
|
-
* @category compilation
|
|
2434
|
-
*/
|
|
2435
|
-
export const compile: {
|
|
2436
|
-
(options?: CompileOptions): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
2437
|
-
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, options?: CompileOptions): Parser<A, E, R, I>
|
|
2438
|
-
} = dual(isParserArg, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, options?: CompileOptions) => {
|
|
2439
|
-
Compiler.register(self, options?.backend ?? "auto")
|
|
2440
|
-
return self
|
|
2441
|
-
})
|
|
2442
|
-
|
|
2443
2691
|
/** Returned by {@link runCompiled} when there is no compiled form to run. */
|
|
2444
|
-
const NotCompiled: unique symbol = Symbol("NotCompiled")
|
|
2692
|
+
const NotCompiled: unique symbol = /*#__PURE__*/ Symbol("NotCompiled")
|
|
2445
2693
|
|
|
2446
2694
|
/**
|
|
2447
2695
|
* Runs the compiled form of `self`, if it has one: returns its value, or
|
|
2448
2696
|
* `Fail` when it failed (or, with `whole`, did not consume the whole
|
|
2449
|
-
* input), in which case the state must be thrown away.
|
|
2450
|
-
|
|
2451
|
-
|
|
2697
|
+
* input), in which case the state must be thrown away. `resumable` selects
|
|
2698
|
+
* the build that handles partial input.
|
|
2699
|
+
*/
|
|
2700
|
+
const runCompiled = <I extends Input>(
|
|
2701
|
+
self: Parser.Any,
|
|
2702
|
+
state: State<I>,
|
|
2703
|
+
whole: boolean,
|
|
2704
|
+
resumable = false
|
|
2705
|
+
): unknown => {
|
|
2452
2706
|
if (state.tracer !== undefined || state.recovered !== undefined) return NotCompiled
|
|
2453
|
-
const step =
|
|
2707
|
+
const step = Registry.stepFor(self, state, resumable)
|
|
2454
2708
|
if (step === undefined) return NotCompiled
|
|
2455
|
-
const a = step
|
|
2709
|
+
const a = Stack.run(step, state)
|
|
2456
2710
|
if (a === Fail || (whole && state.pos < state.end)) return Fail
|
|
2457
2711
|
return a
|
|
2458
2712
|
}
|
|
@@ -2473,6 +2727,19 @@ export interface ParseOptions {
|
|
|
2473
2727
|
* {@link consoleTracer}.
|
|
2474
2728
|
*/
|
|
2475
2729
|
readonly trace?: boolean | ((event: TraceEvent) => void) | undefined
|
|
2730
|
+
/**
|
|
2731
|
+
* Where to start parsing (default `0`): in code units for strings, bytes
|
|
2732
|
+
* for byte input and elements for arrays. The result is that of parsing
|
|
2733
|
+
* `input.slice(offset)`, but without copying the input, and every offset
|
|
2734
|
+
* (`parsePartial`'s `Done`, `location`, spans, `ParseError.offset` and its
|
|
2735
|
+
* line and column) is a position in the whole input. This is what an
|
|
2736
|
+
* incremental driver, such as a lexer reading one token at a time from a
|
|
2737
|
+
* buffer, needs: compiled parsers run compiled from any offset.
|
|
2738
|
+
*
|
|
2739
|
+
* Throws a `RangeError` unless it is an integer from `0` to the input's
|
|
2740
|
+
* length.
|
|
2741
|
+
*/
|
|
2742
|
+
readonly offset?: number | undefined
|
|
2476
2743
|
}
|
|
2477
2744
|
|
|
2478
2745
|
/**
|
|
@@ -2490,7 +2757,11 @@ const makeState = <I extends Input>(
|
|
|
2490
2757
|
options: (ParseOptions & { readonly context?: Context.Context<any> }) | undefined,
|
|
2491
2758
|
partial: boolean
|
|
2492
2759
|
): State<I> => {
|
|
2493
|
-
const
|
|
2760
|
+
const offset = options?.offset
|
|
2761
|
+
const state = new State(input, { partial, context: options?.context, offset })
|
|
2762
|
+
if (offset !== undefined && !(Number.isInteger(offset) && offset >= 0 && offset <= state.end)) {
|
|
2763
|
+
throw new RangeError(`Invalid offset ${offset} for an input of length ${state.end}`)
|
|
2764
|
+
}
|
|
2494
2765
|
const t = options?.trace
|
|
2495
2766
|
if (t !== undefined && t !== false) state.tracer = t === true ? consoleTracer : t
|
|
2496
2767
|
return state
|
|
@@ -2517,7 +2788,7 @@ const runComplete = <A, E, R, I extends Input>(
|
|
|
2517
2788
|
self: Parser<A, E, R, I>,
|
|
2518
2789
|
state: State<I>
|
|
2519
2790
|
): Result.Result<A, ParseError.ParseError<E>> => {
|
|
2520
|
-
const a = self.step
|
|
2791
|
+
const a = Stack.run(self.step, state)
|
|
2521
2792
|
if (a === Fail) return Result.fail(toError(state))
|
|
2522
2793
|
if (state.pos < state.end) {
|
|
2523
2794
|
state.backtrack("Eof", expectedEof)
|
|
@@ -2567,7 +2838,11 @@ export const parse: {
|
|
|
2567
2838
|
*/
|
|
2568
2839
|
export const parseSync: {
|
|
2569
2840
|
<A, E, I extends Input>(self: Parser<A, E, never, I>, input: NoInfer<Source<I>>, options?: ParseOptions): A
|
|
2570
|
-
<A, E, R, I extends Input>(
|
|
2841
|
+
<A, E, R, I extends Input>(
|
|
2842
|
+
self: Parser<A, E, R, I>,
|
|
2843
|
+
input: NoInfer<Source<I>>,
|
|
2844
|
+
options: ParseOptionsWithContext<R>
|
|
2845
|
+
): A
|
|
2571
2846
|
} = <A, E, R, I extends Input>(
|
|
2572
2847
|
self: Parser<A, E, R, I>,
|
|
2573
2848
|
input: I | Source<I>,
|
|
@@ -2583,6 +2858,10 @@ export const parseSync: {
|
|
|
2583
2858
|
* input along with the output, nom-style (winnow's `parse_peek`, nom's
|
|
2584
2859
|
* `IResult`).
|
|
2585
2860
|
*
|
|
2861
|
+
* The parser ended at offset `input.length - remaining.length`, which is
|
|
2862
|
+
* how a caller running from an `offset` (see {@link ParseOptions}) finds
|
|
2863
|
+
* where to continue.
|
|
2864
|
+
*
|
|
2586
2865
|
* @since 0.1.0
|
|
2587
2866
|
* @category running
|
|
2588
2867
|
*/
|
|
@@ -2608,7 +2887,7 @@ export const parsePeek: {
|
|
|
2608
2887
|
return Result.succeed([state.slice(state.pos, state.end), compiled as A])
|
|
2609
2888
|
}
|
|
2610
2889
|
if (compiled === Fail) state = makeState(input, options, false)
|
|
2611
|
-
const a = self.step
|
|
2890
|
+
const a = Stack.run(self.step, state)
|
|
2612
2891
|
if (a === Fail) return Result.fail(toError(state))
|
|
2613
2892
|
return Result.succeed([state.slice(state.pos, state.end), a])
|
|
2614
2893
|
}
|
|
@@ -2633,7 +2912,14 @@ export type PartialResult<A> =
|
|
|
2633
2912
|
* of failing or succeeding early.
|
|
2634
2913
|
*
|
|
2635
2914
|
* The parser does not have to consume the whole input; the returned
|
|
2636
|
-
* `offset` says
|
|
2915
|
+
* `offset` says where it stopped. It is a position in the whole input, so
|
|
2916
|
+
* with the `offset` option (see {@link ParseOptions}) it is where the next
|
|
2917
|
+
* parse starts.
|
|
2918
|
+
*
|
|
2919
|
+
* A parser compiled with the `Compiler` module runs compiled, with a build
|
|
2920
|
+
* that handles partial input. When it fails or needs more input, it runs again
|
|
2921
|
+
* interpreted, so `Incomplete`'s `needed` and every `ParseError` are the
|
|
2922
|
+
* interpreter's.
|
|
2637
2923
|
*
|
|
2638
2924
|
* @example
|
|
2639
2925
|
* ```ts
|
|
@@ -2664,8 +2950,14 @@ export const parsePartial: {
|
|
|
2664
2950
|
input: I | Source<I>,
|
|
2665
2951
|
options?: ParseOptions & { readonly context?: Context.Context<R> }
|
|
2666
2952
|
): Result.Result<PartialResult<A>, ParseError.ParseError<E>> => {
|
|
2667
|
-
|
|
2668
|
-
const
|
|
2953
|
+
let state = makeState(input, options, true)
|
|
2954
|
+
const compiled = runCompiled(self, state, false, true)
|
|
2955
|
+
if (compiled !== NotCompiled && compiled !== Fail) {
|
|
2956
|
+
return Result.succeed({ _tag: "Done", value: compiled as A, offset: state.pos })
|
|
2957
|
+
}
|
|
2958
|
+
// Re-run interpreted for `needed` and the diagnostics
|
|
2959
|
+
if (compiled === Fail) state = makeState(input, options, true)
|
|
2960
|
+
const a = Stack.run(self.step, state)
|
|
2669
2961
|
if (a !== Fail) return Result.succeed({ _tag: "Done", value: a, offset: state.pos })
|
|
2670
2962
|
if (state.mode === "Incomplete") {
|
|
2671
2963
|
const needed = state.failure.needed
|
|
@@ -2697,11 +2989,87 @@ export const parseEffect = <A, E, R, I extends Input>(
|
|
|
2697
2989
|
input: NoInfer<Source<I>>,
|
|
2698
2990
|
options?: ParseOptions
|
|
2699
2991
|
): Effect.Effect<A, ParseError.ParseError<E>, R> =>
|
|
2700
|
-
Effect.flatMap(
|
|
2701
|
-
Effect.context
|
|
2702
|
-
(context) => Effect.fromResult(parseComplete(self, input, { ...options, context }))
|
|
2992
|
+
Effect.flatMap(Effect.context<R>(), (context) =>
|
|
2993
|
+
Effect.fromResult(parseComplete(self, input, { ...options, context }))
|
|
2703
2994
|
)
|
|
2704
2995
|
|
|
2996
|
+
/**
|
|
2997
|
+
* Runs a parser on a state you own, from `state.pos`, and returns its output
|
|
2998
|
+
* or {@link Fail}: like calling `self.step(state)`, but using the parser's
|
|
2999
|
+
* compiled form when it has one (see the `Compiler` module). This is the
|
|
3000
|
+
* runner for drivers that make many small runs over one buffer, such as a
|
|
3001
|
+
* lexer reading one token at a time: keep one `Input.State` and
|
|
3002
|
+
* `reset` it (`Input.State.reset`) before each run, and no run allocates a
|
|
3003
|
+
* state, a `Result` or a slice.
|
|
3004
|
+
*
|
|
3005
|
+
* On success the cursor is where the parser stopped. On failure the state
|
|
3006
|
+
* holds the interpreter's failure (`mode`, `failure`, and what
|
|
3007
|
+
* `reportedFailure()` returns): a compiled run that fails is thrown away and
|
|
3008
|
+
* the parser's step runs again from the same position. A partial state
|
|
3009
|
+
* (`partial: true`) runs the compiled build that handles partial input, so
|
|
3010
|
+
* `Incomplete` is reported as the step would report it. Under a tracer,
|
|
3011
|
+
* with recovery on or inside a `Syntax` parse, the step runs interpreted.
|
|
3012
|
+
*
|
|
3013
|
+
* A driver that only needs to know *that* a parser failed (it tries
|
|
3014
|
+
* another, or skips a character) can pass `{ diagnostics: false }` to skip
|
|
3015
|
+
* the interpreted re-run; see {@link RunOptions}.
|
|
3016
|
+
*
|
|
3017
|
+
* Compiled code records no hints or furthest failure when it succeeds, so
|
|
3018
|
+
* a later failure on the same state can list fewer expectations than one
|
|
3019
|
+
* after interpreted runs would: reset the state between runs (as above) and
|
|
3020
|
+
* its errors are the ones {@link parse} reports. Deep nesting fails with an
|
|
3021
|
+
* unrecoverable `TooDeep` failure instead of throwing, as in the other
|
|
3022
|
+
* runners.
|
|
3023
|
+
*
|
|
3024
|
+
* @example
|
|
3025
|
+
* ```ts
|
|
3026
|
+
* import { Ascii, Compiler, Input, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
3027
|
+
*
|
|
3028
|
+
* const token = Compiler.jit(Parser.preceded(Ascii.space0, Parser.alt(Ascii.alpha1, Token.oneOf("+-"))))
|
|
3029
|
+
*
|
|
3030
|
+
* const tokens = (text: string): Array<string> => {
|
|
3031
|
+
* const state = new Input.State(text)
|
|
3032
|
+
* const out: Array<string> = []
|
|
3033
|
+
* while (state.pos < state.end) {
|
|
3034
|
+
* const t = Parser.run(token, state.reset(state.pos))
|
|
3035
|
+
* if (t === Input.Fail) break
|
|
3036
|
+
* out.push(t)
|
|
3037
|
+
* }
|
|
3038
|
+
* return out
|
|
3039
|
+
* }
|
|
3040
|
+
*
|
|
3041
|
+
* tokens("a + b") // ["a", "+", "b"]
|
|
3042
|
+
* ```
|
|
3043
|
+
*
|
|
3044
|
+
* @since 0.2.0
|
|
3045
|
+
* @category running
|
|
3046
|
+
*/
|
|
3047
|
+
export const run = <A, E, R, I extends Input>(
|
|
3048
|
+
self: Parser<A, E, R, I>,
|
|
3049
|
+
state: State<I>,
|
|
3050
|
+
options?: RunOptions
|
|
3051
|
+
): A | Fail => Run.runOn(self, self.step, state, options?.diagnostics !== false)
|
|
3052
|
+
|
|
3053
|
+
/**
|
|
3054
|
+
* Options for {@link run}.
|
|
3055
|
+
*
|
|
3056
|
+
* @since 0.2.0
|
|
3057
|
+
* @category running
|
|
3058
|
+
*/
|
|
3059
|
+
export interface RunOptions {
|
|
3060
|
+
/**
|
|
3061
|
+
* Whether a failure records the interpreter's diagnostics (default
|
|
3062
|
+
* `true`). With `false`, a compiled run that fails is not run again
|
|
3063
|
+
* interpreted: the state's `mode` (`Backtrack`, `Cut` or `Incomplete`)
|
|
3064
|
+
* is set and the cursor is back where the run started, but `failure`,
|
|
3065
|
+
* hints and the furthest failure are left as they were. For drivers that
|
|
3066
|
+
* try a parser and move on when it fails, without reporting why, this
|
|
3067
|
+
* halves the cost of each failure. Parsers that run interpreted record
|
|
3068
|
+
* their diagnostics either way.
|
|
3069
|
+
*/
|
|
3070
|
+
readonly diagnostics?: boolean | undefined
|
|
3071
|
+
}
|
|
3072
|
+
|
|
2705
3073
|
/**
|
|
2706
3074
|
* The outcome of {@link parseRecoverable}.
|
|
2707
3075
|
*
|