@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/Syntax.ts
CHANGED
|
@@ -66,11 +66,15 @@ import { described, isParser } from "./Parser.js"
|
|
|
66
66
|
// Grammar annotations
|
|
67
67
|
// -----------------------------------------------------------------------------
|
|
68
68
|
|
|
69
|
-
const syntaxNode =
|
|
69
|
+
const syntaxNode = <A, E, R, I extends Input>(
|
|
70
|
+
self: Parser<A, E, R, I>,
|
|
71
|
+
kind: string,
|
|
72
|
+
named: boolean
|
|
73
|
+
): Parser<A, E, R, I> => {
|
|
70
74
|
const step = self.step
|
|
71
75
|
// Identifies the nodes this parser builds, so a reparse can reuse them
|
|
72
76
|
const key = new Key()
|
|
73
|
-
return described<
|
|
77
|
+
return described<A, E, R, I>(
|
|
74
78
|
(state) => {
|
|
75
79
|
const builder = state.syntax
|
|
76
80
|
return builder === undefined ? step(state) : builder.node(state, step, key, kind, named)
|
|
@@ -101,10 +105,8 @@ const syntaxNode = (self: Parser.Any, kind: string, named: boolean): Parser.Any
|
|
|
101
105
|
export const node: {
|
|
102
106
|
(kind: string): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>
|
|
103
107
|
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, kind: string): Parser<A, E, R, I>
|
|
104
|
-
} = /*#__PURE__*/ dual(
|
|
105
|
-
|
|
106
|
-
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, kind: string): Parser<A, E, R, I> =>
|
|
107
|
-
syntaxNode(self, kind, true) as Parser<A, E, R, I>
|
|
108
|
+
} = /*#__PURE__*/ dual(2, <A, E, R, I extends Input>(self: Parser<A, E, R, I>, kind: string): Parser<A, E, R, I> =>
|
|
109
|
+
syntaxNode(self, kind, true)
|
|
108
110
|
)
|
|
109
111
|
|
|
110
112
|
/**
|
|
@@ -130,7 +132,7 @@ export const token: {
|
|
|
130
132
|
} = /*#__PURE__*/ dual(
|
|
131
133
|
(args) => isParser(args[0]),
|
|
132
134
|
<A, E, R, I extends Input>(self: Parser<A, E, R, I>, kind?: string): Parser<A, E, R, I> =>
|
|
133
|
-
syntaxNode(self, kind ?? defaultTokenKind(self), false)
|
|
135
|
+
syntaxNode(self, kind ?? defaultTokenKind(self), false)
|
|
134
136
|
)
|
|
135
137
|
|
|
136
138
|
const defaultTokenKind = (self: Parser.Any): string => {
|
|
@@ -168,7 +170,7 @@ export const field: {
|
|
|
168
170
|
return described<A, E, R, I>(
|
|
169
171
|
(state) => {
|
|
170
172
|
const builder = state.syntax
|
|
171
|
-
return
|
|
173
|
+
return builder === undefined ? step(state) : builder.field(state, step, name)
|
|
172
174
|
},
|
|
173
175
|
self.name,
|
|
174
176
|
{ _tag: "Syntax", self, kind: undefined, named: false }
|
|
@@ -346,6 +348,18 @@ export class Tree<out A, out E = never, I extends Input = string> {
|
|
|
346
348
|
}
|
|
347
349
|
}
|
|
348
350
|
|
|
351
|
+
/**
|
|
352
|
+
* What `JSON.stringify` writes for a {@link SyntaxNode}: its kind and span.
|
|
353
|
+
*
|
|
354
|
+
* @since 0.5.0
|
|
355
|
+
* @category models
|
|
356
|
+
*/
|
|
357
|
+
export interface SyntaxNodeJson {
|
|
358
|
+
readonly kind: string
|
|
359
|
+
readonly start: number
|
|
360
|
+
readonly end: number
|
|
361
|
+
}
|
|
362
|
+
|
|
349
363
|
/**
|
|
350
364
|
* A node of a syntax tree: its kind, span and value, and its place in the
|
|
351
365
|
* tree. Nodes are views built on demand; two views of the same node are
|
|
@@ -403,10 +417,11 @@ export class SyntaxNode<I extends Input = string> {
|
|
|
403
417
|
|
|
404
418
|
/** The input the node spans. */
|
|
405
419
|
get text(): Slice<I> {
|
|
406
|
-
const input = this.tree.input
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
: input.slice(this.start, this.end)
|
|
420
|
+
const input: Input = this.tree.input
|
|
421
|
+
// SAFETY: a `subarray` of a `Uint8Array`, or a `slice` of a string or array, has the input's own kind, `Slice<I>`
|
|
422
|
+
return (
|
|
423
|
+
input instanceof Uint8Array ? input.subarray(this.start, this.end) : input.slice(this.start, this.end)
|
|
424
|
+
) as Slice<I>
|
|
410
425
|
}
|
|
411
426
|
|
|
412
427
|
/** Whether this is an `ERROR` node. */
|
|
@@ -592,7 +607,7 @@ export class SyntaxNode<I extends Input = string> {
|
|
|
592
607
|
return out
|
|
593
608
|
}
|
|
594
609
|
|
|
595
|
-
toJSON():
|
|
610
|
+
toJSON(): SyntaxNodeJson {
|
|
596
611
|
return { kind: this.kind, start: this.start, end: this.end }
|
|
597
612
|
}
|
|
598
613
|
|
|
@@ -723,6 +738,8 @@ const run = <A, E, I extends Input>(config: Config, input: I, previous: Previous
|
|
|
723
738
|
state.backtrack("Eof", expectedEof)
|
|
724
739
|
fatal = { failure: state.reportedFailure(), mode: "Backtrack" }
|
|
725
740
|
} else {
|
|
741
|
+
// SAFETY: `config.inner` is the `Parser<A, ...>` given to `parse` or the parser its root `node` wraps, which returns
|
|
742
|
+
// the same `A` (a `reparse` reuses the tree's config)
|
|
726
743
|
value = Option.some(a as A)
|
|
727
744
|
}
|
|
728
745
|
const green = builder.finish(config.kind, Option.getOrUndefined(value), fatal, state.pos)
|
|
@@ -730,19 +747,12 @@ const run = <A, E, I extends Input>(config: Config, input: I, previous: Previous
|
|
|
730
747
|
}
|
|
731
748
|
|
|
732
749
|
/**
|
|
733
|
-
*
|
|
734
|
-
* tree's `value`, and its {@link node}s are the tree's nodes. When the
|
|
735
|
-
* grammar is itself a {@link node}, that node is the root; otherwise the
|
|
736
|
-
* root is a node of kind `options.kind` (by default `"document"`).
|
|
737
|
-
*
|
|
738
|
-
* The parse never fails: recovered failures (see `Parser.resumeAfter`), a
|
|
739
|
-
* fatal failure and unparsed input at the end all become `ERROR` nodes, and
|
|
740
|
-
* are listed in `tree.errors`. The parse is interpreted, never compiled.
|
|
750
|
+
* The overloads of {@link parse}.
|
|
741
751
|
*
|
|
742
|
-
* @since 0.
|
|
752
|
+
* @since 0.5.0
|
|
743
753
|
* @category parsing
|
|
744
754
|
*/
|
|
745
|
-
export
|
|
755
|
+
export interface ParseFn {
|
|
746
756
|
<A, E, I extends Input>(
|
|
747
757
|
grammar: Parser<A, E, never, I>,
|
|
748
758
|
input: NoInfer<Source<I>>,
|
|
@@ -753,7 +763,22 @@ export const parse: {
|
|
|
753
763
|
input: NoInfer<Source<I>>,
|
|
754
764
|
options: ParseOptionsWithContext<R>
|
|
755
765
|
): Tree<A, E, I>
|
|
756
|
-
}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Parses an input into a syntax {@link Tree}. The grammar's output is the
|
|
770
|
+
* tree's `value`, and its {@link node}s are the tree's nodes. When the
|
|
771
|
+
* grammar is itself a {@link node}, that node is the root; otherwise the
|
|
772
|
+
* root is a node of kind `options.kind` (by default `"document"`).
|
|
773
|
+
*
|
|
774
|
+
* The parse never fails: recovered failures (see `Parser.resumeAfter`), a
|
|
775
|
+
* fatal failure and unparsed input at the end all become `ERROR` nodes, and
|
|
776
|
+
* are listed in `tree.errors`. The parse is interpreted, never compiled.
|
|
777
|
+
*
|
|
778
|
+
* @since 0.2.0
|
|
779
|
+
* @category parsing
|
|
780
|
+
*/
|
|
781
|
+
export const parse: ParseFn = <A, E, R, I extends Input>(
|
|
757
782
|
grammar: Parser<A, E, R, I>,
|
|
758
783
|
input: I | Source<I>,
|
|
759
784
|
options?: ParseOptions & { readonly context?: Context.Context<R> }
|
|
@@ -762,11 +787,12 @@ export const parse: {
|
|
|
762
787
|
const isRoot = Predicate.isTagged(n, "Syntax") && n.kind !== undefined && n.named
|
|
763
788
|
const config: Config = {
|
|
764
789
|
kind: isRoot ? n.kind : (options?.kind ?? "document"),
|
|
790
|
+
// SAFETY: a `Syntax` node's `self` is the parser that `node` wrapped, a parser built by this library
|
|
765
791
|
inner: isRoot ? (n.self as Parser.Any) : grammar,
|
|
766
792
|
lookahead: options?.lookahead ?? 0,
|
|
767
|
-
context: options?.context
|
|
793
|
+
context: options?.context
|
|
768
794
|
}
|
|
769
|
-
return run(config, fromSource(input
|
|
795
|
+
return run(config, fromSource<I>(input), undefined)
|
|
770
796
|
}
|
|
771
797
|
|
|
772
798
|
/**
|
|
@@ -803,13 +829,8 @@ export const reparse = <A, E, I extends Input>(
|
|
|
803
829
|
input: NoInfer<Source<I>>,
|
|
804
830
|
edits?: Edit | ReadonlyArray<Edit>
|
|
805
831
|
): Tree<A, E, I> => {
|
|
806
|
-
const next = fromSource(input
|
|
807
|
-
const list =
|
|
808
|
-
edits === undefined
|
|
809
|
-
? diffList(tree.input, next)
|
|
810
|
-
: "start" in edits
|
|
811
|
-
? [edits as Edit]
|
|
812
|
-
: (edits as ReadonlyArray<Edit>)
|
|
832
|
+
const next = fromSource<I>(input)
|
|
833
|
+
const list = edits === undefined ? diffList(tree.input, next) : "start" in edits ? [edits] : edits
|
|
813
834
|
const previous: Previous = {
|
|
814
835
|
root: tree.green,
|
|
815
836
|
oldLength: tree.input.length,
|
|
@@ -854,9 +875,12 @@ export const replace = <A, E>(
|
|
|
854
875
|
* @category parsing
|
|
855
876
|
*/
|
|
856
877
|
export const diff = <I extends Input>(before: I, after: I): Edit | undefined => {
|
|
857
|
-
const a = before
|
|
858
|
-
const b = after
|
|
859
|
-
|
|
878
|
+
const a: Input = before
|
|
879
|
+
const b: Input = after
|
|
880
|
+
// SAFETY: the string reader is chosen only when `a` is a string, and `b` has the same type `I`
|
|
881
|
+
const at = Predicate.isString(a)
|
|
882
|
+
? (s: Input, i: number) => (s as string).charCodeAt(i)
|
|
883
|
+
: (s: Input, i: number) => s[i]
|
|
860
884
|
const max = Math.min(a.length, b.length)
|
|
861
885
|
let prefix = 0
|
|
862
886
|
while (prefix < max && at(a, prefix) === at(b, prefix)) prefix++
|
package/src/Text.ts
CHANGED
|
@@ -39,13 +39,14 @@
|
|
|
39
39
|
import * as Predicate from "effect/Predicate"
|
|
40
40
|
import type { Encoding } from "./Encoding.js"
|
|
41
41
|
import * as Encodings from "./Encoding.js"
|
|
42
|
-
import type {
|
|
42
|
+
import type { State } from "./Input.js"
|
|
43
43
|
import { Fail } from "./Input.js"
|
|
44
44
|
import { escapedImpl, overflow, takeEscapedImpl, toFloat } from "./Ascii.js"
|
|
45
45
|
import { codePointPredicate, compile, indexOf, matchLiteral } from "./internal/tokens.js"
|
|
46
46
|
import { floatText as markFloatText } from "./internal/numbers.js"
|
|
47
47
|
import * as internal from "./internal/text.js"
|
|
48
48
|
import type { Node } from "./internal/node.js"
|
|
49
|
+
import { bounds, checkCount, controlCode } from "./internal/node.js"
|
|
49
50
|
import type { ErrorKind } from "./ParseError.js"
|
|
50
51
|
import type { Parser, Range } from "./Parser.js"
|
|
51
52
|
import * as P from "./Parser.js"
|
|
@@ -354,9 +355,8 @@ export interface TextParsers<I extends string | Uint8Array> {
|
|
|
354
355
|
}
|
|
355
356
|
|
|
356
357
|
const normalize = (r: Range | undefined): [number, number] => {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
return [r.min ?? 0, r.max ?? Infinity]
|
|
358
|
+
const { max, min } = bounds(r)
|
|
359
|
+
return [min, max]
|
|
360
360
|
}
|
|
361
361
|
|
|
362
362
|
const isAsciiDigit = /*#__PURE__*/ codePointPredicate("isAsciiDigit", (c: number): boolean => c >= 48 && c <= 57, [
|
|
@@ -392,7 +392,7 @@ const expectedIdentifier = ["identifier"]
|
|
|
392
392
|
* @category constructors
|
|
393
393
|
*/
|
|
394
394
|
export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): TextParsers<I> => {
|
|
395
|
-
const enc = encoding
|
|
395
|
+
const enc = encoding
|
|
396
396
|
const fast = internal.fastLimit(enc)
|
|
397
397
|
|
|
398
398
|
// Each parser records its encoding on byte input (`state.encoding`), so
|
|
@@ -410,7 +410,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
410
410
|
): string | Fail => {
|
|
411
411
|
const count = internal.validate(enc, state, start, end)
|
|
412
412
|
if (count < 0) return backtrack(state, kind, expected, -1 - count)
|
|
413
|
-
return
|
|
413
|
+
return internal.textIn(enc, state, start, end)
|
|
414
414
|
}
|
|
415
415
|
|
|
416
416
|
const takeWhileText = (
|
|
@@ -438,7 +438,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
438
438
|
// More matching characters would have been accepted where we stopped
|
|
439
439
|
if (hint && count < max) state.setHint(offset, expected)
|
|
440
440
|
state.pos = offset
|
|
441
|
-
return
|
|
441
|
+
return internal.textIn(enc, state, start, offset)
|
|
442
442
|
},
|
|
443
443
|
name,
|
|
444
444
|
{ _tag: "TakeWhile", set, negate, min, max, encoding: enc }
|
|
@@ -471,6 +471,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
471
471
|
if (state.inputKind === 1) state.encoding = enc
|
|
472
472
|
if (pos >= state.end) return state.eoi("Literal", expected, 1)
|
|
473
473
|
const input = state.input
|
|
474
|
+
// SAFETY: a `Text` parser runs on strings or `Uint8Array`s, and `inputKind` 0 is set only for a string
|
|
474
475
|
if ((state.inputKind === 0 ? (input as string).charCodeAt(pos) : (input as Uint8Array)[pos]) !== unit) {
|
|
475
476
|
return backtrack(state, "Literal", expected)
|
|
476
477
|
}
|
|
@@ -518,7 +519,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
518
519
|
pos += internal.width
|
|
519
520
|
}
|
|
520
521
|
state.pos = pos
|
|
521
|
-
return
|
|
522
|
+
return internal.textIn(enc, state, start, pos)
|
|
522
523
|
},
|
|
523
524
|
expected[0],
|
|
524
525
|
{ _tag: "Literal", literal: lit, caseless: true, encoding: enc }
|
|
@@ -546,6 +547,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
546
547
|
}
|
|
547
548
|
|
|
548
549
|
const take = (count: number): Parser<string, never, never, I> => {
|
|
550
|
+
checkCount(count)
|
|
549
551
|
const expected = [count === 1 ? "1 character" : `${count} characters`]
|
|
550
552
|
return P.described<string, never, never, I>(
|
|
551
553
|
(state: State<any>) => {
|
|
@@ -559,7 +561,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
559
561
|
pos += internal.width
|
|
560
562
|
}
|
|
561
563
|
state.pos = pos
|
|
562
|
-
return
|
|
564
|
+
return internal.textIn(enc, state, start, pos)
|
|
563
565
|
},
|
|
564
566
|
"take",
|
|
565
567
|
{ _tag: "Take", count, encoding: enc }
|
|
@@ -575,9 +577,9 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
575
577
|
(state: State<any>) => {
|
|
576
578
|
if (state.inputKind === 1) state.encoding = enc
|
|
577
579
|
const start = state.pos
|
|
578
|
-
let idx = indexOf(state, needle
|
|
580
|
+
let idx = indexOf(state, needle, start)
|
|
579
581
|
// Multi-unit encodings: only accept matches on a character boundary
|
|
580
|
-
while (unit > 1 && idx >= 0 && (idx - start) % unit !== 0) idx = indexOf(state, needle
|
|
582
|
+
while (unit > 1 && idx >= 0 && (idx - start) % unit !== 0) idx = indexOf(state, needle, idx + 1)
|
|
581
583
|
if (idx < 0) {
|
|
582
584
|
if (state.partial) return state.incomplete(0, expected)
|
|
583
585
|
return backtrack(state, "TakeUntil", expected, state.end)
|
|
@@ -590,7 +592,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
590
592
|
if (count < min) return backtrack(state, "TakeUntil", expected, idx)
|
|
591
593
|
if (count > max) return backtrack(state, "TakeUntil", expected)
|
|
592
594
|
state.pos = idx
|
|
593
|
-
return
|
|
595
|
+
return internal.textIn(enc, state, start, idx)
|
|
594
596
|
},
|
|
595
597
|
"takeUntil",
|
|
596
598
|
{ _tag: "TakeUntil", literal: lit, min, max, encoding: enc }
|
|
@@ -607,7 +609,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
607
609
|
if (internal.scanStop === internal.Truncated) return state.incomplete(1, expectedAny)
|
|
608
610
|
if (internal.scanStop === internal.Invalid) return backtrack(state, "Token", expectedAny, offset)
|
|
609
611
|
state.pos = offset
|
|
610
|
-
return
|
|
612
|
+
return internal.textIn(enc, state, start, offset)
|
|
611
613
|
},
|
|
612
614
|
"rest",
|
|
613
615
|
{ _tag: "Rest", encoding: enc }
|
|
@@ -628,7 +630,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
628
630
|
}
|
|
629
631
|
|
|
630
632
|
const cls = (test: CharPredicate, min: 0 | 1, description: string, kind: ErrorKind, hint = true) =>
|
|
631
|
-
takeWhileText(test
|
|
633
|
+
takeWhileText(test, { min }, false, `${kind.toLowerCase()}${min}`, [description], kind, hint)
|
|
632
634
|
|
|
633
635
|
const identifierStart = (cp: number) => cp === 95 || isIdStart(cp)
|
|
634
636
|
const identifier: Parser<string, never, never, I> = P.described<string, never, never, I>(
|
|
@@ -638,13 +640,13 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
638
640
|
const cp = internal.next(enc, state)
|
|
639
641
|
if (cp < 0) return internal.failAt(state, cp, "TakeWhile", expectedIdentifier)
|
|
640
642
|
if (!identifierStart(cp)) return state.backtrack("TakeWhile", expectedIdentifier)
|
|
641
|
-
internal.scan(enc, state, isIdContinue
|
|
643
|
+
internal.scan(enc, state, isIdContinue, false, Infinity, start + internal.width, fast)
|
|
642
644
|
const stop = internal.scanStop
|
|
643
645
|
if (state.partial && (stop === internal.End || stop === internal.Truncated)) {
|
|
644
646
|
return state.incomplete(1, expectedIdentifier)
|
|
645
647
|
}
|
|
646
648
|
state.pos = internal.scanOffset
|
|
647
|
-
return
|
|
649
|
+
return internal.textIn(enc, state, start, state.pos)
|
|
648
650
|
},
|
|
649
651
|
"identifier",
|
|
650
652
|
{ _tag: "Identifier", encoding: enc }
|
|
@@ -691,7 +693,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
691
693
|
if (after !== 10) return backtrack(state, "LineEnding", expectedLineEnding, offset)
|
|
692
694
|
}
|
|
693
695
|
state.pos = offset
|
|
694
|
-
return
|
|
696
|
+
return internal.textIn(enc, state, start, offset)
|
|
695
697
|
},
|
|
696
698
|
"tillLineEnding",
|
|
697
699
|
{ _tag: "TillLineEnding", encoding: enc }
|
|
@@ -718,8 +720,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
718
720
|
)
|
|
719
721
|
const floatText = markFloatText(taken(P.alt(caseless("nan"), P.seq(sign, unsignedFloat))).pipe(P.expected("number")))
|
|
720
722
|
|
|
721
|
-
const matchControl = (
|
|
722
|
-
const ctrl = control.codePointAt(0)
|
|
723
|
+
const matchControl = (ctrl: number) => {
|
|
723
724
|
return (state: State<any>): boolean => {
|
|
724
725
|
if (internal.next(enc, state) !== ctrl) return false
|
|
725
726
|
state.pos += internal.width
|
|
@@ -778,17 +779,21 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
778
779
|
P.named("hexUint")
|
|
779
780
|
),
|
|
780
781
|
float: floatText.pipe(P.map(toFloat), P.named("float")),
|
|
781
|
-
takeEscaped: (normal, control, escapable) =>
|
|
782
|
-
|
|
782
|
+
takeEscaped: (normal, control, escapable) => {
|
|
783
|
+
const ctrl = controlCode(control, internal.firstCodePoint)
|
|
784
|
+
return takeEscapedImpl(
|
|
783
785
|
normal,
|
|
784
|
-
matchControl(
|
|
786
|
+
matchControl(ctrl),
|
|
785
787
|
escapable,
|
|
786
|
-
(state, start) =>
|
|
787
|
-
|
|
788
|
+
(state, start) => internal.textIn(enc, state, start, state.pos),
|
|
789
|
+
ctrl,
|
|
788
790
|
enc
|
|
789
|
-
)
|
|
790
|
-
|
|
791
|
-
|
|
791
|
+
)
|
|
792
|
+
},
|
|
793
|
+
escaped: (normal, control, escape) => {
|
|
794
|
+
const ctrl = controlCode(control, internal.firstCodePoint)
|
|
795
|
+
return escapedImpl(normal, matchControl(ctrl), escape, ctrl, enc)
|
|
796
|
+
}
|
|
792
797
|
}
|
|
793
798
|
}
|
|
794
799
|
|