@thomasfosterau/effect-parse 0.4.1 → 0.6.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/CHANGELOG.md +202 -0
- package/README.md +56 -14
- package/dist/Ascii.d.ts +11 -4
- package/dist/Ascii.d.ts.map +1 -1
- package/dist/Ascii.js +12 -4
- package/dist/Ascii.js.map +1 -1
- package/dist/Binary.d.ts +5 -2
- package/dist/Binary.d.ts.map +1 -1
- package/dist/Binary.js +83 -37
- package/dist/Binary.js.map +1 -1
- package/dist/Bits.d.ts.map +1 -1
- package/dist/Bits.js +11 -4
- package/dist/Bits.js.map +1 -1
- package/dist/Compiler.d.ts +74 -2
- package/dist/Compiler.d.ts.map +1 -1
- package/dist/Compiler.js +78 -1
- package/dist/Compiler.js.map +1 -1
- package/dist/Expression.d.ts.map +1 -1
- package/dist/Expression.js +86 -74
- package/dist/Expression.js.map +1 -1
- package/dist/Input.d.ts +56 -5
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +70 -1
- package/dist/Input.js.map +1 -1
- package/dist/Nom.d.ts +5 -15
- package/dist/Nom.d.ts.map +1 -1
- package/dist/Nom.js.map +1 -1
- package/dist/ParseError.d.ts +69 -11
- package/dist/ParseError.d.ts.map +1 -1
- package/dist/ParseError.js +129 -28
- package/dist/ParseError.js.map +1 -1
- package/dist/Parser.d.ts +375 -29
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +394 -37
- package/dist/Parser.js.map +1 -1
- package/dist/ParserSchema.d.ts.map +1 -1
- package/dist/ParserSchema.js +2 -3
- package/dist/ParserSchema.js.map +1 -1
- package/dist/ParserStream.d.ts +122 -14
- package/dist/ParserStream.d.ts.map +1 -1
- package/dist/ParserStream.js +293 -62
- package/dist/ParserStream.js.map +1 -1
- package/dist/Syntax.d.ts +23 -5
- package/dist/Syntax.d.ts.map +1 -1
- package/dist/Syntax.js +1 -1
- package/dist/Syntax.js.map +1 -1
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +21 -15
- package/dist/Text.js.map +1 -1
- package/dist/Token.d.ts +65 -11
- package/dist/Token.d.ts.map +1 -1
- package/dist/Token.js +73 -26
- package/dist/Token.js.map +1 -1
- package/dist/internal/compiler/closure.d.ts +1 -1
- package/dist/internal/compiler/closure.d.ts.map +1 -1
- package/dist/internal/compiler/closure.js +263 -113
- package/dist/internal/compiler/closure.js.map +1 -1
- package/dist/internal/compiler/entries.d.ts +3 -1
- package/dist/internal/compiler/entries.d.ts.map +1 -1
- package/dist/internal/compiler/entries.js +3 -2
- package/dist/internal/compiler/entries.js.map +1 -1
- package/dist/internal/compiler/first.d.ts.map +1 -1
- package/dist/internal/compiler/first.js +9 -2
- package/dist/internal/compiler/first.js.map +1 -1
- package/dist/internal/compiler/graph.d.ts +39 -0
- package/dist/internal/compiler/graph.d.ts.map +1 -0
- package/dist/internal/compiler/graph.js +78 -0
- package/dist/internal/compiler/graph.js.map +1 -0
- package/dist/internal/compiler/jit.d.ts +5 -0
- package/dist/internal/compiler/jit.d.ts.map +1 -1
- package/dist/internal/compiler/jit.js +208 -106
- package/dist/internal/compiler/jit.js.map +1 -1
- package/dist/internal/compiler/registry.d.ts +11 -3
- package/dist/internal/compiler/registry.d.ts.map +1 -1
- package/dist/internal/compiler/registry.js.map +1 -1
- package/dist/internal/compiler/search.d.ts +32 -0
- package/dist/internal/compiler/search.d.ts.map +1 -0
- package/dist/internal/compiler/search.js +68 -0
- package/dist/internal/compiler/search.js.map +1 -0
- package/dist/internal/compiler/sets.d.ts.map +1 -1
- package/dist/internal/compiler/sets.js +1 -1
- package/dist/internal/compiler/sets.js.map +1 -1
- package/dist/internal/compiler/wasm.d.ts +8 -0
- package/dist/internal/compiler/wasm.d.ts.map +1 -0
- package/dist/internal/compiler/wasm.js +2840 -0
- package/dist/internal/compiler/wasm.js.map +1 -0
- package/dist/internal/compiler/wasmAsm.d.ts +199 -0
- package/dist/internal/compiler/wasmAsm.d.ts.map +1 -0
- package/dist/internal/compiler/wasmAsm.js +427 -0
- package/dist/internal/compiler/wasmAsm.js.map +1 -0
- package/dist/internal/entries.d.ts +3 -1
- package/dist/internal/entries.d.ts.map +1 -1
- package/dist/internal/entries.js.map +1 -1
- package/dist/internal/node.d.ts +77 -3
- package/dist/internal/node.d.ts.map +1 -1
- package/dist/internal/node.js +54 -10
- package/dist/internal/node.js.map +1 -1
- package/dist/internal/numbers.d.ts.map +1 -1
- package/dist/internal/numbers.js.map +1 -1
- package/dist/internal/run.d.ts +14 -0
- package/dist/internal/run.d.ts.map +1 -1
- package/dist/internal/run.js +53 -11
- package/dist/internal/run.js.map +1 -1
- package/dist/internal/stack.d.ts +14 -0
- package/dist/internal/stack.d.ts.map +1 -1
- package/dist/internal/stack.js +24 -2
- package/dist/internal/stack.js.map +1 -1
- package/dist/internal/syntax.d.ts +4 -4
- package/dist/internal/syntax.d.ts.map +1 -1
- package/dist/internal/syntax.js +18 -10
- package/dist/internal/syntax.js.map +1 -1
- package/dist/internal/text.d.ts +32 -0
- package/dist/internal/text.d.ts.map +1 -1
- package/dist/internal/text.js +68 -14
- package/dist/internal/text.js.map +1 -1
- package/dist/internal/tokens.d.ts +20 -0
- package/dist/internal/tokens.d.ts.map +1 -1
- package/dist/internal/tokens.js +72 -39
- package/dist/internal/tokens.js.map +1 -1
- package/dist/internal/tuple.d.ts +6 -0
- package/dist/internal/tuple.d.ts.map +1 -0
- package/dist/internal/tuple.js +170 -0
- package/dist/internal/tuple.js.map +1 -0
- package/package.json +18 -10
- package/src/Ascii.ts +47 -12
- package/src/Binary.ts +174 -73
- package/src/Bits.ts +16 -6
- package/src/Compiler.ts +101 -10
- package/src/Expression.ts +94 -81
- package/src/Input.ts +99 -7
- package/src/Nom.ts +15 -5
- package/src/ParseError.ts +209 -52
- package/src/Parser.ts +684 -143
- package/src/ParserSchema.ts +1 -2
- package/src/ParserStream.ts +361 -68
- package/src/Syntax.ts +60 -36
- package/src/Text.ts +32 -27
- package/src/Token.ts +152 -34
- package/src/internal/compiler/closure.ts +371 -153
- package/src/internal/compiler/entries.ts +4 -2
- package/src/internal/compiler/first.ts +16 -0
- package/src/internal/compiler/graph.ts +96 -0
- package/src/internal/compiler/jit.ts +319 -169
- package/src/internal/compiler/registry.ts +10 -2
- package/src/internal/compiler/search.ts +68 -0
- package/src/internal/compiler/sets.ts +7 -3
- package/src/internal/compiler/wasm.ts +3276 -0
- package/src/internal/compiler/wasmAsm.ts +484 -0
- package/src/internal/entries.ts +8 -2
- package/src/internal/node.ts +103 -7
- package/src/internal/numbers.ts +3 -1
- package/src/internal/run.ts +73 -12
- package/src/internal/stack.ts +25 -1
- package/src/internal/syntax.ts +39 -18
- package/src/internal/text.ts +97 -9
- package/src/internal/tokens.ts +106 -14
- package/src/internal/tuple.ts +141 -0
package/src/Token.ts
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
describeLiteral,
|
|
31
31
|
End,
|
|
32
32
|
indexOf,
|
|
33
|
+
indexOfAny,
|
|
33
34
|
matchLiteral,
|
|
34
35
|
nextIf,
|
|
35
36
|
NoMatch,
|
|
@@ -37,7 +38,7 @@ import {
|
|
|
37
38
|
splitSurrogate
|
|
38
39
|
} from "./internal/tokens.js"
|
|
39
40
|
import type { ErrorKind } from "./ParseError.js"
|
|
40
|
-
import { bounds } from "./internal/node.js"
|
|
41
|
+
import { bounds, checkCount } from "./internal/node.js"
|
|
41
42
|
import type { Parser, Range } from "./Parser.js"
|
|
42
43
|
import { described } from "./Parser.js"
|
|
43
44
|
|
|
@@ -116,12 +117,13 @@ export const codePoints = (
|
|
|
116
117
|
predicate: (codePoint: number) => boolean,
|
|
117
118
|
ranges?: ReadonlyArray<readonly [number, number]>
|
|
118
119
|
): CodePoints =>
|
|
119
|
-
// Wrapped, so the caller's function is left unmarked
|
|
120
|
+
// Wrapped, so the caller's function is left unmarked.
|
|
121
|
+
// SAFETY: `CodePointsBrand` is a declared, phantom key, so the marked function is all a `CodePoints` is at runtime
|
|
120
122
|
codePointPredicate(
|
|
121
123
|
name,
|
|
122
124
|
(c: number): boolean => predicate(c),
|
|
123
125
|
ranges?.map(([from, to]) => [from, to] as const)
|
|
124
|
-
) as
|
|
126
|
+
) as CodePoints
|
|
125
127
|
|
|
126
128
|
/**
|
|
127
129
|
* A set of string tokens: the characters of a string, a range, a predicate,
|
|
@@ -177,6 +179,7 @@ const anyStep = (state: State<Input>): unknown => {
|
|
|
177
179
|
if (pos >= state.end) return state.eoi("Token", expectedAny, 1)
|
|
178
180
|
switch (state.inputKind) {
|
|
179
181
|
case 0: {
|
|
182
|
+
// SAFETY: `inputKind` 0 is set only for a string input
|
|
180
183
|
const s = state.input as string
|
|
181
184
|
if (splitSurrogate(state, pos)) return state.incomplete(1, expectedAny)
|
|
182
185
|
const c = s.charCodeAt(pos)
|
|
@@ -189,13 +192,21 @@ const anyStep = (state: State<Input>): unknown => {
|
|
|
189
192
|
}
|
|
190
193
|
case 1:
|
|
191
194
|
state.pos = pos + 1
|
|
195
|
+
// SAFETY: `inputKind` 1 is set only for a `Uint8Array` input
|
|
192
196
|
return (state.input as Uint8Array)[pos]
|
|
193
197
|
default:
|
|
194
198
|
state.pos = pos + 1
|
|
199
|
+
// SAFETY: `inputKind` 2 is set for every input that is neither a string nor a `Uint8Array`, an array
|
|
195
200
|
return (state.input as ReadonlyArray<unknown>)[pos]
|
|
196
201
|
}
|
|
197
202
|
}
|
|
198
203
|
|
|
204
|
+
/** The parser behind `any` and `anyToken`, on every input kind. */
|
|
205
|
+
const anyInput: Parser<unknown, never, never, Input> = /*#__PURE__*/ described(anyStep, "any", {
|
|
206
|
+
_tag: "Any",
|
|
207
|
+
encoding: undefined
|
|
208
|
+
})
|
|
209
|
+
|
|
199
210
|
/**
|
|
200
211
|
* Matches any single token: a character of a string (winnow's `any`, nom's
|
|
201
212
|
* `anychar`).
|
|
@@ -203,7 +214,9 @@ const anyStep = (state: State<Input>): unknown => {
|
|
|
203
214
|
* @since 0.1.0
|
|
204
215
|
* @category tokens
|
|
205
216
|
*/
|
|
206
|
-
export const any: Parser<string> =
|
|
217
|
+
export const any: Parser<string> =
|
|
218
|
+
// SAFETY: on string input, `anyStep` returns the character (one or two code units) at the position, a string
|
|
219
|
+
anyInput as Parser<string>
|
|
207
220
|
|
|
208
221
|
/**
|
|
209
222
|
* Matches any single token of an input of type `I`.
|
|
@@ -219,7 +232,21 @@ export const any: Parser<string> = /*#__PURE__*/ described(anyStep as any, "any"
|
|
|
219
232
|
* @since 0.1.0
|
|
220
233
|
* @category tokens
|
|
221
234
|
*/
|
|
222
|
-
export const anyToken = <I extends Input = string>(): Parser<Token<NoInfer<I>>, never, never, NoInfer<I>> =>
|
|
235
|
+
export const anyToken = <I extends Input = string>(): Parser<Token<NoInfer<I>>, never, never, NoInfer<I>> =>
|
|
236
|
+
// SAFETY: `anyStep` handles every input kind, returning the token at the position (a character, byte or element)
|
|
237
|
+
anyInput as Parser<Token<NoInfer<I>>, never, never, NoInfer<I>>
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* The overloads of {@link literal}.
|
|
241
|
+
*
|
|
242
|
+
* @since 0.5.0
|
|
243
|
+
* @category tokens
|
|
244
|
+
*/
|
|
245
|
+
export interface LiteralFn {
|
|
246
|
+
<const L extends string>(literal: L): Parser<L, never, never, string>
|
|
247
|
+
(literal: Uint8Array): Parser<Uint8Array, never, never, Uint8Array>
|
|
248
|
+
<const T>(literal: ReadonlyArray<T>): Parser<ReadonlyArray<T>, never, never, ReadonlyArray<T>>
|
|
249
|
+
}
|
|
223
250
|
|
|
224
251
|
/**
|
|
225
252
|
* Matches a literal sequence of tokens (winnow's `literal`, nom's `tag`).
|
|
@@ -237,11 +264,7 @@ export const anyToken = <I extends Input = string>(): Parser<Token<NoInfer<I>>,
|
|
|
237
264
|
* @since 0.1.0
|
|
238
265
|
* @category tokens
|
|
239
266
|
*/
|
|
240
|
-
export const literal:
|
|
241
|
-
<const L extends string>(literal: L): Parser<L, never, never, string>
|
|
242
|
-
(literal: Uint8Array): Parser<Uint8Array, never, never, Uint8Array>
|
|
243
|
-
<const T>(literal: ReadonlyArray<T>): Parser<ReadonlyArray<T>, never, never, ReadonlyArray<T>>
|
|
244
|
-
} = (lit: Input): Parser<any, never, never, any> => literalImpl(lit, false)
|
|
267
|
+
export const literal: LiteralFn = (lit: Input): Parser<any, never, never, any> => literalImpl(lit, false)
|
|
245
268
|
|
|
246
269
|
/** @internal */
|
|
247
270
|
export const literalImpl = (lit: Input, caseless: boolean): Parser<any, never, never, any> => {
|
|
@@ -253,6 +276,7 @@ export const literalImpl = (lit: Input, caseless: boolean): Parser<any, never, n
|
|
|
253
276
|
return described(
|
|
254
277
|
(state: State<Input>) => {
|
|
255
278
|
const pos = state.pos
|
|
279
|
+
// SAFETY: `literalKind` 0 is set only for a string literal
|
|
256
280
|
const l = literalKind === 0 && state.inputKind === 1 ? (asBytes ??= new TextEncoder().encode(lit as string)) : lit
|
|
257
281
|
const len = l.length
|
|
258
282
|
const r = matchLiteral(state, l, caseless)
|
|
@@ -295,6 +319,7 @@ export const oneOf = <I extends Input = string>(
|
|
|
295
319
|
const t = nextIf(state, m, false)
|
|
296
320
|
if (t === End) return state.eoi("OneOf", expected, 1)
|
|
297
321
|
if (t === NoMatch) return state.backtrack("OneOf", expected)
|
|
322
|
+
// SAFETY: past `End` and `NoMatch`, `nextIf` returns the token it consumed from the parser's input `I`
|
|
298
323
|
return t as Token<I>
|
|
299
324
|
},
|
|
300
325
|
m.description,
|
|
@@ -319,6 +344,7 @@ export const noneOf = <I extends Input = string>(
|
|
|
319
344
|
const t = nextIf(state, m, true)
|
|
320
345
|
if (t === End) return state.eoi("NoneOf", expected, 1)
|
|
321
346
|
if (t === NoMatch) return state.backtrack("NoneOf", expected)
|
|
347
|
+
// SAFETY: past `End` and `NoMatch`, `nextIf` returns the token it consumed from the parser's input `I`
|
|
322
348
|
return t as Token<I>
|
|
323
349
|
},
|
|
324
350
|
expected[0],
|
|
@@ -327,12 +353,22 @@ export const noneOf = <I extends Input = string>(
|
|
|
327
353
|
}
|
|
328
354
|
|
|
329
355
|
/**
|
|
330
|
-
* Takes exactly `count` tokens (winnow's and nom's `take`).
|
|
356
|
+
* Takes exactly `count` tokens (winnow's and nom's `take`). `count` must be
|
|
357
|
+
* a non-negative integer: anything else throws a `RangeError` here, when
|
|
358
|
+
* the parser is built.
|
|
359
|
+
*
|
|
360
|
+
* @example
|
|
361
|
+
* ```ts
|
|
362
|
+
* import { Parser, Token } from "@thomasfosterau/effect-parse"
|
|
363
|
+
*
|
|
364
|
+
* Parser.parsePeek(Token.take(2), "abc") // Result.succeed(["c", "ab"])
|
|
365
|
+
* ```
|
|
331
366
|
*
|
|
332
367
|
* @since 0.1.0
|
|
333
368
|
* @category slices
|
|
334
369
|
*/
|
|
335
370
|
export const take = <I extends Input = string>(count: number): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> => {
|
|
371
|
+
checkCount(count)
|
|
336
372
|
const expected = [count === 1 ? "1 token" : `${count} tokens`]
|
|
337
373
|
return described(
|
|
338
374
|
(state) => {
|
|
@@ -348,9 +384,8 @@ export const take = <I extends Input = string>(count: number): Parser<Slice<NoIn
|
|
|
348
384
|
}
|
|
349
385
|
|
|
350
386
|
const normalize = (r: Range | undefined): [number, number] => {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
return [r.min ?? 0, r.max ?? Infinity]
|
|
387
|
+
const { max, min } = bounds(r)
|
|
388
|
+
return [min, max]
|
|
354
389
|
}
|
|
355
390
|
|
|
356
391
|
/** @internal */
|
|
@@ -418,6 +453,18 @@ export const takeTill = <I extends Input = string>(
|
|
|
418
453
|
range?: Range
|
|
419
454
|
): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> => takeWhileImpl(set, range, true, "takeTill")
|
|
420
455
|
|
|
456
|
+
/**
|
|
457
|
+
* The overloads of {@link takeUntil}.
|
|
458
|
+
*
|
|
459
|
+
* @since 0.5.0
|
|
460
|
+
* @category slices
|
|
461
|
+
*/
|
|
462
|
+
export interface TakeUntilFn {
|
|
463
|
+
(literal: string, range?: Range): Parser<string, never, never, string>
|
|
464
|
+
(literal: Uint8Array, range?: Range): Parser<Uint8Array, never, never, Uint8Array>
|
|
465
|
+
<T>(literal: ReadonlyArray<T>, range?: Range): Parser<ReadonlyArray<T>, never, never, ReadonlyArray<T>>
|
|
466
|
+
}
|
|
467
|
+
|
|
421
468
|
/**
|
|
422
469
|
* Takes tokens up to (not including) the first occurrence of a literal
|
|
423
470
|
* (winnow's `take_until`, nom's `take_until`). The literal is not
|
|
@@ -426,25 +473,40 @@ export const takeTill = <I extends Input = string>(
|
|
|
426
473
|
* @since 0.1.0
|
|
427
474
|
* @category slices
|
|
428
475
|
*/
|
|
429
|
-
export const takeUntil:
|
|
430
|
-
(
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
476
|
+
export const takeUntil: TakeUntilFn = (lit: Input, r?: Range): Parser<any, never, never, any> =>
|
|
477
|
+
untilParser(
|
|
478
|
+
(state, from) => indexOf(state, lit, from),
|
|
479
|
+
// A string literal is up to three bytes per unit of UTF-8
|
|
480
|
+
(state) => lit.length * (Predicate.isString(lit) && state.inputKind === 1 ? 3 : 1),
|
|
481
|
+
[describeLiteral(lit)],
|
|
482
|
+
r,
|
|
483
|
+
"takeUntil",
|
|
484
|
+
{ _tag: "TakeUntil", literal: lit, ...bounds(r), encoding: undefined }
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* The parser of `takeUntil` and `takeUntilAny`: `search` finds the first
|
|
489
|
+
* occurrence, which is not consumed (`read` is how far past it the search
|
|
490
|
+
* read). As in winnow, the first occurrence must lie within the range.
|
|
491
|
+
*/
|
|
492
|
+
const untilParser = (
|
|
493
|
+
search: (state: State<Input>, from: number) => number,
|
|
494
|
+
read: (state: State<Input>) => number,
|
|
495
|
+
expected: ReadonlyArray<string>,
|
|
496
|
+
r: Range | undefined,
|
|
497
|
+
name: string,
|
|
498
|
+
node: Parameters<typeof described>[2]
|
|
499
|
+
): Parser<any, never, never, any> => {
|
|
434
500
|
const [min, max] = normalize(r)
|
|
435
|
-
const description = describeLiteral(lit)
|
|
436
|
-
const expected = [description]
|
|
437
501
|
return described(
|
|
438
502
|
(state: State<Input>) => {
|
|
439
503
|
const start = state.pos
|
|
440
|
-
const idx =
|
|
504
|
+
const idx = search(state, start)
|
|
441
505
|
if (idx < 0) {
|
|
442
506
|
if (state.partial) return state.incomplete(0, expected)
|
|
443
507
|
return state.backtrack("TakeUntil", expected, state.end)
|
|
444
508
|
}
|
|
445
|
-
|
|
446
|
-
state.syntax?.read(idx + lit.length * (Predicate.isString(lit) && state.inputKind === 1 ? 3 : 1))
|
|
447
|
-
// As in winnow, the first occurrence must lie within the range
|
|
509
|
+
state.syntax?.read(idx + read(state))
|
|
448
510
|
if (min > 0 || max !== Infinity) {
|
|
449
511
|
const count = countTokens(state, start, idx)
|
|
450
512
|
if (count < min) return state.backtrack("TakeUntil", expected, idx)
|
|
@@ -453,34 +515,88 @@ export const takeUntil: {
|
|
|
453
515
|
state.pos = idx
|
|
454
516
|
return state.slice(start, idx)
|
|
455
517
|
},
|
|
456
|
-
|
|
457
|
-
|
|
518
|
+
name,
|
|
519
|
+
node
|
|
458
520
|
)
|
|
459
521
|
}
|
|
460
522
|
|
|
461
523
|
/**
|
|
462
|
-
*
|
|
524
|
+
* The overloads of {@link takeUntilAny}.
|
|
463
525
|
*
|
|
464
|
-
* @since 0.
|
|
526
|
+
* @since 0.5.0
|
|
465
527
|
* @category slices
|
|
466
528
|
*/
|
|
467
|
-
export
|
|
468
|
-
(
|
|
529
|
+
export interface TakeUntilAnyFn {
|
|
530
|
+
(literals: ReadonlyArray<string>, range?: Range): Parser<string, never, never, string>
|
|
531
|
+
(literals: ReadonlyArray<Uint8Array>, range?: Range): Parser<Uint8Array, never, never, Uint8Array>
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Takes tokens up to (not including) the first occurrence of any of
|
|
536
|
+
* several literals: {@link takeUntil} for a set of them, the search a
|
|
537
|
+
* multi-pattern prefilter makes. No literal is consumed. `range` constrains
|
|
538
|
+
* the number of tokens taken. On bytes, `Compiler.wasm` searches with SIMD
|
|
539
|
+
* (Teddy, from ripgrep), sixteen bytes at a time.
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* ```ts
|
|
543
|
+
* import { Parser, Token } from "@thomasfosterau/effect-parse"
|
|
544
|
+
* import * as Result from "effect/Result"
|
|
545
|
+
*
|
|
546
|
+
* const upTo = Parser.seq(Token.takeUntilAny(["Holmes", "Watson"]), Token.rest)
|
|
547
|
+
* console.log(Result.getOrThrow(Parser.parseSync(upTo, "Dr. Watson and Holmes")))
|
|
548
|
+
* // ["Dr. ", "Watson and Holmes"]
|
|
549
|
+
* ```
|
|
550
|
+
*
|
|
551
|
+
* @since 0.5.0
|
|
552
|
+
* @category slices
|
|
553
|
+
*/
|
|
554
|
+
export const takeUntilAny: TakeUntilAnyFn = (
|
|
555
|
+
literals: ReadonlyArray<Input>,
|
|
556
|
+
r?: Range
|
|
557
|
+
): Parser<any, never, never, any> => {
|
|
558
|
+
const longest = Math.max(0, ...literals.map((lit) => lit.length))
|
|
559
|
+
return untilParser(
|
|
560
|
+
(state, from) => indexOfAny(state, literals, from),
|
|
561
|
+
// Every literal was read up to where it would end (a string literal is up to three bytes per unit of UTF-8)
|
|
562
|
+
(state) => longest * (state.inputKind === 1 ? 3 : 1),
|
|
563
|
+
literals.map(describeLiteral),
|
|
564
|
+
r,
|
|
565
|
+
"takeUntilAny",
|
|
566
|
+
{ _tag: "TakeUntilAny", literals, ...bounds(r), encoding: undefined }
|
|
567
|
+
)
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/** The parser behind `rest` and `restOf`, on every input kind. */
|
|
571
|
+
const restInput: Parser<unknown, never, never, Input> = /*#__PURE__*/ described(
|
|
572
|
+
(state) => {
|
|
469
573
|
const start = state.pos
|
|
470
574
|
state.pos = state.end
|
|
471
|
-
return state.slice(start, state.end)
|
|
575
|
+
return state.slice(start, state.end)
|
|
472
576
|
},
|
|
473
577
|
"rest",
|
|
474
578
|
{ _tag: "Rest", encoding: undefined }
|
|
475
579
|
)
|
|
476
580
|
|
|
581
|
+
/**
|
|
582
|
+
* Takes the rest of the input (winnow's and nom's `rest`).
|
|
583
|
+
*
|
|
584
|
+
* @since 0.1.0
|
|
585
|
+
* @category slices
|
|
586
|
+
*/
|
|
587
|
+
export const rest: Parser<string> =
|
|
588
|
+
// SAFETY: on string input, `State.slice` returns a string
|
|
589
|
+
restInput as Parser<string>
|
|
590
|
+
|
|
477
591
|
/**
|
|
478
592
|
* Takes the rest of an input of type `I`.
|
|
479
593
|
*
|
|
480
594
|
* @since 0.1.0
|
|
481
595
|
* @category slices
|
|
482
596
|
*/
|
|
483
|
-
export const restOf = <I extends Input = string>(): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> =>
|
|
597
|
+
export const restOf = <I extends Input = string>(): Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>> =>
|
|
598
|
+
// SAFETY: `State.slice` returns the input's own slice type for every input kind, so `restInput` returns `Slice<I>`
|
|
599
|
+
restInput as Parser<Slice<NoInfer<I>>, never, never, NoInfer<I>>
|
|
484
600
|
|
|
485
601
|
/**
|
|
486
602
|
* Returns the length of the remaining input without consuming it (winnow's
|
|
@@ -506,4 +622,6 @@ export const restLen: Parser<number, never, never, Input> = /*#__PURE__*/ descri
|
|
|
506
622
|
*/
|
|
507
623
|
export const satisfy = <I extends Input = string>(
|
|
508
624
|
predicate: (token: Token<I>) => boolean
|
|
509
|
-
): Parser<Token<NoInfer<I>>, never, never, NoInfer<I>> =>
|
|
625
|
+
): Parser<Token<NoInfer<I>>, never, never, NoInfer<I>> =>
|
|
626
|
+
// SAFETY: a predicate over the input's tokens is a member of `TokenSet<I>` for each input kind
|
|
627
|
+
oneOf<I>(predicate as TokenSet<I>)
|