@thomasfosterau/effect-parse 0.0.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.
Files changed (155) hide show
  1. package/README.md +247 -230
  2. package/dist/Ascii.d.ts +32 -53
  3. package/dist/Ascii.d.ts.map +1 -1
  4. package/dist/Ascii.js +576 -571
  5. package/dist/Ascii.js.map +1 -1
  6. package/dist/Binary.d.ts +6 -29
  7. package/dist/Binary.d.ts.map +1 -1
  8. package/dist/Binary.js +129 -116
  9. package/dist/Binary.js.map +1 -1
  10. package/dist/Bits.d.ts +4 -2
  11. package/dist/Bits.d.ts.map +1 -1
  12. package/dist/Bits.js +121 -123
  13. package/dist/Bits.js.map +1 -1
  14. package/dist/Compiler.d.ts +39 -0
  15. package/dist/Compiler.d.ts.map +1 -0
  16. package/dist/Compiler.js +48 -0
  17. package/dist/Compiler.js.map +1 -0
  18. package/dist/Encoding.d.ts +29 -46
  19. package/dist/Encoding.d.ts.map +1 -1
  20. package/dist/Encoding.js +76 -75
  21. package/dist/Encoding.js.map +1 -1
  22. package/dist/Expression.d.ts +15 -49
  23. package/dist/Expression.d.ts.map +1 -1
  24. package/dist/Expression.js +143 -131
  25. package/dist/Expression.js.map +1 -1
  26. package/dist/Input.d.ts +206 -177
  27. package/dist/Input.d.ts.map +1 -1
  28. package/dist/Input.js +317 -299
  29. package/dist/Input.js.map +1 -1
  30. package/dist/Nom.d.ts +44 -84
  31. package/dist/Nom.d.ts.map +1 -1
  32. package/dist/Nom.js +423 -453
  33. package/dist/Nom.js.map +1 -1
  34. package/dist/ParseError.d.ts +54 -49
  35. package/dist/ParseError.d.ts.map +1 -1
  36. package/dist/ParseError.js +233 -275
  37. package/dist/ParseError.js.map +1 -1
  38. package/dist/Parser.d.ts +345 -313
  39. package/dist/Parser.d.ts.map +1 -1
  40. package/dist/Parser.js +2010 -1802
  41. package/dist/Parser.js.map +1 -1
  42. package/dist/ParserSchema.d.ts +8 -7
  43. package/dist/ParserSchema.d.ts.map +1 -1
  44. package/dist/ParserSchema.js +49 -49
  45. package/dist/ParserSchema.js.map +1 -1
  46. package/dist/ParserStream.d.ts +26 -20
  47. package/dist/ParserStream.d.ts.map +1 -1
  48. package/dist/ParserStream.js +267 -255
  49. package/dist/ParserStream.js.map +1 -1
  50. package/dist/Syntax.d.ts +401 -0
  51. package/dist/Syntax.d.ts.map +1 -0
  52. package/dist/Syntax.js +717 -0
  53. package/dist/Syntax.js.map +1 -0
  54. package/dist/Text.d.ts +98 -134
  55. package/dist/Text.d.ts.map +1 -1
  56. package/dist/Text.js +534 -496
  57. package/dist/Text.js.map +1 -1
  58. package/dist/Token.d.ts +60 -42
  59. package/dist/Token.d.ts.map +1 -1
  60. package/dist/Token.js +331 -265
  61. package/dist/Token.js.map +1 -1
  62. package/dist/index.d.ts +16 -17
  63. package/dist/index.js +16 -17
  64. package/dist/internal/compiler/closure.d.ts +14 -16
  65. package/dist/internal/compiler/closure.d.ts.map +1 -1
  66. package/dist/internal/compiler/closure.js +1458 -1637
  67. package/dist/internal/compiler/closure.js.map +1 -1
  68. package/dist/internal/compiler/entries.d.ts +11 -11
  69. package/dist/internal/compiler/entries.d.ts.map +1 -1
  70. package/dist/internal/compiler/entries.js +36 -26
  71. package/dist/internal/compiler/entries.js.map +1 -1
  72. package/dist/internal/compiler/first.d.ts +19 -19
  73. package/dist/internal/compiler/first.d.ts.map +1 -1
  74. package/dist/internal/compiler/first.js +251 -227
  75. package/dist/internal/compiler/first.js.map +1 -1
  76. package/dist/internal/compiler/jit.d.ts +6 -17
  77. package/dist/internal/compiler/jit.d.ts.map +1 -1
  78. package/dist/internal/compiler/jit.js +860 -988
  79. package/dist/internal/compiler/jit.js.map +1 -1
  80. package/dist/internal/compiler/registry.d.ts +20 -21
  81. package/dist/internal/compiler/registry.d.ts.map +1 -1
  82. package/dist/internal/compiler/registry.js +21 -41
  83. package/dist/internal/compiler/registry.js.map +1 -1
  84. package/dist/internal/compiler/sets.d.ts +9 -13
  85. package/dist/internal/compiler/sets.d.ts.map +1 -1
  86. package/dist/internal/compiler/sets.js +76 -73
  87. package/dist/internal/compiler/sets.js.map +1 -1
  88. package/dist/internal/entries.d.ts +3 -3
  89. package/dist/internal/entries.d.ts.map +1 -1
  90. package/dist/internal/entries.js +38 -30
  91. package/dist/internal/entries.js.map +1 -1
  92. package/dist/internal/node.d.ts +177 -173
  93. package/dist/internal/node.d.ts.map +1 -1
  94. package/dist/internal/node.js +77 -66
  95. package/dist/internal/node.js.map +1 -1
  96. package/dist/internal/numbers.d.ts +7 -8
  97. package/dist/internal/numbers.d.ts.map +1 -1
  98. package/dist/internal/numbers.js +246 -276
  99. package/dist/internal/numbers.js.map +1 -1
  100. package/dist/internal/resume.d.ts +6 -24
  101. package/dist/internal/resume.d.ts.map +1 -1
  102. package/dist/internal/resume.js +30 -29
  103. package/dist/internal/resume.js.map +1 -1
  104. package/dist/internal/run.d.ts +15 -0
  105. package/dist/internal/run.d.ts.map +1 -0
  106. package/dist/internal/run.js +36 -0
  107. package/dist/internal/run.js.map +1 -0
  108. package/dist/internal/stack.d.ts +16 -0
  109. package/dist/internal/stack.d.ts.map +1 -0
  110. package/dist/internal/stack.js +26 -0
  111. package/dist/internal/stack.js.map +1 -0
  112. package/dist/internal/syntax.d.ts +146 -0
  113. package/dist/internal/syntax.d.ts.map +1 -0
  114. package/dist/internal/syntax.js +305 -0
  115. package/dist/internal/syntax.js.map +1 -0
  116. package/dist/internal/text.d.ts +10 -2
  117. package/dist/internal/text.d.ts.map +1 -1
  118. package/dist/internal/text.js +295 -345
  119. package/dist/internal/text.js.map +1 -1
  120. package/dist/internal/tokens.d.ts +25 -30
  121. package/dist/internal/tokens.d.ts.map +1 -1
  122. package/dist/internal/tokens.js +369 -363
  123. package/dist/internal/tokens.js.map +1 -1
  124. package/package.json +42 -28
  125. package/src/Ascii.ts +278 -187
  126. package/src/Binary.ts +150 -44
  127. package/src/Bits.ts +6 -3
  128. package/src/Compiler.ts +98 -0
  129. package/src/Expression.ts +10 -5
  130. package/src/Input.ts +106 -28
  131. package/src/Nom.ts +4 -3
  132. package/src/ParseError.ts +48 -51
  133. package/src/Parser.ts +1163 -795
  134. package/src/ParserStream.ts +104 -80
  135. package/src/Syntax.ts +900 -0
  136. package/src/Text.ts +272 -187
  137. package/src/Token.ts +180 -87
  138. package/src/index.ts +2 -0
  139. package/src/internal/compiler/closure.ts +121 -88
  140. package/src/internal/compiler/entries.ts +21 -8
  141. package/src/internal/compiler/first.ts +17 -15
  142. package/src/internal/compiler/jit.ts +360 -157
  143. package/src/internal/compiler/registry.ts +12 -33
  144. package/src/internal/compiler/sets.ts +17 -11
  145. package/src/internal/entries.ts +4 -2
  146. package/src/internal/node.ts +51 -37
  147. package/src/internal/numbers.ts +22 -20
  148. package/src/internal/resume.ts +8 -4
  149. package/src/internal/run.ts +41 -0
  150. package/src/internal/stack.ts +36 -0
  151. package/src/internal/syntax.ts +421 -0
  152. package/src/internal/text.ts +32 -25
  153. package/src/internal/tokens.ts +96 -51
  154. package/dist/index.d.ts.map +0 -1
  155. package/dist/index.js.map +0 -1
package/dist/Token.js CHANGED
@@ -1,294 +1,360 @@
1
- import { advance, compileAny, countTokens, describeBytes, End, indexOf, matchLiteral, nextIf, NoMatch, scan, splitSurrogate } from "./internal/tokens.js";
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
- * Creates an inclusive token range (winnow's `'a'..='z'`).
6
- *
7
- * @since 0.1.0
8
- * @category constructors
9
- */
10
- export const range = (from, to) => ({ _tag: "TokenRange", from, to });
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
- const pos = state.pos;
14
- if (pos >= state.end)
15
- return state.eoi("Token", expectedAny, 1);
16
- switch (state.inputKind) {
17
- case 0: {
18
- const s = state.input;
19
- if (splitSurrogate(state, pos))
20
- return state.incomplete(1, expectedAny);
21
- const c = s.charCodeAt(pos);
22
- if (c >= 0xd800 && c <= 0xdbff && pos + 1 < s.length && (s.charCodeAt(pos + 1) & 0xfc00) === 0xdc00) {
23
- state.pos = pos + 2;
24
- return s.slice(pos, pos + 2);
25
- }
26
- state.pos = pos + 1;
27
- return s[pos];
28
- }
29
- case 1:
30
- state.pos = pos + 1;
31
- return state.input[pos];
32
- default:
33
- state.pos = pos + 1;
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
- * Matches any single token: a character of a string (winnow's `any`, nom's
39
- * `anychar`).
40
- *
41
- * @since 0.1.0
42
- * @category tokens
43
- */
44
- export const any = described(anyStep, "any", { _tag: "Any", encoding: undefined });
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
- * Matches any single token of an input of type `I`.
47
- *
48
- * @example
49
- * ```ts
50
- * import { Parser, Token } from "@thomasfosterau/effect-parse"
51
- *
52
- * const byte = Token.anyToken<Uint8Array>()
53
- * Parser.parse(byte, new Uint8Array([7])) // Result.succeed(7)
54
- * ```
55
- *
56
- * @since 0.1.0
57
- * @category tokens
58
- */
59
- export const anyToken = () => any;
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
- * Matches a literal sequence of tokens (winnow's `literal`, nom's `tag`).
62
- * Strings are matched against string input, `Uint8Array`s against byte
63
- * input, and arrays element-wise (with `===`) against array input.
64
- *
65
- * @example
66
- * ```ts
67
- * import { Parser, Token } from "@thomasfosterau/effect-parse"
68
- *
69
- * const keyword = Parser.alt(Token.literal("true"), Token.literal("false"))
70
- * // ^? Parser<"true" | "false">
71
- * ```
72
- *
73
- * @since 0.1.0
74
- * @category tokens
75
- */
76
- export const literal = (lit) => literalImpl(lit, false);
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
- export const literalImpl = (lit, caseless) => {
79
- const description = typeof lit === "string"
80
- ? JSON.stringify(lit)
81
- : lit instanceof Uint8Array
82
- ? describeBytes(lit)
83
- : `[${lit.map((t) => JSON.stringify(t)).join(", ")}]`;
84
- const expected = [caseless ? `${description} (case insensitive)` : description];
85
- // A string literal may also be matched against byte input (as UTF-8)
86
- let asBytes;
87
- const literalKind = typeof lit === "string" ? 0 : lit instanceof Uint8Array ? 1 : 2;
88
- return described((state) => {
89
- const pos = state.pos;
90
- const l = literalKind === 0 && state.inputKind === 1 ? (asBytes ??= new TextEncoder().encode(lit)) : lit;
91
- const len = l.length;
92
- const r = matchLiteral(state, l, caseless);
93
- if (r === -1)
94
- return state.backtrack("Literal", expected);
95
- if (r === -2) {
96
- if (state.partial)
97
- return state.incomplete(len - (state.end - pos), expected);
98
- return state.backtrack("Literal", expected);
99
- }
100
- state.pos = pos + len;
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
- * Matches one token belonging to a set, returning it (winnow's and nom's
106
- * `one_of`).
107
- *
108
- * @example
109
- * ```ts
110
- * import { Parser, Token } from "@thomasfosterau/effect-parse"
111
- *
112
- * const sign = Token.oneOf("+-")
113
- * const lower = Token.oneOf(Token.range("a", "z"))
114
- * const hexByte = Token.oneOf<Uint8Array>([Token.range(0x30, 0x39), Token.range(0x61, 0x66)])
115
- * ```
116
- *
117
- * @since 0.1.0
118
- * @category tokens
119
- */
120
- export const oneOf = (set) => {
121
- const m = compileAny(set);
122
- const expected = [m.description];
123
- return described((state) => {
124
- const t = nextIf(state, m, false);
125
- if (t === End)
126
- return state.eoi("OneOf", expected, 1);
127
- if (t === NoMatch)
128
- return state.backtrack("OneOf", expected);
129
- return t;
130
- }, m.description, { _tag: "OneOf", set, negate: false, encoding: undefined });
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
- * Matches one token *not* belonging to a set, returning it (winnow's and
134
- * nom's `none_of`).
135
- *
136
- * @since 0.1.0
137
- * @category tokens
138
- */
139
- export const noneOf = (set) => {
140
- const m = compileAny(set);
141
- const expected = [`anything but ${m.description}`];
142
- return described((state) => {
143
- const t = nextIf(state, m, true);
144
- if (t === End)
145
- return state.eoi("NoneOf", expected, 1);
146
- if (t === NoMatch)
147
- return state.backtrack("NoneOf", expected);
148
- return t;
149
- }, expected[0], { _tag: "OneOf", set, negate: true, encoding: undefined });
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
- * Takes exactly `count` tokens (winnow's and nom's `take`).
153
- *
154
- * @since 0.1.0
155
- * @category slices
156
- */
157
- export const take = (count) => {
158
- const expected = [count === 1 ? "1 token" : `${count} tokens`];
159
- return described((state) => {
160
- const start = state.pos;
161
- const { count: got, offset } = advance(state, start, count);
162
- if (got < count)
163
- return state.eoi("Take", expected, count - got);
164
- state.pos = offset;
165
- return state.slice(start, offset);
166
- }, "take", { _tag: "Take", count, encoding: undefined });
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
- if (r === undefined)
170
- return [0, Infinity];
171
- if (typeof r === "number")
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
- export const takeWhileImpl = (set, r, negate, name, description, kind = "TakeWhile", hint = false) => {
177
- const m = compileAny(set);
178
- const [min, max] = normalize(r);
179
- const expected = [description ?? (negate ? `anything but ${m.description}` : m.description)];
180
- return described((state) => {
181
- const start = state.pos;
182
- const { count, hitEnd, offset } = scan(state, m, negate, max);
183
- if (hitEnd && state.partial)
184
- return state.incomplete(1, expected);
185
- if (count < min)
186
- return state.backtrack(kind, expected, offset);
187
- // More matching tokens would have been accepted where we stopped
188
- if (hint && count < max)
189
- state.setHint(offset, expected);
190
- state.pos = offset;
191
- return state.slice(start, offset);
192
- }, name, { _tag: "TakeWhile", set, negate, min, max, encoding: undefined });
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
- * Takes the longest run of tokens belonging to a set, with the number of
196
- * tokens constrained by `range` (default: zero or more). This is winnow's
197
- * `take_while(range, set)`, and nom's `take_while`, `take_while1` and
198
- * `take_while_m_n`.
199
- *
200
- * @example
201
- * ```ts
202
- * import { Parser, Token } from "@thomasfosterau/effect-parse"
203
- *
204
- * const identifier = Token.takeWhile(
205
- * [Token.range("a", "z"), Token.range("A", "Z"), "_"],
206
- * { min: 1 }
207
- * )
208
- * ```
209
- *
210
- * @since 0.1.0
211
- * @category slices
212
- */
213
- export const takeWhile = (set, range) => takeWhileImpl(set, range, false, "takeWhile");
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
- * Takes the longest run of tokens *not* belonging to a set (winnow's
216
- * `take_till`, nom's `take_till` and `take_till1`).
217
- *
218
- * @since 0.1.0
219
- * @category slices
220
- */
221
- export const takeTill = (set, range) => takeWhileImpl(set, range, true, "takeTill");
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
- * Takes tokens up to (not including) the first occurrence of a literal
224
- * (winnow's `take_until`, nom's `take_until`). The literal is not
225
- * consumed. `range` constrains the number of tokens taken.
226
- *
227
- * @since 0.1.0
228
- * @category slices
229
- */
230
- export const takeUntil = (lit, r) => {
231
- const [min, max] = normalize(r);
232
- const description = typeof lit === "string"
233
- ? JSON.stringify(lit)
234
- : lit instanceof Uint8Array
235
- ? describeBytes(lit)
236
- : `[${lit.map((t) => JSON.stringify(t)).join(", ")}]`;
237
- const expected = [description];
238
- return described((state) => {
239
- const start = state.pos;
240
- const idx = indexOf(state, lit, start);
241
- if (idx < 0) {
242
- if (state.partial)
243
- return state.incomplete(0, expected);
244
- return state.backtrack("TakeUntil", expected, state.end);
245
- }
246
- // As in winnow, the first occurrence must lie within the range
247
- if (min > 0 || max !== Infinity) {
248
- const count = countTokens(state, start, idx);
249
- if (count < min)
250
- return state.backtrack("TakeUntil", expected, idx);
251
- if (count > max)
252
- return state.backtrack("TakeUntil", expected);
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
- * Takes the rest of the input (winnow's and nom's `rest`).
260
- *
261
- * @since 0.1.0
262
- * @category slices
263
- */
264
- export const rest = described((state) => {
265
- const start = state.pos;
266
- state.pos = state.end;
267
- return state.slice(start, state.end);
268
- }, "rest", { _tag: "Rest", encoding: undefined });
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
- * Takes the rest of an input of type `I`.
271
- *
272
- * @since 0.1.0
273
- * @category slices
274
- */
275
- export const restOf = () => rest;
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
- * Returns the length of the remaining input without consuming it (winnow's
278
- * and nom's `rest_len`).
279
- *
280
- * @since 0.1.0
281
- * @category slices
282
- */
283
- export const restLen = described((state) => state.end - state.pos, "restLen", {
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
- * Matches a token satisfying a predicate (nom's `satisfy`). Equivalent to
288
- * `Token.oneOf(predicate)`.
289
- *
290
- * @since 0.1.0
291
- * @category tokens
292
- */
293
- export const satisfy = (predicate) => oneOf(predicate);
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