@thomasfosterau/effect-parse 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +291 -231
- 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 +151 -132
- package/dist/Expression.js.map +1 -1
- package/dist/Input.d.ts +251 -177
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +409 -299
- package/dist/Input.js.map +1 -1
- package/dist/Nom.d.ts +45 -85
- 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 +232 -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 +2034 -1802
- package/dist/Parser.js.map +1 -1
- package/dist/ParserSchema.d.ts +206 -7
- package/dist/ParserSchema.d.ts.map +1 -1
- package/dist/ParserSchema.js +678 -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 +36 -0
- package/dist/internal/stack.js.map +1 -0
- package/dist/internal/syntax.d.ts +147 -0
- package/dist/internal/syntax.d.ts.map +1 -0
- package/dist/internal/syntax.js +309 -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/ties.d.ts +30 -0
- package/dist/internal/ties.d.ts.map +1 -0
- package/dist/internal/ties.js +67 -0
- package/dist/internal/ties.js.map +1 -0
- 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 +24 -16
- package/src/Input.ts +210 -35
- package/src/Nom.ts +4 -3
- package/src/ParseError.ts +49 -52
- package/src/Parser.ts +1199 -799
- package/src/ParserSchema.ts +982 -23
- 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 +41 -0
- package/src/internal/syntax.ts +426 -0
- package/src/internal/text.ts +32 -25
- package/src/internal/ties.ts +83 -0
- 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"
|
|
@@ -39,12 +40,15 @@ import { pipeArguments } from "effect/Pipeable"
|
|
|
39
40
|
import * as Result from "effect/Result"
|
|
40
41
|
import type { Contravariant, Covariant, Simplify } from "effect/Types"
|
|
41
42
|
import type { ErrMode, Input, Slice, Source, TraceEvent } from "./Input.js"
|
|
42
|
-
import { Fail, Failure, mergeExpected, mergeFailures, State } from "./Input.js"
|
|
43
|
+
import { Fail, Failure, mergeExpected, mergeFailures, mergeTiedFailures, 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"
|
|
51
|
+
import { TiedFailures } from "./internal/ties.js"
|
|
48
52
|
import type { Node } from "./internal/node.js"
|
|
49
53
|
import { bounds, NodeId } from "./internal/node.js"
|
|
50
54
|
|
|
@@ -56,7 +60,7 @@ import { bounds, NodeId } from "./internal/node.js"
|
|
|
56
60
|
* @since 0.1.0
|
|
57
61
|
* @category type ids
|
|
58
62
|
*/
|
|
59
|
-
export const TypeId
|
|
63
|
+
export const TypeId = "~effect-parse/Parser" as const
|
|
60
64
|
|
|
61
65
|
/**
|
|
62
66
|
* A parser that consumes input of type `I`, producing a value of type `A`,
|
|
@@ -134,9 +138,11 @@ export declare namespace Parser {
|
|
|
134
138
|
*
|
|
135
139
|
* @since 0.1.0
|
|
136
140
|
*/
|
|
137
|
-
export type InputOf<P> = [P] extends [never]
|
|
138
|
-
|
|
139
|
-
:
|
|
141
|
+
export type InputOf<P> = [P] extends [never]
|
|
142
|
+
? Input
|
|
143
|
+
: [P] extends [Parser<infer _A, infer _E, infer _R, infer I>]
|
|
144
|
+
? I
|
|
145
|
+
: never
|
|
140
146
|
}
|
|
141
147
|
|
|
142
148
|
/**
|
|
@@ -158,10 +164,19 @@ export type Range = number | { readonly min?: number | undefined; readonly max?:
|
|
|
158
164
|
* @since 0.1.0
|
|
159
165
|
* @category models
|
|
160
166
|
*/
|
|
161
|
-
export type Repeated<A, Rg> = Rg extends number
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
167
|
+
export type Repeated<A, Rg> = Rg extends number
|
|
168
|
+
? number extends Rg
|
|
169
|
+
? Array<A>
|
|
170
|
+
: Rg extends 0
|
|
171
|
+
? Array<A>
|
|
172
|
+
: NonEmpty<A>
|
|
173
|
+
: Rg extends { readonly min: infer M extends number }
|
|
174
|
+
? number extends M
|
|
175
|
+
? Array<A>
|
|
176
|
+
: M extends 0
|
|
177
|
+
? Array<A>
|
|
178
|
+
: NonEmpty<A>
|
|
179
|
+
: Array<A>
|
|
165
180
|
|
|
166
181
|
type NonEmpty<A> = [A, ...Array<A>]
|
|
167
182
|
|
|
@@ -241,7 +256,7 @@ class ParserImpl<A, E, R, I extends Input> implements Parser<A, E, R, I> {
|
|
|
241
256
|
* @category guards
|
|
242
257
|
*/
|
|
243
258
|
export const isParser = (u: unknown): u is Parser<unknown, unknown, unknown, never> =>
|
|
244
|
-
|
|
259
|
+
Predicate.isObjectOrArray(u) && TypeId in u
|
|
245
260
|
|
|
246
261
|
const isParserArg = (args: IArguments) => isParser(args[0])
|
|
247
262
|
const isTwoParserArgs = (args: IArguments) => isParser(args[0]) && isParser(args[1])
|
|
@@ -306,8 +321,11 @@ const nodeOfParser = (p: Parser.Any): Node | undefined => (p as any)[NodeId]
|
|
|
306
321
|
export const named: {
|
|
307
322
|
(name: string): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
308
323
|
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, name: string): Parser<A, E, R, I>
|
|
309
|
-
} = dual(
|
|
310
|
-
|
|
324
|
+
} = /*#__PURE__*/ dual(
|
|
325
|
+
2,
|
|
326
|
+
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, name: string): Parser<A, E, R, I> =>
|
|
327
|
+
new ParserImpl(self.step, name, nodeOfParser(self))
|
|
328
|
+
)
|
|
311
329
|
|
|
312
330
|
/**
|
|
313
331
|
* A parser that consumes nothing and succeeds with the given value.
|
|
@@ -334,7 +352,7 @@ export const sync = <A>(evaluate: () => A): Parser<A, never, never, Input> =>
|
|
|
334
352
|
* @since 0.1.0
|
|
335
353
|
* @category constructors
|
|
336
354
|
*/
|
|
337
|
-
export const empty: Parser<void, never, never, Input> = described(() => undefined, "empty", {
|
|
355
|
+
export const empty: Parser<void, never, never, Input> = /*#__PURE__*/ described(() => undefined, "empty", {
|
|
338
356
|
_tag: "Succeed",
|
|
339
357
|
value: undefined
|
|
340
358
|
})
|
|
@@ -374,7 +392,7 @@ const failBacktrack: Node = { _tag: "Fail", mode: "Backtrack" }
|
|
|
374
392
|
* @since 0.1.0
|
|
375
393
|
* @category constructors
|
|
376
394
|
*/
|
|
377
|
-
export const reject: Parser<never, never, never, Input> = described<never, never, never, Input>(
|
|
395
|
+
export const reject: Parser<never, never, never, Input> = /*#__PURE__*/ described<never, never, never, Input>(
|
|
378
396
|
(state) => state.backtrack("Fail"),
|
|
379
397
|
"reject",
|
|
380
398
|
failBacktrack
|
|
@@ -400,7 +418,7 @@ export const failMessage = (message: string): Parser<never, never, never, Input>
|
|
|
400
418
|
* @since 0.1.0
|
|
401
419
|
* @category constructors
|
|
402
420
|
*/
|
|
403
|
-
export const todo: Parser<never, never, never, Input> = described<never, never, never, Input>(
|
|
421
|
+
export const todo: Parser<never, never, never, Input> = /*#__PURE__*/ described<never, never, never, Input>(
|
|
404
422
|
(state) => state.failMessage("Cut", "Assert", "`todo` parser reached"),
|
|
405
423
|
"todo",
|
|
406
424
|
{ _tag: "Fail", mode: "Cut" }
|
|
@@ -410,6 +428,11 @@ export const todo: Parser<never, never, never, Input> = described<never, never,
|
|
|
410
428
|
* Lazily constructs a parser, which is needed to define recursive grammars.
|
|
411
429
|
* The thunk is evaluated once, on first use.
|
|
412
430
|
*
|
|
431
|
+
* Each level of recursion uses some of the call stack, interpreted or
|
|
432
|
+
* compiled, so input nested a few thousand levels deep exhausts it. The
|
|
433
|
+
* runners catch the overflow and fail with an unrecoverable `ParseError` of
|
|
434
|
+
* kind `"TooDeep"` at the offset reached, instead of throwing.
|
|
435
|
+
*
|
|
413
436
|
* @example
|
|
414
437
|
* ```ts
|
|
415
438
|
* import { Parser, Token } from "@thomasfosterau/effect-parse"
|
|
@@ -431,7 +454,7 @@ export const suspend = <A, E = never, R = never, I extends Input = string>(
|
|
|
431
454
|
let parser: Parser<A, E, R, I> | undefined
|
|
432
455
|
return described((state) => (parser ??= evaluate()).step(state), "suspend", {
|
|
433
456
|
_tag: "Suspend",
|
|
434
|
-
resolve: () => parser ??= evaluate()
|
|
457
|
+
resolve: () => (parser ??= evaluate())
|
|
435
458
|
})
|
|
436
459
|
}
|
|
437
460
|
|
|
@@ -441,7 +464,7 @@ export const suspend = <A, E = never, R = never, I extends Input = string>(
|
|
|
441
464
|
* @since 0.1.0
|
|
442
465
|
* @category constructors
|
|
443
466
|
*/
|
|
444
|
-
export const location: Parser<number, never, never, Input> = described((state) => state.pos, "location", {
|
|
467
|
+
export const location: Parser<number, never, never, Input> = /*#__PURE__*/ described((state) => state.pos, "location", {
|
|
445
468
|
_tag: "Location"
|
|
446
469
|
})
|
|
447
470
|
|
|
@@ -453,11 +476,15 @@ export const location: Parser<number, never, never, Input> = described((state) =
|
|
|
453
476
|
* @since 0.1.0
|
|
454
477
|
* @category constructors
|
|
455
478
|
*/
|
|
456
|
-
export const eof: Parser<void, never, never, Input> = described(
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
479
|
+
export const eof: Parser<void, never, never, Input> = /*#__PURE__*/ described(
|
|
480
|
+
(state) => {
|
|
481
|
+
if (state.pos < state.end) return state.backtrack("Eof", expectedEof)
|
|
482
|
+
if (state.partial) return state.incomplete(1, expectedEof)
|
|
483
|
+
return undefined
|
|
484
|
+
},
|
|
485
|
+
"eof",
|
|
486
|
+
{ _tag: "Eof" }
|
|
487
|
+
)
|
|
461
488
|
|
|
462
489
|
const expectedEof = ["end of input"]
|
|
463
490
|
|
|
@@ -474,13 +501,20 @@ const expectedEof = ["end of input"]
|
|
|
474
501
|
export const map: {
|
|
475
502
|
<A, B>(f: (a: A) => B): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<B, E, R, I>
|
|
476
503
|
<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
|
-
|
|
504
|
+
} = /*#__PURE__*/ dual(
|
|
505
|
+
2,
|
|
506
|
+
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, f: (a: A) => B): Parser<B, E, R, I> => {
|
|
507
|
+
const step = self.step
|
|
508
|
+
return described(
|
|
509
|
+
(state) => {
|
|
510
|
+
const a = step(state)
|
|
511
|
+
return a === Fail ? Fail : f(a)
|
|
512
|
+
},
|
|
513
|
+
self.name,
|
|
514
|
+
{ _tag: "Map", self, f }
|
|
515
|
+
)
|
|
516
|
+
}
|
|
517
|
+
)
|
|
484
518
|
|
|
485
519
|
/**
|
|
486
520
|
* Builds an object from the `[key, value]` entries a parser returns, as
|
|
@@ -518,9 +552,9 @@ export const fromEntries = <K extends PropertyKey, V, E, R, I extends Input>(
|
|
|
518
552
|
export const as: {
|
|
519
553
|
<B>(value: B): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<B, E, R, I>
|
|
520
554
|
<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> => {
|
|
555
|
+
} = /*#__PURE__*/ dual(2, <A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, value: B): Parser<B, E, R, I> => {
|
|
522
556
|
const step = self.step
|
|
523
|
-
return described((state) => step(state) === Fail ? Fail : value, self.name, { _tag: "As", self, value })
|
|
557
|
+
return described((state) => (step(state) === Fail ? Fail : value), self.name, { _tag: "As", self, value })
|
|
524
558
|
})
|
|
525
559
|
|
|
526
560
|
/**
|
|
@@ -529,8 +563,7 @@ export const as: {
|
|
|
529
563
|
* @since 0.1.0
|
|
530
564
|
* @category mapping
|
|
531
565
|
*/
|
|
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)
|
|
566
|
+
export const asVoid = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<void, E, R, I> => as(self, undefined)
|
|
534
567
|
|
|
535
568
|
/**
|
|
536
569
|
* Replaces the output of a parser with `Option.some(output)`.
|
|
@@ -550,14 +583,21 @@ export const asSome = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Pars
|
|
|
550
583
|
export const tap: {
|
|
551
584
|
<A>(f: (a: A) => void): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
552
585
|
<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
|
-
|
|
586
|
+
} = /*#__PURE__*/ dual(
|
|
587
|
+
2,
|
|
588
|
+
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, f: (a: A) => void): Parser<A, E, R, I> => {
|
|
589
|
+
const step = self.step
|
|
590
|
+
return described(
|
|
591
|
+
(state) => {
|
|
592
|
+
const a = step(state)
|
|
593
|
+
if (a !== Fail) f(a)
|
|
594
|
+
return a
|
|
595
|
+
},
|
|
596
|
+
self.name,
|
|
597
|
+
{ _tag: "Tap", self, f }
|
|
598
|
+
)
|
|
599
|
+
}
|
|
600
|
+
)
|
|
561
601
|
|
|
562
602
|
/**
|
|
563
603
|
* Uses the output of a parser to choose the parser that consumes the rest
|
|
@@ -574,16 +614,23 @@ export const flatMap: {
|
|
|
574
614
|
self: Parser<A, E, R, I>,
|
|
575
615
|
f: (a: A) => Parser<B, E2, R2, I2>
|
|
576
616
|
): Parser<B, E | E2, R | R2, I & I2>
|
|
577
|
-
} = dual(
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
const
|
|
584
|
-
return
|
|
585
|
-
|
|
586
|
-
|
|
617
|
+
} = /*#__PURE__*/ dual(
|
|
618
|
+
2,
|
|
619
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
620
|
+
self: Parser<A, E, R, I>,
|
|
621
|
+
f: (a: A) => Parser<B, E2, R2, I2>
|
|
622
|
+
): Parser<B, E | E2, R | R2, I & I2> => {
|
|
623
|
+
const step = self.step
|
|
624
|
+
return described(
|
|
625
|
+
(state) => {
|
|
626
|
+
const a = step(state)
|
|
627
|
+
return a === Fail ? Fail : f(a).step(state)
|
|
628
|
+
},
|
|
629
|
+
undefined,
|
|
630
|
+
{ _tag: "FlatMap", self, f }
|
|
631
|
+
)
|
|
632
|
+
}
|
|
633
|
+
)
|
|
587
634
|
|
|
588
635
|
/**
|
|
589
636
|
* Applies a second parser to the *output* of the first (winnow's
|
|
@@ -613,34 +660,37 @@ export const mapParser: {
|
|
|
613
660
|
self: Parser<A, E, R, I>,
|
|
614
661
|
inner: Parser<B, E2, R2, A>
|
|
615
662
|
): 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
|
-
|
|
663
|
+
} = /*#__PURE__*/ dual(
|
|
664
|
+
2,
|
|
665
|
+
<A extends Input, E, R, I extends Input, B, E2, R2>(
|
|
666
|
+
self: Parser<A, E, R, I>,
|
|
667
|
+
inner: Parser<B, E2, R2, A>
|
|
668
|
+
): Parser<B, E | E2, R | R2, I> => {
|
|
669
|
+
const step = self.step
|
|
670
|
+
return make((state) => {
|
|
671
|
+
const start = state.pos
|
|
672
|
+
const a = step(state)
|
|
673
|
+
if (a === Fail) return Fail
|
|
674
|
+
const sub = new State(a, { context: state.context })
|
|
675
|
+
sub.tracer = state.tracer
|
|
676
|
+
sub.depth = state.depth
|
|
677
|
+
sub.recovered = state.recovered
|
|
678
|
+
const b = inner.step(sub)
|
|
679
|
+
if (b === Fail) {
|
|
680
|
+
const f = sub.failure
|
|
681
|
+
if (sub.encoding !== undefined) state.encoding = sub.encoding
|
|
682
|
+
// The inner input is usually a slice ending where the outer parser stopped
|
|
683
|
+
const base = Math.max(start, state.pos - a.length)
|
|
684
|
+
const offset = Math.min(base + f.offset, state.pos)
|
|
685
|
+
return state.failWith(
|
|
686
|
+
sub.mode === "Incomplete" ? "Backtrack" : sub.mode,
|
|
687
|
+
new Failure(offset, f.kind, f.expected, f.context, f.hasCause, f.cause, f.message, 0)
|
|
688
|
+
)
|
|
689
|
+
}
|
|
690
|
+
return b
|
|
691
|
+
})
|
|
692
|
+
}
|
|
693
|
+
)
|
|
644
694
|
|
|
645
695
|
/**
|
|
646
696
|
* Transforms the output of a parser with a function that may fail with a
|
|
@@ -659,21 +709,28 @@ export const tryMap: {
|
|
|
659
709
|
self: Parser<A, E, R, I>,
|
|
660
710
|
f: (a: A) => Result.Result<B, E2>
|
|
661
711
|
): Parser<B, E | E2, R, I>
|
|
662
|
-
} = dual(
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
const
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
712
|
+
} = /*#__PURE__*/ dual(
|
|
713
|
+
2,
|
|
714
|
+
<A, E, R, I extends Input, B, E2>(
|
|
715
|
+
self: Parser<A, E, R, I>,
|
|
716
|
+
f: (a: A) => Result.Result<B, E2>
|
|
717
|
+
): Parser<B, E | E2, R, I> => {
|
|
718
|
+
const step = self.step
|
|
719
|
+
return described(
|
|
720
|
+
(state) => {
|
|
721
|
+
const start = state.pos
|
|
722
|
+
const a = step(state)
|
|
723
|
+
if (a === Fail) return Fail
|
|
724
|
+
const r = f(a)
|
|
725
|
+
if (Result.isSuccess(r)) return r.success
|
|
726
|
+
state.pos = start
|
|
727
|
+
return state.failCause("Backtrack", "Verify", r.failure)
|
|
728
|
+
},
|
|
729
|
+
self.name,
|
|
730
|
+
{ _tag: "TryMap", self, f }
|
|
731
|
+
)
|
|
732
|
+
}
|
|
733
|
+
)
|
|
677
734
|
|
|
678
735
|
/**
|
|
679
736
|
* Like {@link tryMap}, but the function may throw. Thrown values become the
|
|
@@ -685,14 +742,18 @@ export const tryMap: {
|
|
|
685
742
|
export const tryMapUnknown: {
|
|
686
743
|
<A, B>(f: (a: A) => B): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<B, E | unknown, R, I>
|
|
687
744
|
<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
|
-
|
|
745
|
+
} = /*#__PURE__*/ dual(
|
|
746
|
+
2,
|
|
747
|
+
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, f: (a: A) => B): Parser<B, unknown, R, I> =>
|
|
748
|
+
tryMap(self, (a) => {
|
|
749
|
+
try {
|
|
750
|
+
return Result.succeed(f(a))
|
|
751
|
+
} catch (e) {
|
|
752
|
+
if (Stack.isStackOverflow(e)) throw e
|
|
753
|
+
return Result.fail(e)
|
|
754
|
+
}
|
|
755
|
+
})
|
|
756
|
+
)
|
|
696
757
|
|
|
697
758
|
/**
|
|
698
759
|
* Transforms the output of a parser with a function returning an `Option`;
|
|
@@ -705,21 +766,25 @@ export const tryMapUnknown: {
|
|
|
705
766
|
export const filterMap: {
|
|
706
767
|
<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
768
|
<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
|
-
|
|
769
|
+
} = /*#__PURE__*/ dual(
|
|
770
|
+
2,
|
|
771
|
+
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, f: (a: A) => Option.Option<B>): Parser<B, E, R, I> => {
|
|
772
|
+
const step = self.step
|
|
773
|
+
return described(
|
|
774
|
+
(state) => {
|
|
775
|
+
const start = state.pos
|
|
776
|
+
const a = step(state)
|
|
777
|
+
if (a === Fail) return Fail
|
|
778
|
+
const o = f(a)
|
|
779
|
+
if (Option.isSome(o)) return o.value
|
|
780
|
+
state.pos = start
|
|
781
|
+
return state.backtrack("Verify")
|
|
782
|
+
},
|
|
783
|
+
self.name,
|
|
784
|
+
{ _tag: "FilterMap", self, f }
|
|
785
|
+
)
|
|
786
|
+
}
|
|
787
|
+
)
|
|
723
788
|
|
|
724
789
|
/**
|
|
725
790
|
* Keeps the output of a parser only if it satisfies a predicate, otherwise
|
|
@@ -735,16 +800,20 @@ export const filter: {
|
|
|
735
800
|
<A>(predicate: (a: NoInfer<A>) => boolean): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
736
801
|
<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
802
|
<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) => {
|
|
803
|
+
} = /*#__PURE__*/ dual(2, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, predicate: (a: A) => boolean) => {
|
|
739
804
|
const step = self.step
|
|
740
|
-
return described<A, E, R, I>(
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
805
|
+
return described<A, E, R, I>(
|
|
806
|
+
(state) => {
|
|
807
|
+
const start = state.pos
|
|
808
|
+
const a = step(state)
|
|
809
|
+
if (a === Fail) return Fail
|
|
810
|
+
if (predicate(a)) return a
|
|
811
|
+
state.pos = start
|
|
812
|
+
return state.backtrack("Verify")
|
|
813
|
+
},
|
|
814
|
+
self.name,
|
|
815
|
+
{ _tag: "Filter", self, predicate }
|
|
816
|
+
)
|
|
748
817
|
})
|
|
749
818
|
|
|
750
819
|
/**
|
|
@@ -773,21 +842,24 @@ export const filterOrFail: {
|
|
|
773
842
|
predicate: (a: A) => boolean,
|
|
774
843
|
orFailWith: (a: A) => E2
|
|
775
844
|
): 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
|
-
}
|
|
845
|
+
} = /*#__PURE__*/ dual(
|
|
846
|
+
3,
|
|
847
|
+
<A, E, R, I extends Input, E2>(self: Parser<A, E, R, I>, predicate: (a: A) => boolean, orFailWith: (a: A) => E2) => {
|
|
848
|
+
const step = self.step
|
|
849
|
+
return described<A, E | E2, R, I>(
|
|
850
|
+
(state) => {
|
|
851
|
+
const start = state.pos
|
|
852
|
+
const a = step(state)
|
|
853
|
+
if (a === Fail) return Fail
|
|
854
|
+
if (predicate(a)) return a
|
|
855
|
+
state.pos = start
|
|
856
|
+
return state.failCause("Backtrack", "Verify", orFailWith(a))
|
|
857
|
+
},
|
|
858
|
+
self.name,
|
|
859
|
+
{ _tag: "Filter", self, predicate }
|
|
860
|
+
)
|
|
861
|
+
}
|
|
862
|
+
)
|
|
791
863
|
|
|
792
864
|
// -----------------------------------------------------------------------------
|
|
793
865
|
// Consumed input
|
|
@@ -802,10 +874,14 @@ export const filterOrFail: {
|
|
|
802
874
|
*/
|
|
803
875
|
export const taken = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<Slice<I>, E, R, I> => {
|
|
804
876
|
const step = self.step
|
|
805
|
-
return described(
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
877
|
+
return described(
|
|
878
|
+
(state) => {
|
|
879
|
+
const start = state.pos
|
|
880
|
+
return step(state) === Fail ? Fail : state.slice(start, state.pos)
|
|
881
|
+
},
|
|
882
|
+
self.name,
|
|
883
|
+
{ _tag: "Taken", self, encoding: undefined }
|
|
884
|
+
)
|
|
809
885
|
}
|
|
810
886
|
|
|
811
887
|
/**
|
|
@@ -819,11 +895,15 @@ export const withTaken = <A, E, R, I extends Input>(
|
|
|
819
895
|
self: Parser<A, E, R, I>
|
|
820
896
|
): Parser<[output: A, taken: Slice<I>], E, R, I> => {
|
|
821
897
|
const step = self.step
|
|
822
|
-
return described(
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
898
|
+
return described(
|
|
899
|
+
(state) => {
|
|
900
|
+
const start = state.pos
|
|
901
|
+
const a = step(state)
|
|
902
|
+
return a === Fail ? Fail : [a, state.slice(start, state.pos)]
|
|
903
|
+
},
|
|
904
|
+
self.name,
|
|
905
|
+
{ _tag: "WithTaken", self }
|
|
906
|
+
)
|
|
827
907
|
}
|
|
828
908
|
|
|
829
909
|
/**
|
|
@@ -835,10 +915,14 @@ export const withTaken = <A, E, R, I extends Input>(
|
|
|
835
915
|
*/
|
|
836
916
|
export const span = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<Span, E, R, I> => {
|
|
837
917
|
const step = self.step
|
|
838
|
-
return described(
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
918
|
+
return described(
|
|
919
|
+
(state) => {
|
|
920
|
+
const start = state.pos
|
|
921
|
+
return step(state) === Fail ? Fail : { start, end: state.pos }
|
|
922
|
+
},
|
|
923
|
+
self.name,
|
|
924
|
+
{ _tag: "Span", self }
|
|
925
|
+
)
|
|
842
926
|
}
|
|
843
927
|
|
|
844
928
|
/**
|
|
@@ -848,13 +932,19 @@ export const span = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser
|
|
|
848
932
|
* @since 0.1.0
|
|
849
933
|
* @category consumed input
|
|
850
934
|
*/
|
|
851
|
-
export const withSpan = <A, E, R, I extends Input>(
|
|
935
|
+
export const withSpan = <A, E, R, I extends Input>(
|
|
936
|
+
self: Parser<A, E, R, I>
|
|
937
|
+
): Parser<[output: A, span: Span], E, R, I> => {
|
|
852
938
|
const step = self.step
|
|
853
|
-
return described(
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
939
|
+
return described(
|
|
940
|
+
(state) => {
|
|
941
|
+
const start = state.pos
|
|
942
|
+
const a = step(state)
|
|
943
|
+
return a === Fail ? Fail : [a, { start, end: state.pos }]
|
|
944
|
+
},
|
|
945
|
+
self.name,
|
|
946
|
+
{ _tag: "WithSpan", self }
|
|
947
|
+
)
|
|
858
948
|
}
|
|
859
949
|
|
|
860
950
|
// -----------------------------------------------------------------------------
|
|
@@ -867,11 +957,15 @@ const changeMode = <A, E, R, I extends Input>(
|
|
|
867
957
|
to: ErrMode
|
|
868
958
|
): Parser<A, E, R, I> => {
|
|
869
959
|
const step = self.step
|
|
870
|
-
return described(
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
960
|
+
return described(
|
|
961
|
+
(state) => {
|
|
962
|
+
const a = step(state)
|
|
963
|
+
if (a === Fail && state.mode === from) state.mode = to
|
|
964
|
+
return a
|
|
965
|
+
},
|
|
966
|
+
self.name,
|
|
967
|
+
{ _tag: "Mode", self, from, to }
|
|
968
|
+
)
|
|
875
969
|
}
|
|
876
970
|
|
|
877
971
|
/**
|
|
@@ -890,8 +984,29 @@ const changeMode = <A, E, R, I extends Input>(
|
|
|
890
984
|
* @since 0.1.0
|
|
891
985
|
* @category error management
|
|
892
986
|
*/
|
|
893
|
-
export const cut = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> =>
|
|
894
|
-
|
|
987
|
+
export const cut = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> => {
|
|
988
|
+
const step = self.step
|
|
989
|
+
return described(
|
|
990
|
+
(state) => {
|
|
991
|
+
// A committed failure is reported where it happened (winnow's
|
|
992
|
+
// `cut_err`): only failures recorded inside `self` can outrank it as the
|
|
993
|
+
// furthest failure, not ones from abandoned branches or lookaheads before
|
|
994
|
+
// the commit.
|
|
995
|
+
const deepest = state.deepest
|
|
996
|
+
state.deepest = undefined
|
|
997
|
+
const a = step(state)
|
|
998
|
+
if (a === Fail && state.mode !== "Incomplete") {
|
|
999
|
+
state.mode = "Cut"
|
|
1000
|
+
return a
|
|
1001
|
+
}
|
|
1002
|
+
const inner = state.deepest as Failure | undefined
|
|
1003
|
+
if (deepest !== undefined && (inner === undefined || deepest.offset > inner.offset)) state.deepest = deepest
|
|
1004
|
+
return a
|
|
1005
|
+
},
|
|
1006
|
+
self.name,
|
|
1007
|
+
{ _tag: "Mode", self, from: "Backtrack", to: "Cut" }
|
|
1008
|
+
)
|
|
1009
|
+
}
|
|
895
1010
|
|
|
896
1011
|
/**
|
|
897
1012
|
* Turns unrecoverable failures back into recoverable ones (winnow's
|
|
@@ -912,15 +1027,19 @@ export const backtrack = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): P
|
|
|
912
1027
|
*/
|
|
913
1028
|
export const complete = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> => {
|
|
914
1029
|
const step = self.step
|
|
915
|
-
return described(
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
state.
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1030
|
+
return described(
|
|
1031
|
+
(state) => {
|
|
1032
|
+
const start = state.pos
|
|
1033
|
+
const a = step(state)
|
|
1034
|
+
if (a === Fail && state.mode === "Incomplete") {
|
|
1035
|
+
state.pos = start
|
|
1036
|
+
return state.backtrack("Complete")
|
|
1037
|
+
}
|
|
1038
|
+
return a
|
|
1039
|
+
},
|
|
1040
|
+
self.name,
|
|
1041
|
+
{ _tag: "Mode", self, from: "Incomplete", to: "Backtrack" }
|
|
1042
|
+
)
|
|
924
1043
|
}
|
|
925
1044
|
|
|
926
1045
|
/**
|
|
@@ -934,25 +1053,22 @@ export const complete = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Pa
|
|
|
934
1053
|
export const context: {
|
|
935
1054
|
(label: string): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
936
1055
|
<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> => {
|
|
1056
|
+
} = /*#__PURE__*/ dual(2, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, label: string): Parser<A, E, R, I> => {
|
|
938
1057
|
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 })
|
|
1058
|
+
return described(
|
|
1059
|
+
(state) => {
|
|
1060
|
+
const a = step(state)
|
|
1061
|
+
if (a === Fail && state.mode !== "Incomplete") {
|
|
1062
|
+
const f = state.failure
|
|
1063
|
+
state.replaceFailure(
|
|
1064
|
+
new Failure(f.offset, f.kind, f.expected, [...f.context, label], f.hasCause, f.cause, f.message, f.needed)
|
|
1065
|
+
)
|
|
1066
|
+
}
|
|
1067
|
+
return a
|
|
1068
|
+
},
|
|
1069
|
+
self.name ?? label,
|
|
1070
|
+
{ _tag: "Context", self, label }
|
|
1071
|
+
)
|
|
956
1072
|
})
|
|
957
1073
|
|
|
958
1074
|
/**
|
|
@@ -967,22 +1083,31 @@ export const context: {
|
|
|
967
1083
|
export const expected: {
|
|
968
1084
|
(description: string): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
969
1085
|
<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
|
-
|
|
1086
|
+
} = /*#__PURE__*/ dual(
|
|
1087
|
+
2,
|
|
1088
|
+
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, description: string): Parser<A, E, R, I> => {
|
|
1089
|
+
const step = self.step
|
|
1090
|
+
const desc = [description]
|
|
1091
|
+
return described(
|
|
1092
|
+
(state) => {
|
|
1093
|
+
const start = state.pos
|
|
1094
|
+
const hintOffset = state.hintOffset
|
|
1095
|
+
const hintExpected = state.hintExpected
|
|
1096
|
+
const a = step(state)
|
|
1097
|
+
if (a === Fail && state.failure.offset === start) {
|
|
1098
|
+
const f = state.failure
|
|
1099
|
+
const expected = hintOffset === start ? mergeExpected(hintExpected, desc) : desc
|
|
1100
|
+
state.replaceFailure(
|
|
1101
|
+
new Failure(f.offset, f.kind, expected, f.context, f.hasCause, f.cause, f.message, f.needed)
|
|
1102
|
+
)
|
|
1103
|
+
}
|
|
1104
|
+
return a
|
|
1105
|
+
},
|
|
1106
|
+
description,
|
|
1107
|
+
{ _tag: "Expected", self, description }
|
|
1108
|
+
)
|
|
1109
|
+
}
|
|
1110
|
+
)
|
|
986
1111
|
|
|
987
1112
|
/**
|
|
988
1113
|
* Transforms the user error (cause) of a parser's failures.
|
|
@@ -993,17 +1118,26 @@ export const expected: {
|
|
|
993
1118
|
export const mapError: {
|
|
994
1119
|
<E, E2>(f: (e: E) => E2): <A, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E2, R, I>
|
|
995
1120
|
<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
|
-
|
|
1121
|
+
} = /*#__PURE__*/ dual(
|
|
1122
|
+
2,
|
|
1123
|
+
<A, E, R, I extends Input, E2>(self: Parser<A, E, R, I>, f: (e: E) => E2): Parser<A, E2, R, I> => {
|
|
1124
|
+
const step = self.step
|
|
1125
|
+
return described(
|
|
1126
|
+
(state) => {
|
|
1127
|
+
const a = step(state)
|
|
1128
|
+
if (a === Fail && state.failure.hasCause) {
|
|
1129
|
+
const x = state.failure
|
|
1130
|
+
state.replaceFailure(
|
|
1131
|
+
new Failure(x.offset, x.kind, x.expected, x.context, true, f(x.cause as E), x.message, x.needed)
|
|
1132
|
+
)
|
|
1133
|
+
}
|
|
1134
|
+
return a
|
|
1135
|
+
},
|
|
1136
|
+
self.name,
|
|
1137
|
+
{ _tag: "MapError", self }
|
|
1138
|
+
)
|
|
1139
|
+
}
|
|
1140
|
+
)
|
|
1007
1141
|
|
|
1008
1142
|
/**
|
|
1009
1143
|
* Replaces any failure of a parser with the given user error, keeping the
|
|
@@ -1015,18 +1149,25 @@ export const mapError: {
|
|
|
1015
1149
|
export const orFail: {
|
|
1016
1150
|
<E2>(error: () => E2): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E2, R, I>
|
|
1017
1151
|
<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
|
-
}
|
|
1152
|
+
} = /*#__PURE__*/ dual(
|
|
1153
|
+
2,
|
|
1154
|
+
<A, E, R, I extends Input, E2>(self: Parser<A, E, R, I>, error: () => E2): Parser<A, E2, R, I> => {
|
|
1155
|
+
const step = self.step
|
|
1156
|
+
return described(
|
|
1157
|
+
(state) => {
|
|
1158
|
+
const start = state.pos
|
|
1159
|
+
const a = step(state)
|
|
1160
|
+
if (a === Fail && state.mode !== "Incomplete") {
|
|
1161
|
+
const x = state.failure
|
|
1162
|
+
state.replaceFailure(new Failure(start, x.kind, [], x.context, true, error(), undefined, 0))
|
|
1163
|
+
}
|
|
1164
|
+
return a
|
|
1165
|
+
},
|
|
1166
|
+
self.name,
|
|
1167
|
+
{ _tag: "OrFail", self }
|
|
1168
|
+
)
|
|
1169
|
+
}
|
|
1170
|
+
)
|
|
1030
1171
|
|
|
1031
1172
|
/**
|
|
1032
1173
|
* If the parser fails recoverably, tries `that` from the same position.
|
|
@@ -1043,10 +1184,13 @@ export const orElse: {
|
|
|
1043
1184
|
self: Parser<A, E, R, I>,
|
|
1044
1185
|
that: () => Parser<B, E2, R2, I2>
|
|
1045
1186
|
): Parser<A | B, E | E2, R | R2, I & I2>
|
|
1046
|
-
} = dual(
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1187
|
+
} = /*#__PURE__*/ dual(
|
|
1188
|
+
2,
|
|
1189
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
1190
|
+
self: Parser<A, E, R, I>,
|
|
1191
|
+
that: () => Parser<B, E2, R2, I2>
|
|
1192
|
+
): Parser<A | B, E | E2, R | R2, I & I2> => alt(self, suspend(that))
|
|
1193
|
+
)
|
|
1050
1194
|
|
|
1051
1195
|
/**
|
|
1052
1196
|
* If the parser fails recoverably, succeeds with the given value without
|
|
@@ -1058,17 +1202,24 @@ export const orElse: {
|
|
|
1058
1202
|
export const orElseSucceed: {
|
|
1059
1203
|
<B>(value: () => B): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A | B, E, R, I>
|
|
1060
1204
|
<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
|
-
|
|
1205
|
+
} = /*#__PURE__*/ dual(
|
|
1206
|
+
2,
|
|
1207
|
+
<A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, value: () => B): Parser<A | B, E, R, I> => {
|
|
1208
|
+
const step = self.step
|
|
1209
|
+
return described(
|
|
1210
|
+
(state) => {
|
|
1211
|
+
const start = state.pos
|
|
1212
|
+
const a = step(state)
|
|
1213
|
+
if (a !== Fail) return a
|
|
1214
|
+
if (state.mode !== "Backtrack") return Fail
|
|
1215
|
+
recover(state, start)
|
|
1216
|
+
return value()
|
|
1217
|
+
},
|
|
1218
|
+
self.name,
|
|
1219
|
+
{ _tag: "OrElseSucceed", self, value }
|
|
1220
|
+
)
|
|
1221
|
+
}
|
|
1222
|
+
)
|
|
1072
1223
|
|
|
1073
1224
|
/** Rewinds after a recoverable failure, remembering it as a hint. */
|
|
1074
1225
|
const recover = (state: State<any>, start: number): void => {
|
|
@@ -1093,14 +1244,18 @@ const recover = (state: State<any>, start: number): void => {
|
|
|
1093
1244
|
*/
|
|
1094
1245
|
export const opt = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<Option.Option<A>, E, R, I> => {
|
|
1095
1246
|
const step = self.step
|
|
1096
|
-
return described(
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1247
|
+
return described(
|
|
1248
|
+
(state) => {
|
|
1249
|
+
const start = state.pos
|
|
1250
|
+
const a = step(state)
|
|
1251
|
+
if (a !== Fail) return Option.some(a)
|
|
1252
|
+
if (state.mode !== "Backtrack") return Fail
|
|
1253
|
+
recover(state, start)
|
|
1254
|
+
return Option.none()
|
|
1255
|
+
},
|
|
1256
|
+
self.name,
|
|
1257
|
+
{ _tag: "Opt", self }
|
|
1258
|
+
)
|
|
1104
1259
|
}
|
|
1105
1260
|
|
|
1106
1261
|
/**
|
|
@@ -1122,7 +1277,7 @@ export const optional = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Pa
|
|
|
1122
1277
|
export const cond = <A, E, R, I extends Input>(
|
|
1123
1278
|
condition: boolean,
|
|
1124
1279
|
self: Parser<A, E, R, I>
|
|
1125
|
-
): Parser<Option.Option<A>, E, R, I> => condition ? asSome(self) : succeed(Option.none())
|
|
1280
|
+
): Parser<Option.Option<A>, E, R, I> => (condition ? asSome(self) : succeed(Option.none()))
|
|
1126
1281
|
|
|
1127
1282
|
/**
|
|
1128
1283
|
* Runs a parser without consuming input (winnow's and nom's `peek`).
|
|
@@ -1132,18 +1287,26 @@ export const cond = <A, E, R, I extends Input>(
|
|
|
1132
1287
|
*/
|
|
1133
1288
|
export const peek = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> => {
|
|
1134
1289
|
const step = self.step
|
|
1135
|
-
return described(
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1290
|
+
return described(
|
|
1291
|
+
(state) => {
|
|
1292
|
+
const start = state.pos
|
|
1293
|
+
const hintOffset = state.hintOffset
|
|
1294
|
+
const hintExpected = state.hintExpected
|
|
1295
|
+
const deepest = state.deepest
|
|
1296
|
+
const a = step(state)
|
|
1297
|
+
if (a !== Fail) {
|
|
1298
|
+
// Failures inside a lookahead that succeeded are about input that was
|
|
1299
|
+
// never consumed, so they are not reported as the furthest failure
|
|
1300
|
+
state.pos = start
|
|
1301
|
+
state.hintOffset = hintOffset
|
|
1302
|
+
state.hintExpected = hintExpected
|
|
1303
|
+
state.deepest = deepest
|
|
1304
|
+
}
|
|
1305
|
+
return a
|
|
1306
|
+
},
|
|
1307
|
+
self.name,
|
|
1308
|
+
{ _tag: "Peek", self }
|
|
1309
|
+
)
|
|
1147
1310
|
}
|
|
1148
1311
|
|
|
1149
1312
|
/**
|
|
@@ -1155,21 +1318,29 @@ export const peek = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser
|
|
|
1155
1318
|
*/
|
|
1156
1319
|
export const not = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<void, E, R, I> => {
|
|
1157
1320
|
const step = self.step
|
|
1158
|
-
return described(
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1321
|
+
return described(
|
|
1322
|
+
(state) => {
|
|
1323
|
+
const start = state.pos
|
|
1324
|
+
const hintOffset = state.hintOffset
|
|
1325
|
+
const hintExpected = state.hintExpected
|
|
1326
|
+
const deepest = state.deepest
|
|
1327
|
+
const a = step(state)
|
|
1328
|
+
if (a !== Fail) {
|
|
1329
|
+
// The failures inside `self` are not this parser's failure
|
|
1330
|
+
state.pos = start
|
|
1331
|
+
state.deepest = deepest
|
|
1332
|
+
return state.backtrack("Not")
|
|
1333
|
+
}
|
|
1334
|
+
if (state.mode !== "Backtrack") return Fail
|
|
1164
1335
|
state.pos = start
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1336
|
+
state.hintOffset = hintOffset
|
|
1337
|
+
state.hintExpected = hintExpected
|
|
1338
|
+
state.deepest = deepest
|
|
1339
|
+
return undefined
|
|
1340
|
+
},
|
|
1341
|
+
self.name,
|
|
1342
|
+
{ _tag: "Not", self }
|
|
1343
|
+
)
|
|
1173
1344
|
}
|
|
1174
1345
|
|
|
1175
1346
|
/**
|
|
@@ -1202,15 +1373,19 @@ export const seq = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1202
1373
|
> => {
|
|
1203
1374
|
const steps = parsers.map((p) => p.step)
|
|
1204
1375
|
const n = steps.length
|
|
1205
|
-
return described(
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1376
|
+
return described(
|
|
1377
|
+
(state: State<any>) => {
|
|
1378
|
+
const out = new Array(n)
|
|
1379
|
+
for (let i = 0; i < n; i++) {
|
|
1380
|
+
const a = steps[i](state)
|
|
1381
|
+
if (a === Fail) return Fail
|
|
1382
|
+
out[i] = a
|
|
1383
|
+
}
|
|
1384
|
+
return out as any
|
|
1385
|
+
},
|
|
1386
|
+
"seq",
|
|
1387
|
+
{ _tag: "Seq", parsers, output: "tuple" }
|
|
1388
|
+
)
|
|
1214
1389
|
}
|
|
1215
1390
|
|
|
1216
1391
|
/**
|
|
@@ -1230,17 +1405,21 @@ export const struct = <const Fields extends Readonly<Record<string, Parser.Any>>
|
|
|
1230
1405
|
Parser.InputOf<Fields[keyof Fields]>
|
|
1231
1406
|
> => {
|
|
1232
1407
|
const keys = Object.keys(fields)
|
|
1233
|
-
const steps = keys.map((k) => fields[k]
|
|
1408
|
+
const steps = keys.map((k) => fields[k].step)
|
|
1234
1409
|
const n = keys.length
|
|
1235
|
-
return described(
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1410
|
+
return described(
|
|
1411
|
+
(state: State<any>) => {
|
|
1412
|
+
const out: Record<string, unknown> = {}
|
|
1413
|
+
for (let i = 0; i < n; i++) {
|
|
1414
|
+
const a = steps[i](state)
|
|
1415
|
+
if (a === Fail) return Fail
|
|
1416
|
+
out[keys[i]] = a
|
|
1417
|
+
}
|
|
1418
|
+
return out as any
|
|
1419
|
+
},
|
|
1420
|
+
"struct",
|
|
1421
|
+
{ _tag: "Struct", keys, parsers: keys.map((k) => fields[k]) }
|
|
1422
|
+
)
|
|
1244
1423
|
}
|
|
1245
1424
|
|
|
1246
1425
|
/**
|
|
@@ -1257,10 +1436,13 @@ export const zip: {
|
|
|
1257
1436
|
self: Parser<A, E, R, I>,
|
|
1258
1437
|
that: Parser<B, E2, R2, I2>
|
|
1259
1438
|
): Parser<[A, B], E | E2, R | R2, I & I2>
|
|
1260
|
-
} = dual(
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1439
|
+
} = /*#__PURE__*/ dual(
|
|
1440
|
+
2,
|
|
1441
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
1442
|
+
self: Parser<A, E, R, I>,
|
|
1443
|
+
that: Parser<B, E2, R2, I2>
|
|
1444
|
+
): Parser<[A, B], E | E2, R | R2, I & I2> => zipWith(self, that, (a, b) => [a, b])
|
|
1445
|
+
)
|
|
1264
1446
|
|
|
1265
1447
|
/**
|
|
1266
1448
|
* Runs two parsers in sequence and combines their outputs.
|
|
@@ -1278,21 +1460,28 @@ export const zipWith: {
|
|
|
1278
1460
|
that: Parser<B, E2, R2, I2>,
|
|
1279
1461
|
f: (a: A, b: B) => C
|
|
1280
1462
|
): 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
|
-
|
|
1463
|
+
} = /*#__PURE__*/ dual(
|
|
1464
|
+
3,
|
|
1465
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input, C>(
|
|
1466
|
+
self: Parser<A, E, R, I>,
|
|
1467
|
+
that: Parser<B, E2, R2, I2>,
|
|
1468
|
+
f: (a: A, b: B) => C
|
|
1469
|
+
): Parser<C, E | E2, R | R2, I & I2> => {
|
|
1470
|
+
const s1 = self.step
|
|
1471
|
+
const s2 = that.step
|
|
1472
|
+
return described(
|
|
1473
|
+
(state) => {
|
|
1474
|
+
const a = s1(state)
|
|
1475
|
+
if (a === Fail) return Fail
|
|
1476
|
+
const b = s2(state)
|
|
1477
|
+
if (b === Fail) return Fail
|
|
1478
|
+
return f(a, b)
|
|
1479
|
+
},
|
|
1480
|
+
undefined,
|
|
1481
|
+
{ _tag: "ZipWith", self, that, f }
|
|
1482
|
+
)
|
|
1483
|
+
}
|
|
1484
|
+
)
|
|
1296
1485
|
|
|
1297
1486
|
/**
|
|
1298
1487
|
* Runs two parsers in sequence, keeping the output of the first.
|
|
@@ -1308,10 +1497,13 @@ export const zipLeft: {
|
|
|
1308
1497
|
self: Parser<A, E, R, I>,
|
|
1309
1498
|
that: Parser<B, E2, R2, I2>
|
|
1310
1499
|
): Parser<A, E | E2, R | R2, I & I2>
|
|
1311
|
-
} = dual(
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1500
|
+
} = /*#__PURE__*/ dual(
|
|
1501
|
+
2,
|
|
1502
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
1503
|
+
self: Parser<A, E, R, I>,
|
|
1504
|
+
that: Parser<B, E2, R2, I2>
|
|
1505
|
+
): Parser<A, E | E2, R | R2, I & I2> => terminated(self, that)
|
|
1506
|
+
)
|
|
1315
1507
|
|
|
1316
1508
|
/**
|
|
1317
1509
|
* Runs two parsers in sequence, keeping the output of the second.
|
|
@@ -1327,10 +1519,13 @@ export const zipRight: {
|
|
|
1327
1519
|
self: Parser<A, E, R, I>,
|
|
1328
1520
|
that: Parser<B, E2, R2, I2>
|
|
1329
1521
|
): Parser<B, E | E2, R | R2, I & I2>
|
|
1330
|
-
} = dual(
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1522
|
+
} = /*#__PURE__*/ dual(
|
|
1523
|
+
2,
|
|
1524
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
1525
|
+
self: Parser<A, E, R, I>,
|
|
1526
|
+
that: Parser<B, E2, R2, I2>
|
|
1527
|
+
): Parser<B, E | E2, R | R2, I & I2> => preceded(self, that)
|
|
1528
|
+
)
|
|
1334
1529
|
|
|
1335
1530
|
/**
|
|
1336
1531
|
* Runs `prefix` then `parser`, keeping the output of `parser` (winnow's and
|
|
@@ -1345,7 +1540,7 @@ export const preceded = <A1, E1, R1, I1 extends Input, A2, E2, R2, I2 extends In
|
|
|
1345
1540
|
): Parser<A2, E1 | E2, R1 | R2, I1 & I2> => {
|
|
1346
1541
|
const s1 = prefix.step
|
|
1347
1542
|
const s2 = parser.step
|
|
1348
|
-
return described((state) => s1(state) === Fail ? Fail : s2(state), parser.name, {
|
|
1543
|
+
return described((state) => (s1(state) === Fail ? Fail : s2(state)), parser.name, {
|
|
1349
1544
|
_tag: "Seq",
|
|
1350
1545
|
parsers: [prefix, parser],
|
|
1351
1546
|
output: 1
|
|
@@ -1365,11 +1560,15 @@ export const terminated = <A1, E1, R1, I1 extends Input, A2, E2, R2, I2 extends
|
|
|
1365
1560
|
): Parser<A1, E1 | E2, R1 | R2, I1 & I2> => {
|
|
1366
1561
|
const s1 = parser.step
|
|
1367
1562
|
const s2 = suffix.step
|
|
1368
|
-
return described(
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1563
|
+
return described(
|
|
1564
|
+
(state) => {
|
|
1565
|
+
const a = s1(state)
|
|
1566
|
+
if (a === Fail) return Fail
|
|
1567
|
+
return s2(state) === Fail ? Fail : a
|
|
1568
|
+
},
|
|
1569
|
+
parser.name,
|
|
1570
|
+
{ _tag: "Seq", parsers: [parser, suffix], output: 0 }
|
|
1571
|
+
)
|
|
1373
1572
|
}
|
|
1374
1573
|
|
|
1375
1574
|
/**
|
|
@@ -1379,20 +1578,7 @@ export const terminated = <A1, E1, R1, I1 extends Input, A2, E2, R2, I2 extends
|
|
|
1379
1578
|
* @since 0.1.0
|
|
1380
1579
|
* @category sequencing
|
|
1381
1580
|
*/
|
|
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
|
-
>(
|
|
1581
|
+
export const delimited = <A1, E1, R1, I1 extends Input, A2, E2, R2, I2 extends Input, A3, E3, R3, I3 extends Input>(
|
|
1396
1582
|
open: Parser<A1, E1, R1, I1>,
|
|
1397
1583
|
parser: Parser<A2, E2, R2, I2>,
|
|
1398
1584
|
close: Parser<A3, E3, R3, I3>
|
|
@@ -1400,12 +1586,16 @@ export const delimited = <
|
|
|
1400
1586
|
const s1 = open.step
|
|
1401
1587
|
const s2 = parser.step
|
|
1402
1588
|
const s3 = close.step
|
|
1403
|
-
return described(
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1589
|
+
return described(
|
|
1590
|
+
(state) => {
|
|
1591
|
+
if (s1(state) === Fail) return Fail
|
|
1592
|
+
const a = s2(state)
|
|
1593
|
+
if (a === Fail) return Fail
|
|
1594
|
+
return s3(state) === Fail ? Fail : a
|
|
1595
|
+
},
|
|
1596
|
+
parser.name,
|
|
1597
|
+
{ _tag: "Seq", parsers: [open, parser, close], output: 1 }
|
|
1598
|
+
)
|
|
1409
1599
|
}
|
|
1410
1600
|
|
|
1411
1601
|
/**
|
|
@@ -1415,20 +1605,7 @@ export const delimited = <
|
|
|
1415
1605
|
* @since 0.1.0
|
|
1416
1606
|
* @category sequencing
|
|
1417
1607
|
*/
|
|
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
|
-
>(
|
|
1608
|
+
export const separatedPair = <A1, E1, R1, I1 extends Input, A2, E2, R2, I2 extends Input, A3, E3, R3, I3 extends Input>(
|
|
1432
1609
|
first: Parser<A1, E1, R1, I1>,
|
|
1433
1610
|
separator: Parser<A2, E2, R2, I2>,
|
|
1434
1611
|
second: Parser<A3, E3, R3, I3>
|
|
@@ -1436,13 +1613,17 @@ export const separatedPair = <
|
|
|
1436
1613
|
const s1 = first.step
|
|
1437
1614
|
const s2 = separator.step
|
|
1438
1615
|
const s3 = second.step
|
|
1439
|
-
return described(
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1616
|
+
return described(
|
|
1617
|
+
(state) => {
|
|
1618
|
+
const a = s1(state)
|
|
1619
|
+
if (a === Fail) return Fail
|
|
1620
|
+
if (s2(state) === Fail) return Fail
|
|
1621
|
+
const b = s3(state)
|
|
1622
|
+
return b === Fail ? Fail : [a, b]
|
|
1623
|
+
},
|
|
1624
|
+
undefined,
|
|
1625
|
+
{ _tag: "Seq", parsers: [first, separator, second], output: [0, 2] }
|
|
1626
|
+
)
|
|
1446
1627
|
}
|
|
1447
1628
|
|
|
1448
1629
|
/**
|
|
@@ -1461,6 +1642,23 @@ export const separatedPair = <
|
|
|
1461
1642
|
* })
|
|
1462
1643
|
* ```
|
|
1463
1644
|
*
|
|
1645
|
+
* The body runs on every parse, so parsers created inside it, like
|
|
1646
|
+
* `Token.literal("=")` above, are rebuilt on every run. On hot paths, build
|
|
1647
|
+
* them once outside the body:
|
|
1648
|
+
*
|
|
1649
|
+
* ```ts
|
|
1650
|
+
* import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
1651
|
+
*
|
|
1652
|
+
* const equals = Token.literal("=")
|
|
1653
|
+
*
|
|
1654
|
+
* const keyValue = Parser.gen(function*() {
|
|
1655
|
+
* const key = yield* Ascii.alpha1
|
|
1656
|
+
* yield* equals
|
|
1657
|
+
* const value = yield* Ascii.decInt
|
|
1658
|
+
* return [key, value] as const
|
|
1659
|
+
* })
|
|
1660
|
+
* ```
|
|
1661
|
+
*
|
|
1464
1662
|
* @since 0.1.0
|
|
1465
1663
|
* @category sequencing
|
|
1466
1664
|
*/
|
|
@@ -1498,7 +1696,7 @@ export const gen = <Eff extends Parser.Any, AEff>(
|
|
|
1498
1696
|
* @since 0.1.0
|
|
1499
1697
|
* @category do notation
|
|
1500
1698
|
*/
|
|
1501
|
-
export const Do: Parser<
|
|
1699
|
+
export const Do: Parser<Record<never, never>, never, never, Input> = /*#__PURE__*/ succeed({})
|
|
1502
1700
|
|
|
1503
1701
|
/**
|
|
1504
1702
|
* Binds the output of a parser to a field of the Do record.
|
|
@@ -1518,8 +1716,9 @@ export const bind: {
|
|
|
1518
1716
|
name: Exclude<N, keyof A>,
|
|
1519
1717
|
f: (a: NoInfer<A>) => Parser<B, E2, R2, I2>
|
|
1520
1718
|
): 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 })))
|
|
1719
|
+
} = /*#__PURE__*/ dual(3, (self: Parser.Any, name: string, f: (a: any) => Parser.Any): Parser.Any =>
|
|
1720
|
+
flatMap(self, (a) => map(f(a), (b) => ({ ...a, [name]: b })))
|
|
1721
|
+
)
|
|
1523
1722
|
|
|
1524
1723
|
/**
|
|
1525
1724
|
* Wraps the output of a parser in a record with a single field.
|
|
@@ -1530,7 +1729,7 @@ export const bind: {
|
|
|
1530
1729
|
export const bindTo: {
|
|
1531
1730
|
<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
1731
|
<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 })))
|
|
1732
|
+
} = /*#__PURE__*/ dual(2, (self: Parser.Any, name: string): Parser.Any => map(self, (a) => ({ [name]: a })))
|
|
1534
1733
|
|
|
1535
1734
|
const let_: {
|
|
1536
1735
|
<N extends string, A extends object, B>(
|
|
@@ -1542,8 +1741,9 @@ const let_: {
|
|
|
1542
1741
|
name: Exclude<N, keyof A>,
|
|
1543
1742
|
f: (a: NoInfer<A>) => B
|
|
1544
1743
|
): 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) }))
|
|
1744
|
+
} = /*#__PURE__*/ dual(3, (self: Parser.Any, name: string, f: (a: any) => unknown): Parser.Any =>
|
|
1745
|
+
map(self, (a) => ({ ...a, [name]: f(a) }))
|
|
1746
|
+
)
|
|
1547
1747
|
|
|
1548
1748
|
export {
|
|
1549
1749
|
/**
|
|
@@ -1582,22 +1782,56 @@ export const alt = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1582
1782
|
const steps = parsers.map((p) => p.step)
|
|
1583
1783
|
const n = steps.length
|
|
1584
1784
|
if (n === 0) return reject as any
|
|
1585
|
-
if (n === 1) return parsers[0]
|
|
1586
|
-
return described(
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1785
|
+
if (n === 1) return parsers[0]
|
|
1786
|
+
return described(
|
|
1787
|
+
(state: State<any>) => {
|
|
1788
|
+
const start = state.pos
|
|
1789
|
+
// The branches' failures merged left to right, as `mergeFailures` would,
|
|
1790
|
+
// except that the last two failures tied with `failure` wait in `tie1`
|
|
1791
|
+
// and `tie2` and are merged only when needed: when a third tie arrives,
|
|
1792
|
+
// when a succeeding branch stops where they failed (for the hint), or
|
|
1793
|
+
// when the merge is read from the state after `failTies`. An `alt` whose
|
|
1794
|
+
// later branch consumes input discards them unmerged.
|
|
1795
|
+
let failure: Failure | undefined
|
|
1796
|
+
let tie1: Failure | undefined
|
|
1797
|
+
let tie2: Failure | undefined
|
|
1798
|
+
for (let i = 0; i < n; i++) {
|
|
1799
|
+
const a = steps[i](state)
|
|
1800
|
+
if (a !== Fail) {
|
|
1801
|
+
if (failure !== undefined && failure.offset === state.pos) {
|
|
1802
|
+
let expected = failure.expected
|
|
1803
|
+
if (tie1 !== undefined) expected = mergeExpected(expected, tie1.expected)
|
|
1804
|
+
if (tie2 !== undefined) expected = mergeExpected(expected, tie2.expected)
|
|
1805
|
+
state.setHint(failure.offset, expected)
|
|
1806
|
+
}
|
|
1807
|
+
return a
|
|
1808
|
+
}
|
|
1809
|
+
if (state.mode !== "Backtrack") return Fail
|
|
1810
|
+
state.pos = start
|
|
1811
|
+
// The branch's failure, whose own ties (from a nested `alt`) can be taken over unmerged
|
|
1812
|
+
const head = state.failureHead
|
|
1813
|
+
if (failure === undefined || head.offset > failure.offset) {
|
|
1814
|
+
failure = head
|
|
1815
|
+
tie1 = state.failureTie1
|
|
1816
|
+
tie2 = state.failureTie2
|
|
1817
|
+
} else if (head.offset === failure.offset) {
|
|
1818
|
+
const f = state.failure
|
|
1819
|
+
if (tie1 === undefined) tie1 = f
|
|
1820
|
+
else if (tie2 === undefined) tie2 = f
|
|
1821
|
+
else {
|
|
1822
|
+
failure = mergeTiedFailures(failure, tie1, mergeExpected(failure.expected, tie1.expected))
|
|
1823
|
+
tie1 = tie2
|
|
1824
|
+
tie2 = f
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1594
1827
|
}
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
state.
|
|
1598
|
-
}
|
|
1599
|
-
|
|
1600
|
-
|
|
1828
|
+
// `failure` is set: there are at least two alternatives, and each one that fails sets it
|
|
1829
|
+
if (failure === undefined) return state.failWith("Backtrack", state.failure)
|
|
1830
|
+
return tie1 === undefined ? state.failWith("Backtrack", failure) : state.failTies(failure, tie1, tie2)
|
|
1831
|
+
},
|
|
1832
|
+
"alt",
|
|
1833
|
+
{ _tag: "Alt", parsers }
|
|
1834
|
+
)
|
|
1601
1835
|
}
|
|
1602
1836
|
|
|
1603
1837
|
/**
|
|
@@ -1609,6 +1843,11 @@ export const alt = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1609
1843
|
* an optional `otherwise` parser for unlisted keys, like winnow's `_ =>`
|
|
1610
1844
|
* arm), or as a function returning a parser (or `undefined` for no match).
|
|
1611
1845
|
*
|
|
1846
|
+
* Prefer a record where the keys are known. Compiled code (see the
|
|
1847
|
+
* `Compiler` module) switches on the key and runs every case compiled; the
|
|
1848
|
+
* parser a function returns always runs interpreted, and one the function
|
|
1849
|
+
* builds (`(c) => Parser.cut(p)`) is rebuilt on every run.
|
|
1850
|
+
*
|
|
1612
1851
|
* @example
|
|
1613
1852
|
* ```ts
|
|
1614
1853
|
* import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
@@ -1656,26 +1895,31 @@ export const dispatch: {
|
|
|
1656
1895
|
cases: ((key: any) => Parser.Any | undefined) | Record<PropertyKey, Parser.Any>,
|
|
1657
1896
|
otherwise?: Parser.Any
|
|
1658
1897
|
) => {
|
|
1659
|
-
const choose =
|
|
1660
|
-
|
|
1898
|
+
const choose = Predicate.isFunction(cases)
|
|
1899
|
+
? cases
|
|
1900
|
+
: (key: PropertyKey) => (Object.prototype.hasOwnProperty.call(cases, key) ? cases[key] : otherwise)
|
|
1661
1901
|
const step = selector.step
|
|
1662
|
-
return described(
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1902
|
+
return described(
|
|
1903
|
+
(state: State<any>) => {
|
|
1904
|
+
const start = state.pos
|
|
1905
|
+
const key = step(state)
|
|
1906
|
+
if (key === Fail) return Fail
|
|
1907
|
+
const parser = choose(key)
|
|
1908
|
+
if (parser === undefined) {
|
|
1909
|
+
state.pos = start
|
|
1910
|
+
return state.backtrack("Dispatch")
|
|
1911
|
+
}
|
|
1912
|
+
return parser.step(state)
|
|
1913
|
+
},
|
|
1914
|
+
"dispatch",
|
|
1915
|
+
{
|
|
1916
|
+
_tag: "Dispatch",
|
|
1917
|
+
selector,
|
|
1918
|
+
cases: Predicate.isFunction(cases) ? undefined : cases,
|
|
1919
|
+
otherwise: Predicate.isFunction(cases) ? undefined : otherwise,
|
|
1920
|
+
choose
|
|
1670
1921
|
}
|
|
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
|
-
})
|
|
1922
|
+
)
|
|
1679
1923
|
}
|
|
1680
1924
|
|
|
1681
1925
|
/**
|
|
@@ -1697,16 +1941,18 @@ export const permutation = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1697
1941
|
const steps = parsers.map((p) => p.step)
|
|
1698
1942
|
const n = steps.length
|
|
1699
1943
|
return make((state: State<any>) => {
|
|
1700
|
-
|
|
1944
|
+
// A round's failures, merged only if no parser matches in it (#44)
|
|
1945
|
+
const ties = new TiedFailures()
|
|
1701
1946
|
const done = new Array<boolean>(n).fill(false)
|
|
1947
|
+
const out = new Array(n)
|
|
1702
1948
|
let remaining = n
|
|
1703
1949
|
while (remaining > 0) {
|
|
1704
|
-
|
|
1950
|
+
ties.clear()
|
|
1705
1951
|
let matched = false
|
|
1706
1952
|
for (let i = 0; i < n; i++) {
|
|
1707
1953
|
if (done[i]) continue
|
|
1708
1954
|
const start = state.pos
|
|
1709
|
-
const a = steps[i]
|
|
1955
|
+
const a = steps[i](state)
|
|
1710
1956
|
if (a !== Fail) {
|
|
1711
1957
|
out[i] = a
|
|
1712
1958
|
done[i] = true
|
|
@@ -1715,10 +1961,11 @@ export const permutation = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1715
1961
|
break
|
|
1716
1962
|
}
|
|
1717
1963
|
if (state.mode !== "Backtrack") return Fail
|
|
1718
|
-
failure = failure === undefined ? state.failure : mergeFailures(failure, state.failure)
|
|
1719
1964
|
state.pos = start
|
|
1965
|
+
ties.add(state)
|
|
1720
1966
|
}
|
|
1721
|
-
|
|
1967
|
+
// Some parser is not done yet, and each one that fails is folded in
|
|
1968
|
+
if (!matched) return ties.fail(state)
|
|
1722
1969
|
}
|
|
1723
1970
|
return out as any
|
|
1724
1971
|
}, "permutation")
|
|
@@ -1730,7 +1977,7 @@ export const permutation = <const Ps extends ReadonlyArray<Parser.Any>>(
|
|
|
1730
1977
|
|
|
1731
1978
|
const normalizeRange = (range: Range | undefined): [min: number, max: number] => {
|
|
1732
1979
|
if (range === undefined) return [0, Infinity]
|
|
1733
|
-
if (
|
|
1980
|
+
if (Predicate.isNumber(range)) return [range, range]
|
|
1734
1981
|
const min = range.min ?? 0
|
|
1735
1982
|
const max = range.max ?? Infinity
|
|
1736
1983
|
if (min > max) throw new RangeError(`invalid range: min (${min}) > max (${max})`)
|
|
@@ -1757,44 +2004,50 @@ const foldImpl = <A, B, E, R, I extends Input>(
|
|
|
1757
2004
|
init: () => B,
|
|
1758
2005
|
f: (acc: B, a: A) => B,
|
|
1759
2006
|
name: string,
|
|
1760
|
-
node?: Node
|
|
2007
|
+
node?: Node,
|
|
2008
|
+
cond?: (acc: B) => boolean
|
|
1761
2009
|
): Parser<B, E, R, I> => {
|
|
1762
2010
|
const [min, max] = normalizeRange(range)
|
|
1763
2011
|
const step = self.step
|
|
1764
2012
|
const checkLoop = max === Infinity
|
|
1765
2013
|
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
|
-
|
|
2014
|
+
return described(
|
|
2015
|
+
(state) => {
|
|
2016
|
+
const entry = state.pos
|
|
2017
|
+
let acc: B
|
|
2018
|
+
let count = 0
|
|
2019
|
+
const resumed = state.resume === undefined ? undefined : (Resume.take(state, key, entry) as FoldCheckpoint<B>)
|
|
2020
|
+
if (resumed instanceof Resume.Done) {
|
|
2021
|
+
state.pos = resumed.pos
|
|
2022
|
+
return resumed.value as B
|
|
2023
|
+
}
|
|
2024
|
+
if (resumed !== undefined) {
|
|
2025
|
+
acc = resumed.acc
|
|
2026
|
+
count = resumed.count
|
|
2027
|
+
state.pos = resumed.pos
|
|
2028
|
+
} else {
|
|
2029
|
+
acc = init()
|
|
2030
|
+
}
|
|
2031
|
+
for (; count < max; count++) {
|
|
2032
|
+
if (cond !== undefined && count >= min && !cond(acc)) break
|
|
2033
|
+
const start = state.pos
|
|
2034
|
+
const a = step(state)
|
|
2035
|
+
if (a === Fail) {
|
|
2036
|
+
if (state.mode === "Incomplete" && state.resume !== undefined) {
|
|
2037
|
+
Resume.save(state, key, entry, { acc, count, pos: start } satisfies FoldCheckpoint<B>)
|
|
2038
|
+
}
|
|
2039
|
+
if (state.mode !== "Backtrack" || count < min) return Fail
|
|
2040
|
+
recover(state, start)
|
|
2041
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
1788
2042
|
}
|
|
1789
|
-
if (state.
|
|
1790
|
-
|
|
1791
|
-
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
2043
|
+
if (checkLoop && state.pos === start) return assertConsumes(state, name)
|
|
2044
|
+
acc = f(acc, a)
|
|
1792
2045
|
}
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
2046
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
2047
|
+
},
|
|
2048
|
+
name,
|
|
2049
|
+
node ?? { _tag: "Fold", self, init, f, while: cond, name, ...bounds(range) }
|
|
2050
|
+
)
|
|
1798
2051
|
}
|
|
1799
2052
|
|
|
1800
2053
|
/**
|
|
@@ -1828,17 +2081,43 @@ export const repeat: {
|
|
|
1828
2081
|
self: Parser<A, E, R, I>,
|
|
1829
2082
|
range?: Rg
|
|
1830
2083
|
): 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
|
-
|
|
2084
|
+
} = /*#__PURE__*/ dual(isParserArg, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, range?: Range) =>
|
|
2085
|
+
foldImpl<A, Array<A>, E, R, I>(
|
|
2086
|
+
self,
|
|
2087
|
+
range,
|
|
2088
|
+
() => [],
|
|
2089
|
+
(acc, a) => {
|
|
2090
|
+
acc.push(a)
|
|
2091
|
+
return acc
|
|
2092
|
+
},
|
|
2093
|
+
"repeat",
|
|
2094
|
+
{ _tag: "Repeat", self, ...bounds(range) }
|
|
2095
|
+
)
|
|
2096
|
+
)
|
|
1836
2097
|
|
|
1837
2098
|
/**
|
|
1838
2099
|
* Applies a parser repeatedly, folding the outputs into an accumulator
|
|
1839
2100
|
* (winnow's `repeat(..).fold(..)`, nom's `fold_many0`/`fold_many1`/
|
|
1840
2101
|
* `fold_many_m_n`).
|
|
1841
2102
|
*
|
|
2103
|
+
* With `while`, the repetition also stops, successfully and without
|
|
2104
|
+
* consuming more input, as soon as the predicate is false of the
|
|
2105
|
+
* accumulator. It is checked before each element once `range.min` elements
|
|
2106
|
+
* have been folded, so `min` still holds.
|
|
2107
|
+
*
|
|
2108
|
+
* @example
|
|
2109
|
+
* ```ts
|
|
2110
|
+
* import { Parser, Token } from "@thomasfosterau/effect-parse"
|
|
2111
|
+
*
|
|
2112
|
+
* // Keeps the first two digits, leaving the rest unparsed
|
|
2113
|
+
* const two = Parser.fold(Token.oneOf("0123456789"), {
|
|
2114
|
+
* init: () => "",
|
|
2115
|
+
* f: (acc, d) => acc + d,
|
|
2116
|
+
* while: (acc) => acc.length < 2
|
|
2117
|
+
* })
|
|
2118
|
+
* Parser.parsePeek(two, "1234") // Result.succeed(["34", "12"])
|
|
2119
|
+
* ```
|
|
2120
|
+
*
|
|
1842
2121
|
* @since 0.1.0
|
|
1843
2122
|
* @category repetition
|
|
1844
2123
|
*/
|
|
@@ -1847,17 +2126,29 @@ export const fold: {
|
|
|
1847
2126
|
readonly init: () => B
|
|
1848
2127
|
readonly f: (acc: B, a: A) => B
|
|
1849
2128
|
readonly range?: Range | undefined
|
|
2129
|
+
readonly while?: ((acc: B) => boolean) | undefined
|
|
1850
2130
|
}): <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
|
-
}
|
|
2131
|
+
<A, E, R, I extends Input, B>(
|
|
2132
|
+
self: Parser<A, E, R, I>,
|
|
2133
|
+
options: {
|
|
2134
|
+
readonly init: () => B
|
|
2135
|
+
readonly f: (acc: B, a: A) => B
|
|
2136
|
+
readonly range?: Range | undefined
|
|
2137
|
+
readonly while?: ((acc: B) => boolean) | undefined
|
|
2138
|
+
}
|
|
2139
|
+
): Parser<B, E, R, I>
|
|
2140
|
+
} = /*#__PURE__*/ dual(
|
|
2141
|
+
2,
|
|
2142
|
+
<A, E, R, I extends Input, B>(
|
|
2143
|
+
self: Parser<A, E, R, I>,
|
|
2144
|
+
options: {
|
|
2145
|
+
readonly init: () => B
|
|
2146
|
+
readonly f: (acc: B, a: A) => B
|
|
2147
|
+
readonly range?: Range | undefined
|
|
2148
|
+
readonly while?: ((acc: B) => boolean) | undefined
|
|
2149
|
+
}
|
|
2150
|
+
): Parser<B, E, R, I> => foldImpl(self, options.range, options.init, options.f, "fold", undefined, options.while)
|
|
2151
|
+
)
|
|
1861
2152
|
|
|
1862
2153
|
/**
|
|
1863
2154
|
* Applies `self` repeatedly until `end` succeeds, returning the collected
|
|
@@ -1871,47 +2162,58 @@ export const repeatTill: {
|
|
|
1871
2162
|
<B, E2, R2, I2 extends Input, const Rg extends Range = { readonly min: 0 }>(
|
|
1872
2163
|
end: Parser<B, E2, R2, I2>,
|
|
1873
2164
|
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>
|
|
2165
|
+
): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<[Repeated<A, Rg>, B], E | E2, R | R2, I & I2>
|
|
1877
2166
|
<A, E, R, I extends Input, B, E2, R2, I2 extends Input, const Rg extends Range = { readonly min: 0 }>(
|
|
1878
2167
|
self: Parser<A, E, R, I>,
|
|
1879
2168
|
end: Parser<B, E2, R2, I2>,
|
|
1880
2169
|
range?: Rg
|
|
1881
2170
|
): 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
|
-
|
|
2171
|
+
} = /*#__PURE__*/ dual(
|
|
2172
|
+
isTwoParserArgs,
|
|
2173
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
2174
|
+
self: Parser<A, E, R, I>,
|
|
2175
|
+
end: Parser<B, E2, R2, I2>,
|
|
2176
|
+
range?: Range
|
|
2177
|
+
): Parser<[Array<A>, B], E | E2, R | R2, I & I2> => {
|
|
2178
|
+
const [min, max] = normalizeRange(range)
|
|
2179
|
+
const step = self.step
|
|
2180
|
+
const endStep = end.step
|
|
2181
|
+
return described(
|
|
2182
|
+
(state) => {
|
|
2183
|
+
const acc: Array<A> = []
|
|
2184
|
+
while (true) {
|
|
2185
|
+
const start = state.pos
|
|
2186
|
+
let endFailure: Failure | undefined
|
|
2187
|
+
if (acc.length >= min) {
|
|
2188
|
+
const b = endStep(state)
|
|
2189
|
+
if (b !== Fail) return [acc, b]
|
|
2190
|
+
if (state.mode !== "Backtrack") return Fail
|
|
2191
|
+
endFailure = state.failure
|
|
2192
|
+
state.pos = start
|
|
2193
|
+
if (acc.length >= max) return Fail
|
|
2194
|
+
}
|
|
2195
|
+
const a = step(state)
|
|
2196
|
+
if (a === Fail) {
|
|
2197
|
+
if (endFailure !== undefined && state.mode === "Backtrack") {
|
|
2198
|
+
state.failWith("Backtrack", mergeFailures(endFailure, state.failure))
|
|
2199
|
+
}
|
|
2200
|
+
return Fail
|
|
2201
|
+
}
|
|
2202
|
+
if (state.pos === start) return assertConsumes(state, "repeatTill")
|
|
2203
|
+
acc.push(a)
|
|
1907
2204
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
2205
|
+
},
|
|
2206
|
+
"repeatTill",
|
|
2207
|
+
{ _tag: "RepeatTill", self, end, ...bounds(range) }
|
|
2208
|
+
)
|
|
2209
|
+
}
|
|
2210
|
+
)
|
|
2211
|
+
|
|
2212
|
+
/** How far `separated` got: the elements so far, and where the next separator starts. */
|
|
2213
|
+
interface SeparatedCheckpoint<A> {
|
|
2214
|
+
readonly acc: Array<A>
|
|
2215
|
+
readonly pos: number
|
|
2216
|
+
}
|
|
1915
2217
|
|
|
1916
2218
|
/**
|
|
1917
2219
|
* Applies `self` repeatedly, separated by `separator`, collecting the
|
|
@@ -1929,12 +2231,6 @@ export const repeatTill: {
|
|
|
1929
2231
|
* @since 0.1.0
|
|
1930
2232
|
* @category repetition
|
|
1931
2233
|
*/
|
|
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
2234
|
export const separated: {
|
|
1939
2235
|
<S, E2, R2, I2 extends Input, const Rg extends Range = { readonly min: 0 }>(
|
|
1940
2236
|
separator: Parser<S, E2, R2, I2>,
|
|
@@ -1945,64 +2241,72 @@ export const separated: {
|
|
|
1945
2241
|
separator: Parser<S, E2, R2, I2>,
|
|
1946
2242
|
range?: Rg
|
|
1947
2243
|
): 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>)
|
|
2244
|
+
} = /*#__PURE__*/ dual(
|
|
2245
|
+
isTwoParserArgs,
|
|
2246
|
+
<A, E, R, I extends Input, S, E2, R2, I2 extends Input>(
|
|
2247
|
+
self: Parser<A, E, R, I>,
|
|
2248
|
+
separator: Parser<S, E2, R2, I2>,
|
|
2249
|
+
range?: Range
|
|
2250
|
+
): Parser<Array<A>, E | E2, R | R2, I & I2> => {
|
|
2251
|
+
const [min, max] = normalizeRange(range)
|
|
2252
|
+
const step = self.step
|
|
2253
|
+
const sepStep = separator.step
|
|
2254
|
+
const checkLoop = max === Infinity
|
|
2255
|
+
const key = {}
|
|
2256
|
+
return described(
|
|
2257
|
+
(state) => {
|
|
2258
|
+
const entry = state.pos
|
|
2259
|
+
let acc: Array<A>
|
|
2260
|
+
const resumed =
|
|
2261
|
+
state.resume === undefined ? undefined : (Resume.take(state, key, entry) as SeparatedCheckpoint<A>)
|
|
2262
|
+
if (resumed instanceof Resume.Done) {
|
|
2263
|
+
state.pos = resumed.pos
|
|
2264
|
+
return resumed.value as Array<A>
|
|
1986
2265
|
}
|
|
1987
|
-
if (
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2266
|
+
if (resumed !== undefined) {
|
|
2267
|
+
acc = resumed.acc
|
|
2268
|
+
state.pos = resumed.pos
|
|
2269
|
+
} else {
|
|
2270
|
+
acc = []
|
|
2271
|
+
if (max === 0) return acc
|
|
2272
|
+
const start = state.pos
|
|
2273
|
+
const first = step(state)
|
|
2274
|
+
if (first === Fail) {
|
|
2275
|
+
if (state.mode !== "Backtrack" || min > 0) return Fail
|
|
2276
|
+
recover(state, start)
|
|
2277
|
+
return acc
|
|
2278
|
+
}
|
|
2279
|
+
acc.push(first)
|
|
2280
|
+
}
|
|
2281
|
+
while (acc.length < max) {
|
|
2282
|
+
const start = state.pos
|
|
2283
|
+
if (sepStep(state) === Fail) {
|
|
2284
|
+
if (state.mode === "Incomplete" && state.resume !== undefined) {
|
|
2285
|
+
Resume.save(state, key, entry, { acc, pos: start } satisfies SeparatedCheckpoint<A>)
|
|
2286
|
+
}
|
|
2287
|
+
if (state.mode !== "Backtrack" || acc.length < min) return Fail
|
|
2288
|
+
recover(state, start)
|
|
2289
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
2290
|
+
}
|
|
2291
|
+
if (checkLoop && state.pos === start) return assertConsumes(state, "separated")
|
|
2292
|
+
const a = step(state)
|
|
2293
|
+
if (a === Fail) {
|
|
2294
|
+
if (state.mode === "Incomplete" && state.resume !== undefined) {
|
|
2295
|
+
Resume.save(state, key, entry, { acc, pos: start } satisfies SeparatedCheckpoint<A>)
|
|
2296
|
+
}
|
|
2297
|
+
if (state.mode !== "Backtrack" || acc.length < min) return Fail
|
|
2298
|
+
state.pos = start
|
|
2299
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
2300
|
+
}
|
|
2301
|
+
acc.push(a)
|
|
1996
2302
|
}
|
|
1997
|
-
if (state.mode !== "Backtrack" || acc.length < min) return Fail
|
|
1998
|
-
state.pos = start
|
|
1999
2303
|
return Resume.done(state, key, entry, resumed !== undefined, acc)
|
|
2000
|
-
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
}
|
|
2005
|
-
|
|
2304
|
+
},
|
|
2305
|
+
"separated",
|
|
2306
|
+
{ _tag: "Separated", self, separator, ...bounds(range) }
|
|
2307
|
+
)
|
|
2308
|
+
}
|
|
2309
|
+
)
|
|
2006
2310
|
|
|
2007
2311
|
/**
|
|
2008
2312
|
* Parses one or more `self` separated by `separator`, folding them from the
|
|
@@ -2033,41 +2337,45 @@ export const separatedFoldl1 = <A, E, R, I extends Input, S, E2, R2, I2 extends
|
|
|
2033
2337
|
const step = self.step
|
|
2034
2338
|
const sepStep = separator.step
|
|
2035
2339
|
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)
|
|
2340
|
+
return described(
|
|
2341
|
+
(state) => {
|
|
2342
|
+
const entry = state.pos
|
|
2343
|
+
const resumed = state.resume === undefined ? undefined : (Resume.take(state, key, entry) as FoldCheckpoint<A>)
|
|
2344
|
+
let acc: A | Fail
|
|
2345
|
+
if (resumed instanceof Resume.Done) {
|
|
2346
|
+
state.pos = resumed.pos
|
|
2347
|
+
return resumed.value as A
|
|
2059
2348
|
}
|
|
2060
|
-
if (
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
return Resume.done(state, key, entry, resumed !== undefined, acc as A)
|
|
2349
|
+
if (resumed !== undefined) {
|
|
2350
|
+
acc = resumed.acc
|
|
2351
|
+
state.pos = resumed.pos
|
|
2352
|
+
} else {
|
|
2353
|
+
acc = step(state)
|
|
2354
|
+
if (acc === Fail) return Fail
|
|
2067
2355
|
}
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2356
|
+
while (true) {
|
|
2357
|
+
const start = state.pos
|
|
2358
|
+
const s = sepStep(state)
|
|
2359
|
+
if (s === Fail) {
|
|
2360
|
+
if (state.mode === "Incomplete" && state.resume !== undefined) saveFold(state, key, entry, acc, start)
|
|
2361
|
+
if (state.mode !== "Backtrack") return Fail
|
|
2362
|
+
recover(state, start)
|
|
2363
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc as A)
|
|
2364
|
+
}
|
|
2365
|
+
if (state.pos === start) return assertConsumes(state, "separatedFoldl1")
|
|
2366
|
+
const a = step(state)
|
|
2367
|
+
if (a === Fail) {
|
|
2368
|
+
if (state.mode === "Incomplete" && state.resume !== undefined) saveFold(state, key, entry, acc, start)
|
|
2369
|
+
if (state.mode !== "Backtrack") return Fail
|
|
2370
|
+
state.pos = start
|
|
2371
|
+
return Resume.done(state, key, entry, resumed !== undefined, acc as A)
|
|
2372
|
+
}
|
|
2373
|
+
acc = op(acc, s, a)
|
|
2374
|
+
}
|
|
2375
|
+
},
|
|
2376
|
+
"separatedFoldl1",
|
|
2377
|
+
{ _tag: "SeparatedFold", self, separator, op, right: false }
|
|
2378
|
+
)
|
|
2071
2379
|
}
|
|
2072
2380
|
|
|
2073
2381
|
/**
|
|
@@ -2086,35 +2394,39 @@ export const separatedFoldr1 = <A, E, R, I extends Input, S, E2, R2, I2 extends
|
|
|
2086
2394
|
): Parser<A, E | E2, R | R2, I & I2> => {
|
|
2087
2395
|
const step = self.step
|
|
2088
2396
|
const sepStep = separator.step
|
|
2089
|
-
return described(
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
if (
|
|
2099
|
-
|
|
2100
|
-
|
|
2397
|
+
return described(
|
|
2398
|
+
(state) => {
|
|
2399
|
+
const first = step(state)
|
|
2400
|
+
if (first === Fail) return Fail
|
|
2401
|
+
const values: Array<A> = [first]
|
|
2402
|
+
const seps: Array<S> = []
|
|
2403
|
+
while (true) {
|
|
2404
|
+
const start = state.pos
|
|
2405
|
+
const s = sepStep(state)
|
|
2406
|
+
if (s === Fail) {
|
|
2407
|
+
if (state.mode !== "Backtrack") return Fail
|
|
2408
|
+
recover(state, start)
|
|
2409
|
+
break
|
|
2410
|
+
}
|
|
2411
|
+
if (state.pos === start) return assertConsumes(state, "separatedFoldr1")
|
|
2412
|
+
const a = step(state)
|
|
2413
|
+
if (a === Fail) {
|
|
2414
|
+
if (state.mode !== "Backtrack") return Fail
|
|
2415
|
+
state.pos = start
|
|
2416
|
+
break
|
|
2417
|
+
}
|
|
2418
|
+
seps.push(s)
|
|
2419
|
+
values.push(a)
|
|
2101
2420
|
}
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
if (state.mode !== "Backtrack") return Fail
|
|
2106
|
-
state.pos = start
|
|
2107
|
-
break
|
|
2421
|
+
let acc = values[values.length - 1] as A
|
|
2422
|
+
for (let i = seps.length - 1; i >= 0; i--) {
|
|
2423
|
+
acc = op(values[i] as A, seps[i] as S, acc)
|
|
2108
2424
|
}
|
|
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 })
|
|
2425
|
+
return acc
|
|
2426
|
+
},
|
|
2427
|
+
"separatedFoldr1",
|
|
2428
|
+
{ _tag: "SeparatedFold", self, separator, op, right: true }
|
|
2429
|
+
)
|
|
2118
2430
|
}
|
|
2119
2431
|
|
|
2120
2432
|
// -----------------------------------------------------------------------------
|
|
@@ -2173,22 +2485,29 @@ export const provideService: {
|
|
|
2173
2485
|
key: Context.Key<Id, S>,
|
|
2174
2486
|
service: NoInfer<S>
|
|
2175
2487
|
): 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
|
-
|
|
2488
|
+
} = /*#__PURE__*/ dual(
|
|
2489
|
+
3,
|
|
2490
|
+
<A, E, R, I extends Input, Id, S>(
|
|
2491
|
+
self: Parser<A, E, R, I>,
|
|
2492
|
+
key: Context.Key<Id, S>,
|
|
2493
|
+
service: S
|
|
2494
|
+
): Parser<A, E, Exclude<R, Id>, I> => {
|
|
2495
|
+
const step = self.step
|
|
2496
|
+
return described(
|
|
2497
|
+
(state) => {
|
|
2498
|
+
const prev = state.context
|
|
2499
|
+
state.context = Context.add(prev, key, service) as Context.Context<never>
|
|
2500
|
+
try {
|
|
2501
|
+
return step(state)
|
|
2502
|
+
} finally {
|
|
2503
|
+
state.context = prev
|
|
2504
|
+
}
|
|
2505
|
+
},
|
|
2506
|
+
self.name,
|
|
2507
|
+
{ _tag: "Provide", self }
|
|
2508
|
+
)
|
|
2509
|
+
}
|
|
2510
|
+
)
|
|
2192
2511
|
|
|
2193
2512
|
/**
|
|
2194
2513
|
* Provides a context of services to a parser.
|
|
@@ -2204,21 +2523,28 @@ export const provide: {
|
|
|
2204
2523
|
self: Parser<A, E, R, I>,
|
|
2205
2524
|
context: Context.Context<R2>
|
|
2206
2525
|
): Parser<A, E, Exclude<R, R2>, I>
|
|
2207
|
-
} = dual(
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
const
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2526
|
+
} = /*#__PURE__*/ dual(
|
|
2527
|
+
2,
|
|
2528
|
+
<A, E, R, I extends Input, R2>(
|
|
2529
|
+
self: Parser<A, E, R, I>,
|
|
2530
|
+
context: Context.Context<R2>
|
|
2531
|
+
): Parser<A, E, Exclude<R, R2>, I> => {
|
|
2532
|
+
const step = self.step
|
|
2533
|
+
return described(
|
|
2534
|
+
(state) => {
|
|
2535
|
+
const prev = state.context
|
|
2536
|
+
state.context = Context.merge(prev, context) as Context.Context<never>
|
|
2537
|
+
try {
|
|
2538
|
+
return step(state)
|
|
2539
|
+
} finally {
|
|
2540
|
+
state.context = prev
|
|
2541
|
+
}
|
|
2542
|
+
},
|
|
2543
|
+
self.name,
|
|
2544
|
+
{ _tag: "Provide", self }
|
|
2545
|
+
)
|
|
2546
|
+
}
|
|
2547
|
+
)
|
|
2222
2548
|
|
|
2223
2549
|
// -----------------------------------------------------------------------------
|
|
2224
2550
|
// Error recovery
|
|
@@ -2242,25 +2568,33 @@ export const resumeAfter: {
|
|
|
2242
2568
|
self: Parser<A, E, R, I>,
|
|
2243
2569
|
recover: Parser<B, E2, R2, I2>
|
|
2244
2570
|
): 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
|
-
|
|
2571
|
+
} = /*#__PURE__*/ dual(
|
|
2572
|
+
2,
|
|
2573
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
2574
|
+
self: Parser<A, E, R, I>,
|
|
2575
|
+
recover: Parser<B, E2, R2, I2>
|
|
2576
|
+
): Parser<Option.Option<A>, E | E2, R | R2, I & I2> => {
|
|
2577
|
+
const step = self.step
|
|
2578
|
+
const recoverStep = recover.step
|
|
2579
|
+
return described(
|
|
2580
|
+
(state) => {
|
|
2581
|
+
const start = state.pos
|
|
2582
|
+
const a = step(state)
|
|
2583
|
+
if (a !== Fail) return Option.some(a)
|
|
2584
|
+
if (state.recovered === undefined || state.mode === "Incomplete") return Fail
|
|
2585
|
+
const failure = state.failure
|
|
2586
|
+
const mode = state.mode
|
|
2587
|
+
state.pos = start
|
|
2588
|
+
if (recoverStep(state) === Fail) return state.failWith(mode, failure)
|
|
2589
|
+
state.recovered.push(failure)
|
|
2590
|
+
state.syntax?.skipped(start, failure, mode)
|
|
2591
|
+
return Option.none()
|
|
2592
|
+
},
|
|
2593
|
+
self.name,
|
|
2594
|
+
{ _tag: "ResumeAfter", self, recover }
|
|
2595
|
+
)
|
|
2596
|
+
}
|
|
2597
|
+
)
|
|
2264
2598
|
|
|
2265
2599
|
/**
|
|
2266
2600
|
* Error recovery: if the parser fails, record the failure, skip input with
|
|
@@ -2280,26 +2614,34 @@ export const retryAfter: {
|
|
|
2280
2614
|
self: Parser<A, E, R, I>,
|
|
2281
2615
|
recover: Parser<B, E2, R2, I2>
|
|
2282
2616
|
): 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
|
-
|
|
2617
|
+
} = /*#__PURE__*/ dual(
|
|
2618
|
+
2,
|
|
2619
|
+
<A, E, R, I extends Input, B, E2, R2, I2 extends Input>(
|
|
2620
|
+
self: Parser<A, E, R, I>,
|
|
2621
|
+
recover: Parser<B, E2, R2, I2>
|
|
2622
|
+
): Parser<A, E | E2, R | R2, I & I2> => {
|
|
2623
|
+
const step = self.step
|
|
2624
|
+
const recoverStep = recover.step
|
|
2625
|
+
return described(
|
|
2626
|
+
(state) => {
|
|
2627
|
+
while (true) {
|
|
2628
|
+
const start = state.pos
|
|
2629
|
+
const a = step(state)
|
|
2630
|
+
if (a !== Fail) return a
|
|
2631
|
+
if (state.recovered === undefined || state.mode === "Incomplete") return Fail
|
|
2632
|
+
const failure = state.failure
|
|
2633
|
+
const mode = state.mode
|
|
2634
|
+
state.pos = start
|
|
2635
|
+
if (recoverStep(state) === Fail || state.pos === start) return state.failWith(mode, failure)
|
|
2636
|
+
state.recovered.push(failure)
|
|
2637
|
+
state.syntax?.skipped(start, failure, mode)
|
|
2638
|
+
}
|
|
2639
|
+
},
|
|
2640
|
+
self.name,
|
|
2641
|
+
{ _tag: "RetryAfter", self, recover }
|
|
2642
|
+
)
|
|
2643
|
+
}
|
|
2644
|
+
)
|
|
2303
2645
|
|
|
2304
2646
|
// -----------------------------------------------------------------------------
|
|
2305
2647
|
// Debugging
|
|
@@ -2317,33 +2659,37 @@ export const retryAfter: {
|
|
|
2317
2659
|
export const trace: {
|
|
2318
2660
|
(name: string): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
2319
2661
|
<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> => {
|
|
2662
|
+
} = /*#__PURE__*/ dual(2, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, name: string): Parser<A, E, R, I> => {
|
|
2321
2663
|
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
|
-
|
|
2664
|
+
return described(
|
|
2665
|
+
(state) => {
|
|
2666
|
+
const tracer = state.tracer
|
|
2667
|
+
if (tracer === undefined) return step(state)
|
|
2668
|
+
const start = state.pos
|
|
2669
|
+
const depth = state.depth
|
|
2670
|
+
tracer({ _tag: "Enter", name, depth, offset: start, state })
|
|
2671
|
+
state.depth = depth + 1
|
|
2672
|
+
const a = step(state)
|
|
2673
|
+
state.depth = depth
|
|
2674
|
+
tracer({
|
|
2675
|
+
_tag: "Exit",
|
|
2676
|
+
name,
|
|
2677
|
+
depth,
|
|
2678
|
+
offset: start,
|
|
2679
|
+
endOffset: state.pos,
|
|
2680
|
+
result: a === Fail ? state.mode : "Ok",
|
|
2681
|
+
state
|
|
2682
|
+
})
|
|
2683
|
+
return a
|
|
2684
|
+
},
|
|
2685
|
+
name,
|
|
2686
|
+
{ _tag: "Trace", self, name }
|
|
2687
|
+
)
|
|
2342
2688
|
})
|
|
2343
2689
|
|
|
2344
2690
|
const preview = (state: State<any>, offset: number): string => {
|
|
2345
2691
|
const input = state.input
|
|
2346
|
-
if (
|
|
2692
|
+
if (Predicate.isString(input)) {
|
|
2347
2693
|
const s = input.slice(offset, offset + 24)
|
|
2348
2694
|
return JSON.stringify(s) + (offset + 24 < input.length ? "…" : "∅")
|
|
2349
2695
|
}
|
|
@@ -2371,88 +2717,28 @@ export const consoleTracer = (event: TraceEvent): void => {
|
|
|
2371
2717
|
}
|
|
2372
2718
|
|
|
2373
2719
|
// -----------------------------------------------------------------------------
|
|
2374
|
-
//
|
|
2720
|
+
// Compiled parsers
|
|
2375
2721
|
// -----------------------------------------------------------------------------
|
|
2376
2722
|
|
|
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
2723
|
/** Returned by {@link runCompiled} when there is no compiled form to run. */
|
|
2444
|
-
const NotCompiled: unique symbol = Symbol("NotCompiled")
|
|
2724
|
+
const NotCompiled: unique symbol = /*#__PURE__*/ Symbol("NotCompiled")
|
|
2445
2725
|
|
|
2446
2726
|
/**
|
|
2447
2727
|
* Runs the compiled form of `self`, if it has one: returns its value, or
|
|
2448
2728
|
* `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
|
-
|
|
2729
|
+
* input), in which case the state must be thrown away. `resumable` selects
|
|
2730
|
+
* the build that handles partial input.
|
|
2731
|
+
*/
|
|
2732
|
+
const runCompiled = <I extends Input>(
|
|
2733
|
+
self: Parser.Any,
|
|
2734
|
+
state: State<I>,
|
|
2735
|
+
whole: boolean,
|
|
2736
|
+
resumable = false
|
|
2737
|
+
): unknown => {
|
|
2452
2738
|
if (state.tracer !== undefined || state.recovered !== undefined) return NotCompiled
|
|
2453
|
-
const step =
|
|
2739
|
+
const step = Registry.stepFor(self, state, resumable)
|
|
2454
2740
|
if (step === undefined) return NotCompiled
|
|
2455
|
-
const a = step
|
|
2741
|
+
const a = Stack.run(step, state)
|
|
2456
2742
|
if (a === Fail || (whole && state.pos < state.end)) return Fail
|
|
2457
2743
|
return a
|
|
2458
2744
|
}
|
|
@@ -2473,6 +2759,19 @@ export interface ParseOptions {
|
|
|
2473
2759
|
* {@link consoleTracer}.
|
|
2474
2760
|
*/
|
|
2475
2761
|
readonly trace?: boolean | ((event: TraceEvent) => void) | undefined
|
|
2762
|
+
/**
|
|
2763
|
+
* Where to start parsing (default `0`): in code units for strings, bytes
|
|
2764
|
+
* for byte input and elements for arrays. The result is that of parsing
|
|
2765
|
+
* `input.slice(offset)`, but without copying the input, and every offset
|
|
2766
|
+
* (`parsePartial`'s `Done`, `location`, spans, `ParseError.offset` and its
|
|
2767
|
+
* line and column) is a position in the whole input. This is what an
|
|
2768
|
+
* incremental driver, such as a lexer reading one token at a time from a
|
|
2769
|
+
* buffer, needs: compiled parsers run compiled from any offset.
|
|
2770
|
+
*
|
|
2771
|
+
* Throws a `RangeError` unless it is an integer from `0` to the input's
|
|
2772
|
+
* length.
|
|
2773
|
+
*/
|
|
2774
|
+
readonly offset?: number | undefined
|
|
2476
2775
|
}
|
|
2477
2776
|
|
|
2478
2777
|
/**
|
|
@@ -2490,7 +2789,11 @@ const makeState = <I extends Input>(
|
|
|
2490
2789
|
options: (ParseOptions & { readonly context?: Context.Context<any> }) | undefined,
|
|
2491
2790
|
partial: boolean
|
|
2492
2791
|
): State<I> => {
|
|
2493
|
-
const
|
|
2792
|
+
const offset = options?.offset
|
|
2793
|
+
const state = new State(input, { partial, context: options?.context, offset })
|
|
2794
|
+
if (offset !== undefined && !(Number.isInteger(offset) && offset >= 0 && offset <= state.end)) {
|
|
2795
|
+
throw new RangeError(`Invalid offset ${offset} for an input of length ${state.end}`)
|
|
2796
|
+
}
|
|
2494
2797
|
const t = options?.trace
|
|
2495
2798
|
if (t !== undefined && t !== false) state.tracer = t === true ? consoleTracer : t
|
|
2496
2799
|
return state
|
|
@@ -2517,7 +2820,7 @@ const runComplete = <A, E, R, I extends Input>(
|
|
|
2517
2820
|
self: Parser<A, E, R, I>,
|
|
2518
2821
|
state: State<I>
|
|
2519
2822
|
): Result.Result<A, ParseError.ParseError<E>> => {
|
|
2520
|
-
const a = self.step
|
|
2823
|
+
const a = Stack.run(self.step, state)
|
|
2521
2824
|
if (a === Fail) return Result.fail(toError(state))
|
|
2522
2825
|
if (state.pos < state.end) {
|
|
2523
2826
|
state.backtrack("Eof", expectedEof)
|
|
@@ -2567,7 +2870,11 @@ export const parse: {
|
|
|
2567
2870
|
*/
|
|
2568
2871
|
export const parseSync: {
|
|
2569
2872
|
<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>(
|
|
2873
|
+
<A, E, R, I extends Input>(
|
|
2874
|
+
self: Parser<A, E, R, I>,
|
|
2875
|
+
input: NoInfer<Source<I>>,
|
|
2876
|
+
options: ParseOptionsWithContext<R>
|
|
2877
|
+
): A
|
|
2571
2878
|
} = <A, E, R, I extends Input>(
|
|
2572
2879
|
self: Parser<A, E, R, I>,
|
|
2573
2880
|
input: I | Source<I>,
|
|
@@ -2583,6 +2890,10 @@ export const parseSync: {
|
|
|
2583
2890
|
* input along with the output, nom-style (winnow's `parse_peek`, nom's
|
|
2584
2891
|
* `IResult`).
|
|
2585
2892
|
*
|
|
2893
|
+
* The parser ended at offset `input.length - remaining.length`, which is
|
|
2894
|
+
* how a caller running from an `offset` (see {@link ParseOptions}) finds
|
|
2895
|
+
* where to continue.
|
|
2896
|
+
*
|
|
2586
2897
|
* @since 0.1.0
|
|
2587
2898
|
* @category running
|
|
2588
2899
|
*/
|
|
@@ -2608,7 +2919,7 @@ export const parsePeek: {
|
|
|
2608
2919
|
return Result.succeed([state.slice(state.pos, state.end), compiled as A])
|
|
2609
2920
|
}
|
|
2610
2921
|
if (compiled === Fail) state = makeState(input, options, false)
|
|
2611
|
-
const a = self.step
|
|
2922
|
+
const a = Stack.run(self.step, state)
|
|
2612
2923
|
if (a === Fail) return Result.fail(toError(state))
|
|
2613
2924
|
return Result.succeed([state.slice(state.pos, state.end), a])
|
|
2614
2925
|
}
|
|
@@ -2633,7 +2944,14 @@ export type PartialResult<A> =
|
|
|
2633
2944
|
* of failing or succeeding early.
|
|
2634
2945
|
*
|
|
2635
2946
|
* The parser does not have to consume the whole input; the returned
|
|
2636
|
-
* `offset` says
|
|
2947
|
+
* `offset` says where it stopped. It is a position in the whole input, so
|
|
2948
|
+
* with the `offset` option (see {@link ParseOptions}) it is where the next
|
|
2949
|
+
* parse starts.
|
|
2950
|
+
*
|
|
2951
|
+
* A parser compiled with the `Compiler` module runs compiled, with a build
|
|
2952
|
+
* that handles partial input. When it fails or needs more input, it runs again
|
|
2953
|
+
* interpreted, so `Incomplete`'s `needed` and every `ParseError` are the
|
|
2954
|
+
* interpreter's.
|
|
2637
2955
|
*
|
|
2638
2956
|
* @example
|
|
2639
2957
|
* ```ts
|
|
@@ -2664,8 +2982,14 @@ export const parsePartial: {
|
|
|
2664
2982
|
input: I | Source<I>,
|
|
2665
2983
|
options?: ParseOptions & { readonly context?: Context.Context<R> }
|
|
2666
2984
|
): Result.Result<PartialResult<A>, ParseError.ParseError<E>> => {
|
|
2667
|
-
|
|
2668
|
-
const
|
|
2985
|
+
let state = makeState(input, options, true)
|
|
2986
|
+
const compiled = runCompiled(self, state, false, true)
|
|
2987
|
+
if (compiled !== NotCompiled && compiled !== Fail) {
|
|
2988
|
+
return Result.succeed({ _tag: "Done", value: compiled as A, offset: state.pos })
|
|
2989
|
+
}
|
|
2990
|
+
// Re-run interpreted for `needed` and the diagnostics
|
|
2991
|
+
if (compiled === Fail) state = makeState(input, options, true)
|
|
2992
|
+
const a = Stack.run(self.step, state)
|
|
2669
2993
|
if (a !== Fail) return Result.succeed({ _tag: "Done", value: a, offset: state.pos })
|
|
2670
2994
|
if (state.mode === "Incomplete") {
|
|
2671
2995
|
const needed = state.failure.needed
|
|
@@ -2697,11 +3021,87 @@ export const parseEffect = <A, E, R, I extends Input>(
|
|
|
2697
3021
|
input: NoInfer<Source<I>>,
|
|
2698
3022
|
options?: ParseOptions
|
|
2699
3023
|
): Effect.Effect<A, ParseError.ParseError<E>, R> =>
|
|
2700
|
-
Effect.flatMap(
|
|
2701
|
-
Effect.context
|
|
2702
|
-
(context) => Effect.fromResult(parseComplete(self, input, { ...options, context }))
|
|
3024
|
+
Effect.flatMap(Effect.context<R>(), (context) =>
|
|
3025
|
+
Effect.fromResult(parseComplete(self, input, { ...options, context }))
|
|
2703
3026
|
)
|
|
2704
3027
|
|
|
3028
|
+
/**
|
|
3029
|
+
* Runs a parser on a state you own, from `state.pos`, and returns its output
|
|
3030
|
+
* or {@link Fail}: like calling `self.step(state)`, but using the parser's
|
|
3031
|
+
* compiled form when it has one (see the `Compiler` module). This is the
|
|
3032
|
+
* runner for drivers that make many small runs over one buffer, such as a
|
|
3033
|
+
* lexer reading one token at a time: keep one `Input.State` and
|
|
3034
|
+
* `reset` it (`Input.State.reset`) before each run, and no run allocates a
|
|
3035
|
+
* state, a `Result` or a slice.
|
|
3036
|
+
*
|
|
3037
|
+
* On success the cursor is where the parser stopped. On failure the state
|
|
3038
|
+
* holds the interpreter's failure (`mode`, `failure`, and what
|
|
3039
|
+
* `reportedFailure()` returns): a compiled run that fails is thrown away and
|
|
3040
|
+
* the parser's step runs again from the same position. A partial state
|
|
3041
|
+
* (`partial: true`) runs the compiled build that handles partial input, so
|
|
3042
|
+
* `Incomplete` is reported as the step would report it. Under a tracer,
|
|
3043
|
+
* with recovery on or inside a `Syntax` parse, the step runs interpreted.
|
|
3044
|
+
*
|
|
3045
|
+
* A driver that only needs to know *that* a parser failed (it tries
|
|
3046
|
+
* another, or skips a character) can pass `{ diagnostics: false }` to skip
|
|
3047
|
+
* the interpreted re-run; see {@link RunOptions}.
|
|
3048
|
+
*
|
|
3049
|
+
* Compiled code records no hints or furthest failure when it succeeds, so
|
|
3050
|
+
* a later failure on the same state can list fewer expectations than one
|
|
3051
|
+
* after interpreted runs would: reset the state between runs (as above) and
|
|
3052
|
+
* its errors are the ones {@link parse} reports. Deep nesting fails with an
|
|
3053
|
+
* unrecoverable `TooDeep` failure instead of throwing, as in the other
|
|
3054
|
+
* runners.
|
|
3055
|
+
*
|
|
3056
|
+
* @example
|
|
3057
|
+
* ```ts
|
|
3058
|
+
* import { Ascii, Compiler, Input, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
3059
|
+
*
|
|
3060
|
+
* const token = Compiler.jit(Parser.preceded(Ascii.space0, Parser.alt(Ascii.alpha1, Token.oneOf("+-"))))
|
|
3061
|
+
*
|
|
3062
|
+
* const tokens = (text: string): Array<string> => {
|
|
3063
|
+
* const state = new Input.State(text)
|
|
3064
|
+
* const out: Array<string> = []
|
|
3065
|
+
* while (state.pos < state.end) {
|
|
3066
|
+
* const t = Parser.run(token, state.reset(state.pos))
|
|
3067
|
+
* if (t === Input.Fail) break
|
|
3068
|
+
* out.push(t)
|
|
3069
|
+
* }
|
|
3070
|
+
* return out
|
|
3071
|
+
* }
|
|
3072
|
+
*
|
|
3073
|
+
* tokens("a + b") // ["a", "+", "b"]
|
|
3074
|
+
* ```
|
|
3075
|
+
*
|
|
3076
|
+
* @since 0.2.0
|
|
3077
|
+
* @category running
|
|
3078
|
+
*/
|
|
3079
|
+
export const run = <A, E, R, I extends Input>(
|
|
3080
|
+
self: Parser<A, E, R, I>,
|
|
3081
|
+
state: State<I>,
|
|
3082
|
+
options?: RunOptions
|
|
3083
|
+
): A | Fail => Run.runOn(self, self.step, state, options?.diagnostics !== false)
|
|
3084
|
+
|
|
3085
|
+
/**
|
|
3086
|
+
* Options for {@link run}.
|
|
3087
|
+
*
|
|
3088
|
+
* @since 0.2.0
|
|
3089
|
+
* @category running
|
|
3090
|
+
*/
|
|
3091
|
+
export interface RunOptions {
|
|
3092
|
+
/**
|
|
3093
|
+
* Whether a failure records the interpreter's diagnostics (default
|
|
3094
|
+
* `true`). With `false`, a compiled run that fails is not run again
|
|
3095
|
+
* interpreted: the state's `mode` (`Backtrack`, `Cut` or `Incomplete`)
|
|
3096
|
+
* is set and the cursor is back where the run started, but `failure`,
|
|
3097
|
+
* hints and the furthest failure are left as they were. For drivers that
|
|
3098
|
+
* try a parser and move on when it fails, without reporting why, this
|
|
3099
|
+
* halves the cost of each failure. Parsers that run interpreted record
|
|
3100
|
+
* their diagnostics either way.
|
|
3101
|
+
*/
|
|
3102
|
+
readonly diagnostics?: boolean | undefined
|
|
3103
|
+
}
|
|
3104
|
+
|
|
2705
3105
|
/**
|
|
2706
3106
|
* The outcome of {@link parseRecoverable}.
|
|
2707
3107
|
*
|