@thomasfosterau/effect-parse 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +247 -230
- package/dist/Ascii.d.ts +32 -53
- package/dist/Ascii.d.ts.map +1 -1
- package/dist/Ascii.js +576 -571
- package/dist/Ascii.js.map +1 -1
- package/dist/Binary.d.ts +6 -29
- package/dist/Binary.d.ts.map +1 -1
- package/dist/Binary.js +129 -116
- package/dist/Binary.js.map +1 -1
- package/dist/Bits.d.ts +4 -2
- package/dist/Bits.d.ts.map +1 -1
- package/dist/Bits.js +121 -123
- package/dist/Bits.js.map +1 -1
- package/dist/Compiler.d.ts +39 -0
- package/dist/Compiler.d.ts.map +1 -0
- package/dist/Compiler.js +48 -0
- package/dist/Compiler.js.map +1 -0
- package/dist/Encoding.d.ts +29 -46
- package/dist/Encoding.d.ts.map +1 -1
- package/dist/Encoding.js +76 -75
- package/dist/Encoding.js.map +1 -1
- package/dist/Expression.d.ts +15 -49
- package/dist/Expression.d.ts.map +1 -1
- package/dist/Expression.js +143 -131
- package/dist/Expression.js.map +1 -1
- package/dist/Input.d.ts +206 -177
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +317 -299
- package/dist/Input.js.map +1 -1
- package/dist/Nom.d.ts +44 -84
- package/dist/Nom.d.ts.map +1 -1
- package/dist/Nom.js +423 -453
- package/dist/Nom.js.map +1 -1
- package/dist/ParseError.d.ts +54 -49
- package/dist/ParseError.d.ts.map +1 -1
- package/dist/ParseError.js +233 -275
- package/dist/ParseError.js.map +1 -1
- package/dist/Parser.d.ts +345 -313
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +2010 -1802
- package/dist/Parser.js.map +1 -1
- package/dist/ParserSchema.d.ts +8 -7
- package/dist/ParserSchema.d.ts.map +1 -1
- package/dist/ParserSchema.js +49 -49
- package/dist/ParserSchema.js.map +1 -1
- package/dist/ParserStream.d.ts +26 -20
- package/dist/ParserStream.d.ts.map +1 -1
- package/dist/ParserStream.js +267 -255
- package/dist/ParserStream.js.map +1 -1
- package/dist/Syntax.d.ts +401 -0
- package/dist/Syntax.d.ts.map +1 -0
- package/dist/Syntax.js +717 -0
- package/dist/Syntax.js.map +1 -0
- package/dist/Text.d.ts +98 -134
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +534 -496
- package/dist/Text.js.map +1 -1
- package/dist/Token.d.ts +60 -42
- package/dist/Token.d.ts.map +1 -1
- package/dist/Token.js +331 -265
- package/dist/Token.js.map +1 -1
- package/dist/index.d.ts +16 -17
- package/dist/index.js +16 -17
- package/dist/internal/compiler/closure.d.ts +14 -16
- package/dist/internal/compiler/closure.d.ts.map +1 -1
- package/dist/internal/compiler/closure.js +1458 -1637
- package/dist/internal/compiler/closure.js.map +1 -1
- package/dist/internal/compiler/entries.d.ts +11 -11
- package/dist/internal/compiler/entries.d.ts.map +1 -1
- package/dist/internal/compiler/entries.js +36 -26
- package/dist/internal/compiler/entries.js.map +1 -1
- package/dist/internal/compiler/first.d.ts +19 -19
- package/dist/internal/compiler/first.d.ts.map +1 -1
- package/dist/internal/compiler/first.js +251 -227
- package/dist/internal/compiler/first.js.map +1 -1
- package/dist/internal/compiler/jit.d.ts +6 -17
- package/dist/internal/compiler/jit.d.ts.map +1 -1
- package/dist/internal/compiler/jit.js +860 -988
- package/dist/internal/compiler/jit.js.map +1 -1
- package/dist/internal/compiler/registry.d.ts +20 -21
- package/dist/internal/compiler/registry.d.ts.map +1 -1
- package/dist/internal/compiler/registry.js +21 -41
- package/dist/internal/compiler/registry.js.map +1 -1
- package/dist/internal/compiler/sets.d.ts +9 -13
- package/dist/internal/compiler/sets.d.ts.map +1 -1
- package/dist/internal/compiler/sets.js +76 -73
- package/dist/internal/compiler/sets.js.map +1 -1
- package/dist/internal/entries.d.ts +3 -3
- package/dist/internal/entries.d.ts.map +1 -1
- package/dist/internal/entries.js +38 -30
- package/dist/internal/entries.js.map +1 -1
- package/dist/internal/node.d.ts +177 -173
- package/dist/internal/node.d.ts.map +1 -1
- package/dist/internal/node.js +77 -66
- package/dist/internal/node.js.map +1 -1
- package/dist/internal/numbers.d.ts +7 -8
- package/dist/internal/numbers.d.ts.map +1 -1
- package/dist/internal/numbers.js +246 -276
- package/dist/internal/numbers.js.map +1 -1
- package/dist/internal/resume.d.ts +6 -24
- package/dist/internal/resume.d.ts.map +1 -1
- package/dist/internal/resume.js +30 -29
- package/dist/internal/resume.js.map +1 -1
- package/dist/internal/run.d.ts +15 -0
- package/dist/internal/run.d.ts.map +1 -0
- package/dist/internal/run.js +36 -0
- package/dist/internal/run.js.map +1 -0
- package/dist/internal/stack.d.ts +16 -0
- package/dist/internal/stack.d.ts.map +1 -0
- package/dist/internal/stack.js +26 -0
- package/dist/internal/stack.js.map +1 -0
- package/dist/internal/syntax.d.ts +146 -0
- package/dist/internal/syntax.d.ts.map +1 -0
- package/dist/internal/syntax.js +305 -0
- package/dist/internal/syntax.js.map +1 -0
- package/dist/internal/text.d.ts +10 -2
- package/dist/internal/text.d.ts.map +1 -1
- package/dist/internal/text.js +295 -345
- package/dist/internal/text.js.map +1 -1
- package/dist/internal/tokens.d.ts +25 -30
- package/dist/internal/tokens.d.ts.map +1 -1
- package/dist/internal/tokens.js +369 -363
- package/dist/internal/tokens.js.map +1 -1
- package/package.json +42 -28
- package/src/Ascii.ts +278 -187
- package/src/Binary.ts +150 -44
- package/src/Bits.ts +6 -3
- package/src/Compiler.ts +98 -0
- package/src/Expression.ts +10 -5
- package/src/Input.ts +106 -28
- package/src/Nom.ts +4 -3
- package/src/ParseError.ts +48 -51
- package/src/Parser.ts +1163 -795
- package/src/ParserStream.ts +104 -80
- package/src/Syntax.ts +900 -0
- package/src/Text.ts +272 -187
- package/src/Token.ts +180 -87
- package/src/index.ts +2 -0
- package/src/internal/compiler/closure.ts +121 -88
- package/src/internal/compiler/entries.ts +21 -8
- package/src/internal/compiler/first.ts +17 -15
- package/src/internal/compiler/jit.ts +360 -157
- package/src/internal/compiler/registry.ts +12 -33
- package/src/internal/compiler/sets.ts +17 -11
- package/src/internal/entries.ts +4 -2
- package/src/internal/node.ts +51 -37
- package/src/internal/numbers.ts +22 -20
- package/src/internal/resume.ts +8 -4
- package/src/internal/run.ts +41 -0
- package/src/internal/stack.ts +36 -0
- package/src/internal/syntax.ts +421 -0
- package/src/internal/text.ts +32 -25
- package/src/internal/tokens.ts +96 -51
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/Token.js
CHANGED
|
@@ -1,294 +1,360 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { bounds } from "./internal/node.js";
|
|
1
|
+
import * as Predicate from "effect/Predicate";
|
|
3
2
|
import { described } from "./Parser.js";
|
|
3
|
+
import { End, NoMatch, advance, codePointPredicate, compileAny, countTokens, describeLiteral, indexOf, matchLiteral, nextIf, scan, splitSurrogate } from "./internal/tokens.js";
|
|
4
|
+
import { bounds } from "./internal/node.js";
|
|
5
|
+
//#region src/Token.ts
|
|
6
|
+
/**
|
|
7
|
+
* Parsers for individual tokens and slices of tokens (winnow's `token`
|
|
8
|
+
* module, nom's `bytes` module).
|
|
9
|
+
*
|
|
10
|
+
* Parsers here work on every input kind: `string` (tokens are code points),
|
|
11
|
+
* `Uint8Array` (tokens are bytes) and arrays (tokens are elements). Parsers
|
|
12
|
+
* whose input type cannot be inferred from their arguments take a type
|
|
13
|
+
* parameter that defaults to `string`:
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { Token } from "@thomasfosterau/effect-parse"
|
|
17
|
+
*
|
|
18
|
+
* Token.take(4) // Parser<string, never, never, string>
|
|
19
|
+
* Token.take<Uint8Array>(4) // Parser<Uint8Array, never, never, Uint8Array>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* On partial input (see `Parser.parsePartial`), parsers that reach the end
|
|
23
|
+
* of the available data report `Incomplete` rather than succeeding early or
|
|
24
|
+
* failing.
|
|
25
|
+
*
|
|
26
|
+
* @since 0.1.0
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Creates an inclusive token range (winnow's `'a'..='z'`).
|
|
30
|
+
*
|
|
31
|
+
* @since 0.1.0
|
|
32
|
+
* @category constructors
|
|
33
|
+
*/
|
|
34
|
+
const range = (from, to) => ({
|
|
35
|
+
_tag: "TokenRange",
|
|
36
|
+
from,
|
|
37
|
+
to
|
|
38
|
+
});
|
|
4
39
|
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
40
|
+
* Declares a character class as a predicate over code points, for token sets
|
|
41
|
+
* on string, `Text` and byte inputs. `name` describes it in error messages.
|
|
42
|
+
*
|
|
43
|
+
* A plain `(char: string) => boolean` predicate receives each character as a
|
|
44
|
+
* string, which costs an allocation per character tested; a `codePoints`
|
|
45
|
+
* predicate receives the code point itself (a byte, on byte input).
|
|
46
|
+
*
|
|
47
|
+
* `ranges` optionally lists the code points the predicate accepts, as
|
|
48
|
+
* inclusive `[from, to]` pairs. Compiled parsers then test the ranges
|
|
49
|
+
* instead of calling the predicate, so they must agree with it exactly.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* import { Parser, Token } from "@thomasfosterau/effect-parse"
|
|
54
|
+
*
|
|
55
|
+
* const isNameStart = Token.codePoints(
|
|
56
|
+
* "name start",
|
|
57
|
+
* (c) => (c >= 0x61 && c <= 0x7a) || c === 0x5f || c >= 0xc0,
|
|
58
|
+
* [[0x5f, 0x5f], [0x61, 0x7a], [0xc0, 0x10ffff]]
|
|
59
|
+
* )
|
|
60
|
+
* const name = Token.takeWhile([isNameStart, Token.range("0", "9")], { min: 1 })
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @since 0.2.0
|
|
64
|
+
* @category constructors
|
|
65
|
+
*/
|
|
66
|
+
const codePoints = (name, predicate, ranges) => codePointPredicate(name, (c) => predicate(c), ranges?.map(([from, to]) => [from, to]));
|
|
11
67
|
const expectedAny = ["any token"];
|
|
12
68
|
const anyStep = (state) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return state.input[pos];
|
|
35
|
-
}
|
|
69
|
+
const pos = state.pos;
|
|
70
|
+
if (pos >= state.end) return state.eoi("Token", expectedAny, 1);
|
|
71
|
+
switch (state.inputKind) {
|
|
72
|
+
case 0: {
|
|
73
|
+
const s = state.input;
|
|
74
|
+
if (splitSurrogate(state, pos)) return state.incomplete(1, expectedAny);
|
|
75
|
+
const c = s.charCodeAt(pos);
|
|
76
|
+
if (c >= 55296 && c <= 56319 && pos + 1 < s.length && (s.charCodeAt(pos + 1) & 64512) === 56320) {
|
|
77
|
+
state.pos = pos + 2;
|
|
78
|
+
return s.slice(pos, pos + 2);
|
|
79
|
+
}
|
|
80
|
+
state.pos = pos + 1;
|
|
81
|
+
return s[pos];
|
|
82
|
+
}
|
|
83
|
+
case 1:
|
|
84
|
+
state.pos = pos + 1;
|
|
85
|
+
return state.input[pos];
|
|
86
|
+
default:
|
|
87
|
+
state.pos = pos + 1;
|
|
88
|
+
return state.input[pos];
|
|
89
|
+
}
|
|
36
90
|
};
|
|
37
91
|
/**
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
92
|
+
* Matches any single token: a character of a string (winnow's `any`, nom's
|
|
93
|
+
* `anychar`).
|
|
94
|
+
*
|
|
95
|
+
* @since 0.1.0
|
|
96
|
+
* @category tokens
|
|
97
|
+
*/
|
|
98
|
+
const any = /*#__PURE__*/ described(anyStep, "any", {
|
|
99
|
+
_tag: "Any",
|
|
100
|
+
encoding: void 0
|
|
101
|
+
});
|
|
45
102
|
/**
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
103
|
+
* Matches any single token of an input of type `I`.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* import { Parser, Token } from "@thomasfosterau/effect-parse"
|
|
108
|
+
*
|
|
109
|
+
* const byte = Token.anyToken<Uint8Array>()
|
|
110
|
+
* Parser.parse(byte, new Uint8Array([7])) // Result.succeed(7)
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @since 0.1.0
|
|
114
|
+
* @category tokens
|
|
115
|
+
*/
|
|
116
|
+
const anyToken = () => any;
|
|
60
117
|
/**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
118
|
+
* Matches a literal sequence of tokens (winnow's `literal`, nom's `tag`).
|
|
119
|
+
* Strings are matched against string input, `Uint8Array`s against byte
|
|
120
|
+
* input, and arrays element-wise (with `===`) against array input.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* import { Parser, Token } from "@thomasfosterau/effect-parse"
|
|
125
|
+
*
|
|
126
|
+
* const keyword = Parser.alt(Token.literal("true"), Token.literal("false"))
|
|
127
|
+
* // ^? Parser<"true" | "false">
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* @since 0.1.0
|
|
131
|
+
* @category tokens
|
|
132
|
+
*/
|
|
133
|
+
const literal = (lit) => literalImpl(lit, false);
|
|
77
134
|
/** @internal */
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return caseless || state.inputKind !== literalKind ? state.slice(pos, pos + len) : lit;
|
|
102
|
-
}, description, { _tag: "Literal", literal: lit, caseless, encoding: undefined });
|
|
135
|
+
const literalImpl = (lit, caseless) => {
|
|
136
|
+
const description = describeLiteral(lit);
|
|
137
|
+
const expected = [caseless ? `${description} (case insensitive)` : description];
|
|
138
|
+
let asBytes;
|
|
139
|
+
const literalKind = Predicate.isString(lit) ? 0 : lit instanceof Uint8Array ? 1 : 2;
|
|
140
|
+
return described((state) => {
|
|
141
|
+
const pos = state.pos;
|
|
142
|
+
const l = literalKind === 0 && state.inputKind === 1 ? asBytes ??= new TextEncoder().encode(lit) : lit;
|
|
143
|
+
const len = l.length;
|
|
144
|
+
const r = matchLiteral(state, l, caseless);
|
|
145
|
+
if (r === -1) return state.backtrack("Literal", expected);
|
|
146
|
+
if (r === -2) {
|
|
147
|
+
if (state.partial) return state.incomplete(len - (state.end - pos), expected);
|
|
148
|
+
return state.backtrack("Literal", expected);
|
|
149
|
+
}
|
|
150
|
+
state.pos = pos + len;
|
|
151
|
+
return caseless || state.inputKind !== literalKind ? state.slice(pos, pos + len) : lit;
|
|
152
|
+
}, description, {
|
|
153
|
+
_tag: "Literal",
|
|
154
|
+
literal: lit,
|
|
155
|
+
caseless,
|
|
156
|
+
encoding: void 0
|
|
157
|
+
});
|
|
103
158
|
};
|
|
104
159
|
/**
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
160
|
+
* Matches one token belonging to a set, returning it (winnow's and nom's
|
|
161
|
+
* `one_of`).
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```ts
|
|
165
|
+
* import { Parser, Token } from "@thomasfosterau/effect-parse"
|
|
166
|
+
*
|
|
167
|
+
* const sign = Token.oneOf("+-")
|
|
168
|
+
* const lower = Token.oneOf(Token.range("a", "z"))
|
|
169
|
+
* const hexByte = Token.oneOf<Uint8Array>([Token.range(0x30, 0x39), Token.range(0x61, 0x66)])
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* @since 0.1.0
|
|
173
|
+
* @category tokens
|
|
174
|
+
*/
|
|
175
|
+
const oneOf = (set) => {
|
|
176
|
+
const m = compileAny(set);
|
|
177
|
+
const expected = [m.description];
|
|
178
|
+
return described((state) => {
|
|
179
|
+
const t = nextIf(state, m, false);
|
|
180
|
+
if (t === End) return state.eoi("OneOf", expected, 1);
|
|
181
|
+
if (t === NoMatch) return state.backtrack("OneOf", expected);
|
|
182
|
+
return t;
|
|
183
|
+
}, m.description, {
|
|
184
|
+
_tag: "OneOf",
|
|
185
|
+
set,
|
|
186
|
+
negate: false,
|
|
187
|
+
encoding: void 0
|
|
188
|
+
});
|
|
131
189
|
};
|
|
132
190
|
/**
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
191
|
+
* Matches one token *not* belonging to a set, returning it (winnow's and
|
|
192
|
+
* nom's `none_of`).
|
|
193
|
+
*
|
|
194
|
+
* @since 0.1.0
|
|
195
|
+
* @category tokens
|
|
196
|
+
*/
|
|
197
|
+
const noneOf = (set) => {
|
|
198
|
+
const m = compileAny(set);
|
|
199
|
+
const expected = [`anything but ${m.description}`];
|
|
200
|
+
return described((state) => {
|
|
201
|
+
const t = nextIf(state, m, true);
|
|
202
|
+
if (t === End) return state.eoi("NoneOf", expected, 1);
|
|
203
|
+
if (t === NoMatch) return state.backtrack("NoneOf", expected);
|
|
204
|
+
return t;
|
|
205
|
+
}, expected[0], {
|
|
206
|
+
_tag: "OneOf",
|
|
207
|
+
set,
|
|
208
|
+
negate: true,
|
|
209
|
+
encoding: void 0
|
|
210
|
+
});
|
|
150
211
|
};
|
|
151
212
|
/**
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
213
|
+
* Takes exactly `count` tokens (winnow's and nom's `take`).
|
|
214
|
+
*
|
|
215
|
+
* @since 0.1.0
|
|
216
|
+
* @category slices
|
|
217
|
+
*/
|
|
218
|
+
const take = (count) => {
|
|
219
|
+
const expected = [count === 1 ? "1 token" : `${count} tokens`];
|
|
220
|
+
return described((state) => {
|
|
221
|
+
const start = state.pos;
|
|
222
|
+
const { count: got, offset } = advance(state, start, count);
|
|
223
|
+
if (got < count) return state.eoi("Take", expected, count - got);
|
|
224
|
+
state.pos = offset;
|
|
225
|
+
return state.slice(start, offset);
|
|
226
|
+
}, "take", {
|
|
227
|
+
_tag: "Take",
|
|
228
|
+
count,
|
|
229
|
+
encoding: void 0
|
|
230
|
+
});
|
|
167
231
|
};
|
|
168
232
|
const normalize = (r) => {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return [r, r];
|
|
173
|
-
return [r.min ?? 0, r.max ?? Infinity];
|
|
233
|
+
if (r === void 0) return [0, Infinity];
|
|
234
|
+
if (Predicate.isNumber(r)) return [r, r];
|
|
235
|
+
return [r.min ?? 0, r.max ?? Infinity];
|
|
174
236
|
};
|
|
175
237
|
/** @internal */
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
238
|
+
const takeWhileImpl = (set, r, negate, name, description, kind = "TakeWhile", hint = false) => {
|
|
239
|
+
const m = compileAny(set);
|
|
240
|
+
const [min, max] = normalize(r);
|
|
241
|
+
const expected = [description ?? (negate ? `anything but ${m.description}` : m.description)];
|
|
242
|
+
return described((state) => {
|
|
243
|
+
const start = state.pos;
|
|
244
|
+
const { count, hitEnd, offset } = scan(state, m, negate, max);
|
|
245
|
+
if (hitEnd && state.partial) return state.incomplete(1, expected);
|
|
246
|
+
if (count < min) return state.backtrack(kind, expected, offset);
|
|
247
|
+
if (hint && count < max) state.setHint(offset, expected);
|
|
248
|
+
state.pos = offset;
|
|
249
|
+
return state.slice(start, offset);
|
|
250
|
+
}, name, {
|
|
251
|
+
_tag: "TakeWhile",
|
|
252
|
+
set,
|
|
253
|
+
negate,
|
|
254
|
+
min,
|
|
255
|
+
max,
|
|
256
|
+
encoding: void 0
|
|
257
|
+
});
|
|
193
258
|
};
|
|
194
259
|
/**
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
260
|
+
* Takes the longest run of tokens belonging to a set, with the number of
|
|
261
|
+
* tokens constrained by `range` (default: zero or more). This is winnow's
|
|
262
|
+
* `take_while(range, set)`, and nom's `take_while`, `take_while1` and
|
|
263
|
+
* `take_while_m_n`.
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* ```ts
|
|
267
|
+
* import { Parser, Token } from "@thomasfosterau/effect-parse"
|
|
268
|
+
*
|
|
269
|
+
* const identifier = Token.takeWhile(
|
|
270
|
+
* [Token.range("a", "z"), Token.range("A", "Z"), "_"],
|
|
271
|
+
* { min: 1 }
|
|
272
|
+
* )
|
|
273
|
+
* ```
|
|
274
|
+
*
|
|
275
|
+
* @since 0.1.0
|
|
276
|
+
* @category slices
|
|
277
|
+
*/
|
|
278
|
+
const takeWhile = (set, range) => takeWhileImpl(set, range, false, "takeWhile");
|
|
214
279
|
/**
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
280
|
+
* Takes the longest run of tokens *not* belonging to a set (winnow's
|
|
281
|
+
* `take_till`, nom's `take_till` and `take_till1`).
|
|
282
|
+
*
|
|
283
|
+
* @since 0.1.0
|
|
284
|
+
* @category slices
|
|
285
|
+
*/
|
|
286
|
+
const takeTill = (set, range) => takeWhileImpl(set, range, true, "takeTill");
|
|
222
287
|
/**
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
state.pos = idx;
|
|
255
|
-
return state.slice(start, idx);
|
|
256
|
-
}, "takeUntil", { _tag: "TakeUntil", literal: lit, ...bounds(r), encoding: undefined });
|
|
288
|
+
* Takes tokens up to (not including) the first occurrence of a literal
|
|
289
|
+
* (winnow's `take_until`, nom's `take_until`). The literal is not
|
|
290
|
+
* consumed. `range` constrains the number of tokens taken.
|
|
291
|
+
*
|
|
292
|
+
* @since 0.1.0
|
|
293
|
+
* @category slices
|
|
294
|
+
*/
|
|
295
|
+
const takeUntil = (lit, r) => {
|
|
296
|
+
const [min, max] = normalize(r);
|
|
297
|
+
const expected = [describeLiteral(lit)];
|
|
298
|
+
return described((state) => {
|
|
299
|
+
const start = state.pos;
|
|
300
|
+
const idx = indexOf(state, lit, start);
|
|
301
|
+
if (idx < 0) {
|
|
302
|
+
if (state.partial) return state.incomplete(0, expected);
|
|
303
|
+
return state.backtrack("TakeUntil", expected, state.end);
|
|
304
|
+
}
|
|
305
|
+
state.syntax?.read(idx + lit.length * (Predicate.isString(lit) && state.inputKind === 1 ? 3 : 1));
|
|
306
|
+
if (min > 0 || max !== Infinity) {
|
|
307
|
+
const count = countTokens(state, start, idx);
|
|
308
|
+
if (count < min) return state.backtrack("TakeUntil", expected, idx);
|
|
309
|
+
if (count > max) return state.backtrack("TakeUntil", expected);
|
|
310
|
+
}
|
|
311
|
+
state.pos = idx;
|
|
312
|
+
return state.slice(start, idx);
|
|
313
|
+
}, "takeUntil", {
|
|
314
|
+
_tag: "TakeUntil",
|
|
315
|
+
literal: lit,
|
|
316
|
+
...bounds(r),
|
|
317
|
+
encoding: void 0
|
|
318
|
+
});
|
|
257
319
|
};
|
|
258
320
|
/**
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
}, "rest", {
|
|
321
|
+
* Takes the rest of the input (winnow's and nom's `rest`).
|
|
322
|
+
*
|
|
323
|
+
* @since 0.1.0
|
|
324
|
+
* @category slices
|
|
325
|
+
*/
|
|
326
|
+
const rest = /*#__PURE__*/ described((state) => {
|
|
327
|
+
const start = state.pos;
|
|
328
|
+
state.pos = state.end;
|
|
329
|
+
return state.slice(start, state.end);
|
|
330
|
+
}, "rest", {
|
|
331
|
+
_tag: "Rest",
|
|
332
|
+
encoding: void 0
|
|
333
|
+
});
|
|
269
334
|
/**
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
335
|
+
* Takes the rest of an input of type `I`.
|
|
336
|
+
*
|
|
337
|
+
* @since 0.1.0
|
|
338
|
+
* @category slices
|
|
339
|
+
*/
|
|
340
|
+
const restOf = () => rest;
|
|
276
341
|
/**
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
_tag: "RestLen"
|
|
285
|
-
});
|
|
342
|
+
* Returns the length of the remaining input without consuming it (winnow's
|
|
343
|
+
* and nom's `rest_len`).
|
|
344
|
+
*
|
|
345
|
+
* @since 0.1.0
|
|
346
|
+
* @category slices
|
|
347
|
+
*/
|
|
348
|
+
const restLen = /*#__PURE__*/ described((state) => state.end - state.pos, "restLen", { _tag: "RestLen" });
|
|
286
349
|
/**
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
350
|
+
* Matches a token satisfying a predicate (nom's `satisfy`). Equivalent to
|
|
351
|
+
* `Token.oneOf(predicate)`.
|
|
352
|
+
*
|
|
353
|
+
* @since 0.1.0
|
|
354
|
+
* @category tokens
|
|
355
|
+
*/
|
|
356
|
+
const satisfy = (predicate) => oneOf(predicate);
|
|
357
|
+
//#endregion
|
|
358
|
+
export { any, anyToken, codePoints, literal, literalImpl, noneOf, oneOf, range, rest, restLen, restOf, satisfy, take, takeTill, takeUntil, takeWhile, takeWhileImpl };
|
|
359
|
+
|
|
294
360
|
//# sourceMappingURL=Token.js.map
|