@thomasfosterau/effect-parse 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/README.md +291 -231
  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 +151 -132
  25. package/dist/Expression.js.map +1 -1
  26. package/dist/Input.d.ts +251 -177
  27. package/dist/Input.d.ts.map +1 -1
  28. package/dist/Input.js +409 -299
  29. package/dist/Input.js.map +1 -1
  30. package/dist/Nom.d.ts +45 -85
  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 +232 -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 +2034 -1802
  41. package/dist/Parser.js.map +1 -1
  42. package/dist/ParserSchema.d.ts +206 -7
  43. package/dist/ParserSchema.d.ts.map +1 -1
  44. package/dist/ParserSchema.js +678 -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 +36 -0
  111. package/dist/internal/stack.js.map +1 -0
  112. package/dist/internal/syntax.d.ts +147 -0
  113. package/dist/internal/syntax.d.ts.map +1 -0
  114. package/dist/internal/syntax.js +309 -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/ties.d.ts +30 -0
  121. package/dist/internal/ties.d.ts.map +1 -0
  122. package/dist/internal/ties.js +67 -0
  123. package/dist/internal/ties.js.map +1 -0
  124. package/dist/internal/tokens.d.ts +25 -30
  125. package/dist/internal/tokens.d.ts.map +1 -1
  126. package/dist/internal/tokens.js +369 -363
  127. package/dist/internal/tokens.js.map +1 -1
  128. package/package.json +42 -28
  129. package/src/Ascii.ts +278 -187
  130. package/src/Binary.ts +150 -44
  131. package/src/Bits.ts +6 -3
  132. package/src/Compiler.ts +98 -0
  133. package/src/Expression.ts +24 -16
  134. package/src/Input.ts +210 -35
  135. package/src/Nom.ts +4 -3
  136. package/src/ParseError.ts +49 -52
  137. package/src/Parser.ts +1199 -799
  138. package/src/ParserSchema.ts +982 -23
  139. package/src/ParserStream.ts +104 -80
  140. package/src/Syntax.ts +900 -0
  141. package/src/Text.ts +272 -187
  142. package/src/Token.ts +180 -87
  143. package/src/index.ts +2 -0
  144. package/src/internal/compiler/closure.ts +121 -88
  145. package/src/internal/compiler/entries.ts +21 -8
  146. package/src/internal/compiler/first.ts +17 -15
  147. package/src/internal/compiler/jit.ts +360 -157
  148. package/src/internal/compiler/registry.ts +12 -33
  149. package/src/internal/compiler/sets.ts +17 -11
  150. package/src/internal/entries.ts +4 -2
  151. package/src/internal/node.ts +51 -37
  152. package/src/internal/numbers.ts +22 -20
  153. package/src/internal/resume.ts +8 -4
  154. package/src/internal/run.ts +41 -0
  155. package/src/internal/stack.ts +41 -0
  156. package/src/internal/syntax.ts +426 -0
  157. package/src/internal/text.ts +32 -25
  158. package/src/internal/ties.ts +83 -0
  159. package/src/internal/tokens.ts +96 -51
  160. package/dist/index.d.ts.map +0 -1
  161. package/dist/index.js.map +0 -1
@@ -1,1668 +1,1489 @@
1
+ import * as Predicate from "effect/Predicate";
1
2
  import { Fail } from "../../Input.js";
3
+ import { floatScan, floatTexts, scanFloatBytes, scanFloatString, toFloat } from "../numbers.js";
4
+ import * as Resume from "../resume.js";
5
+ import { countTokens, indexOf } from "../tokens.js";
2
6
  import * as Option from "effect/Option";
7
+ import { charOf, fastLimit, firstCodePoint, fold, validate } from "../text.js";
3
8
  import { addEntry, flushEntries, fromEntries, isPlainKey } from "../entries.js";
4
9
  import { nodeOf } from "../node.js";
5
- import { floatScan, floatTexts, scanFloatBytes, scanFloatString, toFloat } from "../numbers.js";
6
- import { charOf, fastLimit, fold, validate } from "../text.js";
7
- import { countTokens, indexOf } from "../tokens.js";
8
- import * as Resume from "../resume.js";
9
- import { entriesShape, pairOf } from "./entries.js";
10
+ import { buildsEntries, pairOf } from "./entries.js";
10
11
  import { FirstSets, planAlt } from "./first.js";
11
- import { kindOfEncoding, TableSize, textSet, tokenSet } from "./sets.js";
12
+ import { TableSize, kindOfEncoding, textSet, tokenSet } from "./sets.js";
13
+ //#region src/internal/compiler/closure.ts
14
+ /**
15
+ * The closure compiler: turns a parser's description into specialized
16
+ * closures with the step signature. Compiled steps return a value, or
17
+ * `Fail` with only `state.mode` set: no diagnostics are recorded.
18
+ *
19
+ * Nothing here generates code, so it works under a Content Security
20
+ * Policy. Parsers that can't be compiled run their own (interpreted) steps
21
+ * on the same state.
22
+ */
12
23
  /** The maximum number of distinct parsers compiled for one root. */
13
- export const maxNodes = 2048;
24
+ const maxNodes = 2048;
14
25
  const BT = "Backtrack";
15
26
  const CUT = "Cut";
16
27
  const INC = "Incomplete";
17
28
  /**
18
- * How many units past the cursor a single token can depend on (a code
19
- * point is at most 4 units). In a partial parse, a token parser that read
20
- * no closer than this to the end of the input behaves exactly as on
21
- * complete input.
22
- */
29
+ * How many units past the cursor a single token can depend on (a code
30
+ * point is at most 4 units). In a partial parse, a token parser that read
31
+ * no closer than this to the end of the input behaves exactly as on
32
+ * complete input.
33
+ */
23
34
  const Margin = 4;
24
35
  const lowerAscii = (c) => c >= 65 && c <= 90 ? c + 32 : c;
25
36
  const isSuccess = (r) => r._tag === "Success";
26
37
  const isSome = (o) => o._tag === "Some";
27
- class Compiler {
28
- kind;
29
- resumable;
30
- used = new Map();
31
- unused = new Map();
32
- firsts;
33
- fallbacks = [];
34
- fellBack = new Set();
35
- budget = maxNodes;
36
- /**
37
- * `resumable`: compile for streaming parses, which may be partial (see
38
- * `state.partial`) and keep checkpoints (see `internal/resume.ts`).
39
- */
40
- constructor(kind, resumable = false) {
41
- this.kind = kind;
42
- this.resumable = resumable;
43
- this.firsts = new FirstSets(kind);
44
- }
45
- /**
46
- * In a resumable build, runs the compiled token parser `step`, and falls
47
- * back to the interpreted one when it read within `lookahead` units of
48
- * the end of a partial input, where it might have to report `Incomplete`.
49
- * Compiled token parsers leave `state.pos` where they stopped reading,
50
- * even when they fail.
51
- */
52
- partialSafe(p, step, lookahead) {
53
- if (!this.resumable)
54
- return step;
55
- const interpreted = p.step;
56
- const ahead = Math.max(lookahead, Margin);
57
- return (s) => {
58
- if (!s.partial)
59
- return step(s);
60
- const start = s.pos;
61
- const r = step(s);
62
- if (s.pos + ahead <= s.end)
63
- return r;
64
- s.pos = start;
65
- return interpreted(s);
66
- };
67
- }
68
- /** Compiles `p`; when `used` is false its output is not needed. */
69
- compile(p, used) {
70
- const memo = used ? this.used : this.unused;
71
- const slot = memo.get(p);
72
- if (slot !== undefined) {
73
- if (slot.fn !== undefined)
74
- return slot.fn;
75
- return (s) => slot.fn(s); // a cycle through `suspend`
76
- }
77
- const fresh = { fn: undefined };
78
- memo.set(p, fresh);
79
- const node = nodeOf(p);
80
- const fn = --this.budget < 0 ? this.fallback(p, node, "node budget exceeded") : this.build(p, node, used);
81
- fresh.fn = fn;
82
- return fn;
83
- }
84
- fallback(p, node, reason) {
85
- this.note(p, node, reason);
86
- return p.step;
87
- }
88
- /** Records that (part of) `p` runs interpreted. */
89
- note(p, node, reason) {
90
- if (!this.fellBack.has(p)) {
91
- this.fellBack.add(p);
92
- this.fallbacks.push({ name: p.name, tag: node._tag, reason });
93
- }
94
- }
95
- /** Whether a token node reads this input kind natively. */
96
- native(enc) {
97
- return enc === undefined ? this.kind !== 2 : kindOfEncoding(enc) === this.kind;
98
- }
99
- build(p, node, used) {
100
- switch (node._tag) {
101
- case "Opaque":
102
- return this.fallback(p, node, "not describable (Parser.make, gen, ...)");
103
- case "Succeed": {
104
- const value = node.value;
105
- return () => value;
106
- }
107
- case "Sync": {
108
- const evaluate = node.evaluate;
109
- return used ? () => evaluate() : () => undefined;
110
- }
111
- case "Fail": {
112
- const mode = node.mode;
113
- return (s) => {
114
- s.mode = mode;
115
- return Fail;
116
- };
117
- }
118
- case "Eof":
119
- return (s) => {
120
- if (s.pos < s.end) {
121
- s.mode = BT;
122
- return Fail;
123
- }
124
- if (s.partial) {
125
- s.mode = INC;
126
- return Fail;
127
- }
128
- return undefined;
129
- };
130
- case "Location":
131
- return (s) => s.pos;
132
- case "RestLen":
133
- return (s) => s.end - s.pos;
134
- case "Suspend":
135
- return this.compile(node.resolve(), used);
136
- case "Any":
137
- case "Literal":
138
- case "OneOf":
139
- case "Take":
140
- case "TakeWhile":
141
- case "TakeUntil":
142
- case "Rest":
143
- if (!this.native(node.encoding))
144
- return this.fallback(p, node, "token parser on array input");
145
- return this.partialSafe(p, node.encoding === undefined ? this.token(p, node, used) : this.text(p, node, node.encoding, used), node._tag === "Literal" || node._tag === "TakeUntil" ? node.literal.length * 4 : Margin);
146
- case "TillLineEnding":
147
- case "Identifier":
148
- case "Bom":
149
- return this.fallback(p, node, "leaf parser without a compiled form");
150
- case "Escaped":
151
- if (!this.native(node.encoding))
152
- return this.fallback(p, node, "token parser on array input");
153
- return this.escaped(node);
154
- case "Map": {
155
- if (!used)
156
- return this.compile(node.self, false);
157
- if (node.f === toFloat) {
158
- const step = this.float(node);
159
- if (step !== undefined)
160
- return step;
161
- }
162
- // Streaming builds keep the array, which their checkpoints hold
163
- if (node.f === fromEntries && !this.resumable && entriesShape(node.self))
164
- return this.entries(node.self);
165
- const c = this.compile(node.self, true);
166
- const f = node.f;
167
- return (s) => {
168
- const a = c(s);
169
- return a === Fail ? Fail : f(a);
170
- };
171
- }
172
- case "As": {
173
- const c = this.compile(node.self, false);
174
- if (!used)
175
- return c;
176
- const value = node.value;
177
- return (s) => c(s) === Fail ? Fail : value;
178
- }
179
- case "Tap": {
180
- const c = this.compile(node.self, true);
181
- const f = node.f;
182
- return (s) => {
183
- const a = c(s);
184
- if (a !== Fail)
185
- f(a);
186
- return a;
187
- };
188
- }
189
- case "TryMap": {
190
- const c = this.compile(node.self, true);
191
- const f = node.f;
192
- return (s) => {
193
- const a = c(s);
194
- if (a === Fail)
195
- return Fail;
196
- const r = f(a);
197
- if (isSuccess(r))
198
- return r.success;
199
- s.mode = BT;
200
- return Fail;
201
- };
202
- }
203
- case "FilterMap": {
204
- const c = this.compile(node.self, true);
205
- const f = node.f;
206
- return (s) => {
207
- const a = c(s);
208
- if (a === Fail)
209
- return Fail;
210
- const o = f(a);
211
- if (isSome(o))
212
- return o.value;
213
- s.mode = BT;
214
- return Fail;
215
- };
216
- }
217
- case "Filter": {
218
- const c = this.compile(node.self, true);
219
- const predicate = node.predicate;
220
- return (s) => {
221
- const a = c(s);
222
- if (a === Fail)
223
- return Fail;
224
- if (predicate(a))
225
- return a;
226
- s.mode = BT;
227
- return Fail;
228
- };
229
- }
230
- case "FlatMap": {
231
- // The parser returned by `f` runs interpreted
232
- const c = this.compile(node.self, true);
233
- const f = node.f;
234
- this.note(p, node, "the parser returned by the function runs interpreted");
235
- return (s) => {
236
- const a = c(s);
237
- return a === Fail ? Fail : f(a).step(s);
238
- };
239
- }
240
- case "Taken":
241
- if (node.encoding !== undefined && !this.native(node.encoding)) {
242
- return this.fallback(p, node, "Text parser on another input kind");
243
- }
244
- return this.taken(node, used);
245
- case "WithTaken": {
246
- const c = this.compile(node.self, true);
247
- return (s) => {
248
- const start = s.pos;
249
- const a = c(s);
250
- return a === Fail ? Fail : [a, s.slice(start, s.pos)];
251
- };
252
- }
253
- case "Span": {
254
- const c = this.compile(node.self, false);
255
- if (!used)
256
- return c;
257
- return (s) => {
258
- const start = s.pos;
259
- return c(s) === Fail ? Fail : { start, end: s.pos };
260
- };
261
- }
262
- case "WithSpan": {
263
- const c = this.compile(node.self, true);
264
- return (s) => {
265
- const start = s.pos;
266
- const a = c(s);
267
- return a === Fail ? Fail : [a, { start, end: s.pos }];
268
- };
269
- }
270
- case "Mode": {
271
- const c = this.compile(node.self, used);
272
- const from = node.from;
273
- const to = node.to;
274
- return (s) => {
275
- const a = c(s);
276
- if (a === Fail && s.mode === from)
277
- s.mode = to;
278
- return a;
279
- };
280
- }
281
- case "Context":
282
- case "Expected":
283
- case "MapError":
284
- case "OrFail":
285
- case "Trace":
286
- case "RetryAfter":
287
- // Diagnostics only, or inactive outside parseRecoverable / tracing
288
- return this.compile(node.self, used);
289
- case "ResumeAfter": {
290
- const c = this.compile(node.self, used);
291
- if (!used)
292
- return c;
293
- return (s) => {
294
- const a = c(s);
295
- return a === Fail ? Fail : Option.some(a);
296
- };
297
- }
298
- case "Opt":
299
- case "OrElseSucceed": {
300
- const c = this.compile(node.self, used);
301
- const orElse = !used ? undefined : node._tag === "Opt" ? Option.none : node.value;
302
- const some = used && node._tag === "Opt";
303
- return (s) => {
304
- const start = s.pos;
305
- const a = c(s);
306
- if (a !== Fail)
307
- return some ? Option.some(a) : a;
308
- if (s.mode !== BT)
309
- return Fail;
310
- s.pos = start;
311
- return orElse === undefined ? undefined : orElse();
312
- };
313
- }
314
- case "Peek": {
315
- const c = this.compile(node.self, used);
316
- return (s) => {
317
- const start = s.pos;
318
- const a = c(s);
319
- if (a !== Fail)
320
- s.pos = start;
321
- return a;
322
- };
323
- }
324
- case "Not": {
325
- const c = this.compile(node.self, false);
326
- return (s) => {
327
- const start = s.pos;
328
- if (c(s) !== Fail) {
329
- s.pos = start;
330
- s.mode = BT;
331
- return Fail;
332
- }
333
- if (s.mode !== BT)
334
- return Fail;
335
- s.pos = start;
336
- return undefined;
337
- };
338
- }
339
- case "Seq":
340
- return this.seq(node, used);
341
- case "Struct": {
342
- const keys = node.keys;
343
- const steps = node.parsers.map((q) => this.compile(q, used));
344
- const n = steps.length;
345
- if (!used)
346
- return this.chain(steps);
347
- return (s) => {
348
- const out = {};
349
- for (let i = 0; i < n; i++) {
350
- const a = steps[i](s);
351
- if (a === Fail)
352
- return Fail;
353
- out[keys[i]] = a;
354
- }
355
- return out;
356
- };
357
- }
358
- case "ZipWith": {
359
- const c1 = this.compile(node.self, used);
360
- const c2 = this.compile(node.that, used);
361
- if (!used)
362
- return this.chain([c1, c2]);
363
- const f = node.f;
364
- return (s) => {
365
- const a = c1(s);
366
- if (a === Fail)
367
- return Fail;
368
- const b = c2(s);
369
- return b === Fail ? Fail : f(a, b);
370
- };
371
- }
372
- case "Alt":
373
- return this.alt(node, used);
374
- case "Dispatch":
375
- return this.dispatch(p, node, used);
376
- case "Repeat":
377
- case "Fold":
378
- return this.repeat(node, used);
379
- case "RepeatTill":
380
- return this.repeatTill(node);
381
- case "Separated":
382
- return this.separated(node, used);
383
- case "SeparatedFold":
384
- return this.separatedFold(node);
385
- case "Service":
386
- case "Provide":
387
- return this.fallback(p, node, "services stay interpreted");
388
- }
389
- }
390
- /** Runs steps in order, for their effect on the cursor only. */
391
- chain(steps) {
392
- const n = steps.length;
393
- if (n === 0)
394
- return () => undefined;
395
- if (n === 1)
396
- return steps[0];
397
- if (n === 2) {
398
- const [a, b] = steps;
399
- return (s) => a(s) === Fail ? Fail : b(s);
400
- }
401
- return (s) => {
402
- for (let i = 0; i < n; i++)
403
- if (steps[i](s) === Fail)
404
- return Fail;
405
- return undefined;
406
- };
407
- }
408
- seq(node, used) {
409
- const output = node.output;
410
- const keep = (i) => used && (output === "tuple" || output === i || (typeof output === "object" && output.includes(i)));
411
- const steps = node.parsers.map((q, i) => this.compile(q, keep(i)));
412
- const n = steps.length;
413
- if (!used)
414
- return this.chain(steps);
415
- if (output === "tuple") {
416
- return (s) => {
417
- const out = new Array(n);
418
- for (let i = 0; i < n; i++) {
419
- const a = steps[i](s);
420
- if (a === Fail)
421
- return Fail;
422
- out[i] = a;
423
- }
424
- return out;
425
- };
426
- }
427
- if (typeof output === "number") {
428
- if (n === 2) {
429
- const [a, b] = steps;
430
- return output === 0
431
- ? (s) => {
432
- const x = a(s);
433
- if (x === Fail)
434
- return Fail;
435
- return b(s) === Fail ? Fail : x;
436
- }
437
- : (s) => a(s) === Fail ? Fail : b(s);
438
- }
439
- return (s) => {
440
- let out;
441
- for (let i = 0; i < n; i++) {
442
- const a = steps[i](s);
443
- if (a === Fail)
444
- return Fail;
445
- if (i === output)
446
- out = a;
447
- }
448
- return out;
449
- };
450
- }
451
- const [i0, i1] = output;
452
- return (s) => {
453
- let x;
454
- let y;
455
- for (let i = 0; i < n; i++) {
456
- const a = steps[i](s);
457
- if (a === Fail)
458
- return Fail;
459
- if (i === i0)
460
- x = a;
461
- else if (i === i1)
462
- y = a;
463
- }
464
- return [x, y];
465
- };
466
- }
467
- /** The unit at the cursor, or -1 at the end of the input. */
468
- unitReader() {
469
- return this.kind === 0
470
- ? (s) => s.pos < s.end ? s.input.charCodeAt(s.pos) : -1
471
- : (s) => s.pos < s.end ? s.input[s.pos] : -1;
472
- }
473
- alt(node, used) {
474
- const steps = node.parsers.map((q) => this.compile(q, used));
475
- const n = steps.length;
476
- if (n === 0) {
477
- return (s) => {
478
- s.mode = BT;
479
- return Fail;
480
- };
481
- }
482
- if (n === 1)
483
- return steps[0];
484
- const plan = this.kind === 2
485
- ? undefined
486
- : planAlt(node.parsers.map((q) => this.firsts.of(q)));
487
- if (plan === undefined) {
488
- return (s) => {
489
- const start = s.pos;
490
- for (let i = 0; i < n; i++) {
491
- const a = steps[i](s);
492
- if (a !== Fail)
493
- return a;
494
- if (s.mode !== BT)
495
- return Fail;
496
- s.pos = start;
497
- }
498
- s.mode = BT;
499
- return Fail;
500
- };
501
- }
502
- const lists = plan.lists.map((l) => l.map((i) => steps[i]));
503
- const { byUnit, end, high } = plan;
504
- const unit = this.unitReader();
505
- const resumable = this.resumable;
506
- return (s) => {
507
- // Near the end of a partial input, branches may be incomplete rather than fail
508
- const u = resumable && s.partial && s.pos + Margin > s.end ? -2 : unit(s);
509
- const candidates = u === -2 ? steps : lists[u < 0 ? end : u < TableSize ? byUnit[u] : high];
510
- const start = s.pos;
511
- for (let i = 0; i < candidates.length; i++) {
512
- const a = candidates[i](s);
513
- if (a !== Fail)
514
- return a;
515
- if (s.mode !== BT)
516
- return Fail;
517
- s.pos = start;
518
- }
519
- s.mode = BT;
520
- return Fail;
521
- };
522
- }
523
- dispatch(p, node, used) {
524
- const selector = this.compile(node.selector, true);
525
- const choose = node.choose;
526
- const compiled = new Map();
527
- if (node.cases !== undefined) {
528
- for (const key of Reflect.ownKeys(node.cases)) {
529
- const q = node.cases[key];
530
- if (!compiled.has(q))
531
- compiled.set(q, this.compile(q, used));
532
- }
533
- }
534
- if (node.otherwise !== undefined && !compiled.has(node.otherwise)) {
535
- compiled.set(node.otherwise, this.compile(node.otherwise, used));
536
- }
537
- const general = (s) => {
538
- const start = s.pos;
539
- const key = selector(s);
540
- if (key === Fail)
541
- return Fail;
542
- const q = choose(key);
543
- if (q === undefined) {
544
- s.pos = start;
545
- s.mode = BT;
546
- return Fail;
547
- }
548
- return (compiled.get(q) ?? q.step)(s);
549
- };
550
- if (node.cases === undefined) {
551
- this.note(p, node, "the parser returned by the function of cases runs interpreted");
552
- return general;
553
- }
554
- // Switch on the next unit when the selector is `any` or `peek(any)`
555
- let sel = nodeOf(node.selector);
556
- const peek = sel._tag === "Peek";
557
- if (peek)
558
- sel = nodeOf(sel.self);
559
- if (sel._tag !== "Any" || !this.native(sel.encoding))
560
- return general;
561
- const enc = sel.encoding;
562
- // Units below `limit` are whole tokens, so the key is known in advance
563
- const limit = enc === undefined ? (this.kind === 0 ? 0xd800 : TableSize) : Math.min(fastLimit(enc), 0xd800);
564
- const size = Math.min(limit, TableSize);
565
- if (size === 0)
566
- return general;
567
- const table = [];
568
- for (let u = 0; u < size; u++) {
569
- const key = enc === undefined && this.kind === 1 ? u : charOf(u);
570
- const q = choose(key);
571
- table.push(q === undefined ? null : compiled.get(q) ?? q.step);
572
- }
573
- const unit = this.unitReader();
574
- const advance = peek ? 0 : 1;
575
- const resumable = this.resumable;
576
- return (s) => {
577
- if (resumable && s.partial && s.pos + Margin > s.end)
578
- return general(s);
579
- const u = unit(s);
580
- if (u < 0) {
581
- s.mode = BT;
582
- return Fail;
583
- }
584
- if (u >= size)
585
- return general(s);
586
- const q = table[u];
587
- if (q === null) {
588
- s.mode = BT;
589
- return Fail;
590
- }
591
- s.pos += advance;
592
- return q(s);
593
- };
594
- }
595
- repeat(node, used) {
596
- const { max, min } = node;
597
- const checkLoop = max === Infinity;
598
- const isFold = node._tag === "Fold";
599
- const c = this.compile(node.self, used);
600
- const resumable = this.resumable;
601
- const key = {};
602
- // The accumulator: an array, the fold's value, or nothing when unused
603
- const init = !used ? () => undefined : isFold ? node.init : () => [];
604
- const add = !used
605
- ? (acc) => acc
606
- : isFold
607
- ? node.f
608
- : (acc, a) => {
609
- acc.push(a);
610
- return acc;
611
- };
612
- return (s) => {
613
- const entry = s.pos;
614
- let acc;
615
- let count = 0;
616
- let resumed = false;
617
- if (resumable && s.resume !== undefined) {
618
- const cp = Resume.take(s, key, entry);
619
- if (cp instanceof Resume.Done) {
620
- s.pos = cp.pos;
621
- return cp.value;
622
- }
623
- if (cp !== undefined) {
624
- acc = cp.acc;
625
- count = cp.count;
626
- s.pos = cp.pos;
627
- resumed = true;
628
- }
629
- }
630
- if (!resumed)
631
- acc = init();
632
- for (; count < max; count++) {
633
- const start = s.pos;
634
- const a = c(s);
635
- if (a === Fail) {
636
- if (s.mode === INC && s.resume !== undefined)
637
- Resume.save(s, key, entry, { acc, count, pos: start });
638
- if (s.mode !== BT || count < min)
639
- return Fail;
640
- s.pos = start;
641
- return resumed ? Resume.done(s, key, entry, true, acc) : acc;
642
- }
643
- if (checkLoop && s.pos === start) {
644
- s.mode = CUT;
645
- return Fail;
646
- }
647
- acc = add(acc, a);
648
- }
649
- return resumed ? Resume.done(s, key, entry, true, acc) : acc;
650
- };
651
- }
652
- /**
653
- * `map(self, Object.fromEntries)`, where `entriesShape(self)`: builds the
654
- * object directly (see the JIT).
655
- */
656
- entries(p) {
657
- const node = nodeOf(p);
658
- switch (node._tag) {
659
- case "Mode": {
660
- const c = this.entries(node.self);
661
- const from = node.from;
662
- const to = node.to;
663
- return (s) => {
664
- const a = c(s);
665
- if (a === Fail && s.mode === from)
666
- s.mode = to;
667
- return a;
668
- };
669
- }
670
- case "Seq": {
671
- const i = node.output;
672
- const steps = node.parsers.map((q, j) => j === i ? this.entries(q) : this.compile(q, false));
673
- return (s) => {
674
- let out;
675
- for (let j = 0; j < steps.length; j++) {
676
- const a = steps[j](s);
677
- if (a === Fail)
678
- return Fail;
679
- if (j === i)
680
- out = a;
681
- }
682
- return out;
683
- };
684
- }
685
- case "Repeat":
686
- case "Separated":
687
- return this.entriesLoop(node);
688
- default:
689
- return this.entries(node.self);
690
- }
691
- }
692
- entriesLoop(node) {
693
- const pair = pairOf(node.self);
694
- const parts = pair.parsers.map((q, j) => this.compile(q, j === pair.key || j === pair.value));
695
- const { key: ki, value: vi } = pair;
696
- // Parses an entry and adds it to `acc`
697
- const entry = (s, acc) => {
698
- let key;
699
- let value;
700
- for (let j = 0; j < parts.length; j++) {
701
- const a = parts[j](s);
702
- if (a === Fail)
703
- return false;
704
- if (j === ki)
705
- key = a;
706
- else if (j === vi)
707
- value = a;
708
- }
709
- acc.add(key, value);
710
- return true;
711
- };
712
- const { max, min } = node;
713
- const checkLoop = max === Infinity;
714
- if (node._tag === "Repeat") {
715
- return (s) => {
716
- const acc = new EntriesAcc();
717
- for (let count = 0; count < max; count++) {
718
- const start = s.pos;
719
- let key;
720
- let value;
721
- let ok = true;
722
- for (let j = 0; j < parts.length; j++) {
723
- const a = parts[j](s);
724
- if (a === Fail) {
725
- ok = false;
726
- break;
727
- }
728
- if (j === ki)
729
- key = a;
730
- else if (j === vi)
731
- value = a;
732
- }
733
- if (!ok) {
734
- if (s.mode !== BT || count < min)
735
- return Fail;
736
- s.pos = start;
737
- return acc.result();
738
- }
739
- if (checkLoop && s.pos === start) {
740
- s.mode = CUT;
741
- return Fail;
742
- }
743
- acc.add(key, value);
744
- }
745
- return acc.result();
746
- };
747
- }
748
- const sep = this.compile(node.separator, false);
749
- return (s) => {
750
- const acc = new EntriesAcc();
751
- let count = 0;
752
- if (max === 0)
753
- return acc.result();
754
- let start = s.pos;
755
- if (!entry(s, acc)) {
756
- if (s.mode !== BT || min > 0)
757
- return Fail;
758
- s.pos = start;
759
- return acc.result();
760
- }
761
- count++;
762
- while (count < max) {
763
- start = s.pos;
764
- if (sep(s) === Fail) {
765
- if (s.mode !== BT || count < min)
766
- return Fail;
767
- s.pos = start;
768
- return acc.result();
769
- }
770
- if (checkLoop && s.pos === start) {
771
- s.mode = CUT;
772
- return Fail;
773
- }
774
- if (!entry(s, acc)) {
775
- if (s.mode !== BT || count < min)
776
- return Fail;
777
- s.pos = start;
778
- return acc.result();
779
- }
780
- count++;
781
- }
782
- return acc.result();
783
- };
784
- }
785
- repeatTill(node) {
786
- const { max, min } = node;
787
- const c = this.compile(node.self, true);
788
- const end = this.compile(node.end, true);
789
- return (s) => {
790
- const acc = [];
791
- while (true) {
792
- const start = s.pos;
793
- if (acc.length >= min) {
794
- const b = end(s);
795
- if (b !== Fail)
796
- return [acc, b];
797
- if (s.mode !== BT)
798
- return Fail;
799
- s.pos = start;
800
- if (acc.length >= max)
801
- return Fail;
802
- }
803
- const a = c(s);
804
- if (a === Fail)
805
- return Fail;
806
- if (s.pos === start) {
807
- s.mode = CUT;
808
- return Fail;
809
- }
810
- acc.push(a);
811
- }
812
- };
813
- }
814
- separated(node, used) {
815
- const { max, min } = node;
816
- const checkLoop = max === Infinity;
817
- const c = this.compile(node.self, used);
818
- const sep = this.compile(node.separator, false);
819
- const resumable = this.resumable;
820
- const key = {};
821
- return (s) => {
822
- const entry = s.pos;
823
- let acc;
824
- let count = 0;
825
- let resumed = false;
826
- if (resumable && s.resume !== undefined) {
827
- const cp = Resume.take(s, key, entry);
828
- if (cp instanceof Resume.Done) {
829
- s.pos = cp.pos;
830
- return cp.value;
831
- }
832
- if (cp !== undefined) {
833
- acc = cp.acc;
834
- count = cp.count;
835
- s.pos = cp.pos;
836
- resumed = true;
837
- }
838
- }
839
- if (!resumed) {
840
- acc = used ? [] : undefined;
841
- if (max === 0)
842
- return acc;
843
- const start = s.pos;
844
- const first = c(s);
845
- if (first === Fail) {
846
- if (s.mode !== BT || min > 0)
847
- return Fail;
848
- s.pos = start;
849
- return acc;
850
- }
851
- acc?.push(first);
852
- count = 1;
853
- }
854
- while (count < max) {
855
- const start = s.pos;
856
- if (sep(s) === Fail) {
857
- if (s.mode === INC && s.resume !== undefined)
858
- Resume.save(s, key, entry, { acc, count, pos: start });
859
- if (s.mode !== BT || count < min)
860
- return Fail;
861
- s.pos = start;
862
- return resumed ? Resume.done(s, key, entry, true, acc) : acc;
863
- }
864
- if (checkLoop && s.pos === start) {
865
- s.mode = CUT;
866
- return Fail;
867
- }
868
- const a = c(s);
869
- if (a === Fail) {
870
- if (s.mode === INC && s.resume !== undefined)
871
- Resume.save(s, key, entry, { acc, count, pos: start });
872
- if (s.mode !== BT || count < min)
873
- return Fail;
874
- s.pos = start;
875
- return resumed ? Resume.done(s, key, entry, true, acc) : acc;
876
- }
877
- acc?.push(a);
878
- count++;
879
- }
880
- return resumed ? Resume.done(s, key, entry, true, acc) : acc;
881
- };
882
- }
883
- separatedFold(node) {
884
- const c = this.compile(node.self, true);
885
- const sep = this.compile(node.separator, true);
886
- const op = node.op;
887
- const resumable = this.resumable;
888
- const key = {};
889
- if (!node.right) {
890
- return (s) => {
891
- const entry = s.pos;
892
- let acc;
893
- let resumed = false;
894
- if (resumable && s.resume !== undefined) {
895
- const cp = Resume.take(s, key, entry);
896
- if (cp instanceof Resume.Done) {
897
- s.pos = cp.pos;
898
- return cp.value;
899
- }
900
- if (cp !== undefined) {
901
- acc = cp.acc;
902
- s.pos = cp.pos;
903
- resumed = true;
904
- }
905
- }
906
- if (!resumed) {
907
- acc = c(s);
908
- if (acc === Fail)
909
- return Fail;
910
- }
911
- while (true) {
912
- const start = s.pos;
913
- const x = sep(s);
914
- if (x === Fail) {
915
- if (s.mode === INC && s.resume !== undefined)
916
- Resume.save(s, key, entry, { acc, pos: start });
917
- if (s.mode !== BT)
918
- return Fail;
919
- s.pos = start;
920
- return resumed ? Resume.done(s, key, entry, true, acc) : acc;
921
- }
922
- if (s.pos === start) {
923
- s.mode = CUT;
924
- return Fail;
925
- }
926
- const a = c(s);
927
- if (a === Fail) {
928
- if (s.mode === INC && s.resume !== undefined)
929
- Resume.save(s, key, entry, { acc, pos: start });
930
- if (s.mode !== BT)
931
- return Fail;
932
- s.pos = start;
933
- return resumed ? Resume.done(s, key, entry, true, acc) : acc;
934
- }
935
- acc = op(acc, x, a);
936
- }
937
- };
938
- }
939
- return (s) => {
940
- const first = c(s);
941
- if (first === Fail)
942
- return Fail;
943
- const values = [first];
944
- const seps = [];
945
- while (true) {
946
- const start = s.pos;
947
- const x = sep(s);
948
- if (x === Fail) {
949
- if (s.mode !== BT)
950
- return Fail;
951
- s.pos = start;
952
- break;
953
- }
954
- if (s.pos === start) {
955
- s.mode = CUT;
956
- return Fail;
957
- }
958
- const a = c(s);
959
- if (a === Fail) {
960
- if (s.mode !== BT)
961
- return Fail;
962
- s.pos = start;
963
- break;
964
- }
965
- seps.push(x);
966
- values.push(a);
967
- }
968
- let acc = values[values.length - 1];
969
- for (let i = seps.length - 1; i >= 0; i--)
970
- acc = op(values[i], seps[i], acc);
971
- return acc;
972
- };
973
- }
974
- // ---------------------------------------------------------------------------
975
- // Token parsers (`Token`, `Ascii`)
976
- // ---------------------------------------------------------------------------
977
- token(p, node, used) {
978
- const kind = this.kind;
979
- switch (node._tag) {
980
- case "Any":
981
- if (kind === 1) {
982
- return (s) => {
983
- const pos = s.pos;
984
- if (pos >= s.end)
985
- return fail(s);
986
- s.pos = pos + 1;
987
- return s.input[pos];
988
- };
989
- }
990
- return (s) => {
991
- const pos = s.pos;
992
- if (pos >= s.end)
993
- return fail(s);
994
- const str = s.input;
995
- const c = str.charCodeAt(pos);
996
- if (c >= 0xd800 && c <= 0xdbff && pos + 1 < str.length && (str.charCodeAt(pos + 1) & 0xfc00) === 0xdc00) {
997
- s.pos = pos + 2;
998
- return used ? str.slice(pos, pos + 2) : undefined;
999
- }
1000
- s.pos = pos + 1;
1001
- return used ? str[pos] : undefined;
1002
- };
1003
- case "Literal":
1004
- return this.tokenLiteral(p, node);
1005
- case "OneOf": {
1006
- const set = tokenSet(node.set, kind);
1007
- const negate = node.negate;
1008
- const accept = acceptTable(set, negate);
1009
- const test = set.test;
1010
- if (kind === 1) {
1011
- return (s) => {
1012
- const pos = s.pos;
1013
- if (pos >= s.end)
1014
- return fail(s);
1015
- const b = s.input[pos];
1016
- if (accept[b] === 0)
1017
- return fail(s);
1018
- s.pos = pos + 1;
1019
- return b;
1020
- };
1021
- }
1022
- return (s) => {
1023
- const pos = s.pos;
1024
- if (pos >= s.end)
1025
- return fail(s);
1026
- const str = s.input;
1027
- const c = str.charCodeAt(pos);
1028
- if (c < TableSize) {
1029
- if (accept[c] === 0)
1030
- return fail(s);
1031
- s.pos = pos + 1;
1032
- return used ? str[pos] : undefined;
1033
- }
1034
- let cp = c;
1035
- if (c >= 0xd800 && c <= 0xdbff && pos + 1 < str.length) {
1036
- const d = str.charCodeAt(pos + 1);
1037
- if ((d & 0xfc00) === 0xdc00)
1038
- cp = ((c - 0xd800) << 10) + (d - 0xdc00) + 0x10000;
1039
- }
1040
- if (test(cp) === negate)
1041
- return fail(s);
1042
- const len = cp > 0xffff ? 2 : 1;
1043
- s.pos = pos + len;
1044
- return !used ? undefined : len === 1 ? str[pos] : str.slice(pos, pos + 2);
1045
- };
1046
- }
1047
- case "Take": {
1048
- const count = node.count;
1049
- if (kind === 1) {
1050
- return (s) => {
1051
- const start = s.pos;
1052
- if (s.end - start < count)
1053
- return failAt(s, s.end);
1054
- s.pos = start + count;
1055
- return used ? s.input.subarray(start, start + count) : undefined;
1056
- };
1057
- }
1058
- return (s) => {
1059
- const str = s.input;
1060
- const start = s.pos;
1061
- const end = s.end;
1062
- let i = start;
1063
- let got = 0;
1064
- while (got < count && i < end) {
1065
- const c = str.charCodeAt(i);
1066
- i += c >= 0xd800 && c <= 0xdbff && i + 1 < str.length && (str.charCodeAt(i + 1) & 0xfc00) === 0xdc00 ? 2 : 1;
1067
- got++;
1068
- }
1069
- if (got < count)
1070
- return failAt(s, i);
1071
- s.pos = i;
1072
- return used ? str.slice(start, i) : undefined;
1073
- };
1074
- }
1075
- case "TakeWhile":
1076
- return this.tokenTakeWhile(node, used);
1077
- case "TakeUntil": {
1078
- const { literal, max, min } = node;
1079
- const bounded = min > 0 || max !== Infinity;
1080
- return (s) => {
1081
- const start = s.pos;
1082
- const idx = indexOf(s, literal, start);
1083
- if (idx < 0)
1084
- return failAt(s, s.end);
1085
- if (bounded) {
1086
- const count = countTokens(s, start, idx);
1087
- if (count < min || count > max)
1088
- return failAt(s, idx);
1089
- }
1090
- s.pos = idx;
1091
- return used ? s.slice(start, idx) : undefined;
1092
- };
1093
- }
1094
- case "Rest":
1095
- return (s) => {
1096
- const start = s.pos;
1097
- s.pos = s.end;
1098
- return used ? s.slice(start, s.end) : undefined;
1099
- };
1100
- }
1101
- }
1102
- tokenLiteral(p, node) {
1103
- const lit = node.literal;
1104
- const literalKind = typeof lit === "string" ? 0 : lit instanceof Uint8Array ? 1 : 2;
1105
- if (this.kind === 0) {
1106
- if (literalKind !== 0)
1107
- return this.fallback(p, node, "byte or array literal on string input");
1108
- const str = lit;
1109
- const len = str.length;
1110
- if (node.caseless) {
1111
- const lowered = Array.from({ length: len }, (_, i) => lowerAscii(str.charCodeAt(i)));
1112
- return (s) => {
1113
- const pos = s.pos;
1114
- if (s.end - pos < len)
1115
- return fail(s);
1116
- const input = s.input;
1117
- for (let i = 0; i < len; i++) {
1118
- if (lowerAscii(input.charCodeAt(pos + i)) !== lowered[i])
1119
- return fail(s);
1120
- }
1121
- s.pos = pos + len;
1122
- return input.slice(pos, pos + len);
1123
- };
1124
- }
1125
- return stringLiteral(str, str);
1126
- }
1127
- if (literalKind === 2)
1128
- return this.fallback(p, node, "array literal on byte input");
1129
- const bytes = literalKind === 0 ? new TextEncoder().encode(lit) : lit;
1130
- const len = bytes.length;
1131
- const sameKind = literalKind === 1 && !node.caseless;
1132
- const expect = node.caseless ? Array.from(bytes, lowerAscii) : Array.from(bytes);
1133
- const caseless = node.caseless;
1134
- return (s) => {
1135
- const pos = s.pos;
1136
- if (s.end - pos < len)
1137
- return fail(s);
1138
- const input = s.input;
1139
- for (let i = 0; i < len; i++) {
1140
- const b = input[pos + i];
1141
- if ((caseless ? lowerAscii(b) : b) !== expect[i])
1142
- return fail(s);
1143
- }
1144
- s.pos = pos + len;
1145
- return sameKind ? lit : input.subarray(pos, pos + len);
1146
- };
1147
- }
1148
- tokenTakeWhile(node, used) {
1149
- const kind = this.kind;
1150
- const { max, min, negate } = node;
1151
- const set = tokenSet(node.set, kind);
1152
- const accept = acceptTable(set, negate);
1153
- if (kind === 1) {
1154
- return (s) => {
1155
- const bytes = s.input;
1156
- const start = s.pos;
1157
- const limit = max === Infinity ? s.end : Math.min(s.end, start + max);
1158
- let i = start;
1159
- while (i < limit && accept[bytes[i]] === 1)
1160
- i++;
1161
- if (i - start < min)
1162
- return failAt(s, i);
1163
- s.pos = i;
1164
- return used ? bytes.subarray(start, i) : undefined;
1165
- };
1166
- }
1167
- const test = set.test;
1168
- return (s) => {
1169
- const str = s.input;
1170
- const start = s.pos;
1171
- const end = s.end;
1172
- let i = start;
1173
- let count = 0;
1174
- while (count < max && i < end) {
1175
- const c = str.charCodeAt(i);
1176
- if (c < TableSize) {
1177
- if (accept[c] === 0)
1178
- break;
1179
- i++;
1180
- }
1181
- else if (c < 0xd800 || c > 0xdbff) {
1182
- if (test(c) === negate)
1183
- break;
1184
- i++;
1185
- }
1186
- else {
1187
- let cp = c;
1188
- if (i + 1 < str.length) {
1189
- const d = str.charCodeAt(i + 1);
1190
- if ((d & 0xfc00) === 0xdc00)
1191
- cp = ((c - 0xd800) << 10) + (d - 0xdc00) + 0x10000;
1192
- }
1193
- if (test(cp) === negate)
1194
- break;
1195
- i += cp > 0xffff ? 2 : 1;
1196
- }
1197
- count++;
1198
- }
1199
- if (count < min)
1200
- return failAt(s, i);
1201
- s.pos = i;
1202
- return used ? str.slice(start, i) : undefined;
1203
- };
1204
- }
1205
- // ---------------------------------------------------------------------------
1206
- // Text parsers, specialized per encoding
1207
- // ---------------------------------------------------------------------------
1208
- text(p, node, enc, used) {
1209
- const kind = this.kind;
1210
- const fast = fastLimit(enc);
1211
- const decode = enc.decode;
1212
- const width = enc.width;
1213
- const toText = enc.text;
1214
- const unitAt = kind === 0
1215
- ? (input, i) => input.charCodeAt(i)
1216
- : (input, i) => input[i];
1217
- switch (node._tag) {
1218
- case "Any":
1219
- return (s) => {
1220
- const pos = s.pos;
1221
- const end = s.end;
1222
- if (pos >= end)
1223
- return fail(s);
1224
- const c = unitAt(s.input, pos);
1225
- if (c < fast) {
1226
- s.pos = pos + 1;
1227
- return used ? charOf(c) : undefined;
1228
- }
1229
- const cp = decode(s.input, pos, end);
1230
- if (cp < 0)
1231
- return fail(s);
1232
- s.pos = pos + width(cp);
1233
- return used ? charOf(cp) : undefined;
1234
- };
1235
- case "Literal": {
1236
- const lit = node.literal;
1237
- if (node.caseless) {
1238
- const folded = Array.from(lit, (c) => fold(c.codePointAt(0)));
1239
- const n = folded.length;
1240
- return (s) => {
1241
- const start = s.pos;
1242
- const end = s.end;
1243
- const input = s.input;
1244
- let pos = start;
1245
- for (let i = 0; i < n; i++) {
1246
- if (pos >= end)
1247
- return failAt(s, pos);
1248
- const c = unitAt(input, pos);
1249
- let cp;
1250
- if (c < fast) {
1251
- cp = c;
1252
- pos++;
1253
- }
1254
- else {
1255
- cp = decode(input, pos, end);
1256
- if (cp < 0)
1257
- return failAt(s, pos);
1258
- pos += width(cp);
1259
- }
1260
- if (fold(cp) !== folded[i])
1261
- return failAt(s, pos);
1262
- }
1263
- s.pos = pos;
1264
- return used ? toText(input, start, pos) : undefined;
1265
- };
1266
- }
1267
- const encoded = enc.encode(lit);
1268
- if (typeof encoded === "string")
1269
- return stringLiteral(encoded, lit);
1270
- const bytes = encoded;
1271
- const len = bytes.length;
1272
- if (len === 1) {
1273
- const b0 = bytes[0];
1274
- return (s) => {
1275
- const pos = s.pos;
1276
- if (pos < s.end && s.input[pos] === b0) {
1277
- s.pos = pos + 1;
1278
- return lit;
1279
- }
1280
- return fail(s);
1281
- };
1282
- }
1283
- return (s) => {
1284
- const pos = s.pos;
1285
- if (s.end - pos < len)
1286
- return fail(s);
1287
- const input = s.input;
1288
- for (let i = 0; i < len; i++)
1289
- if (input[pos + i] !== bytes[i])
1290
- return fail(s);
1291
- s.pos = pos + len;
1292
- return lit;
1293
- };
1294
- }
1295
- case "OneOf": {
1296
- const set = textSet(node.set);
1297
- const negate = node.negate;
1298
- const accept = acceptTable(set, negate);
1299
- const test = set.test;
1300
- return (s) => {
1301
- const pos = s.pos;
1302
- const end = s.end;
1303
- if (pos >= end)
1304
- return fail(s);
1305
- const c = unitAt(s.input, pos);
1306
- if (c < fast && c < TableSize) {
1307
- if (accept[c] === 0)
1308
- return fail(s);
1309
- s.pos = pos + 1;
1310
- return used ? charOf(c) : undefined;
1311
- }
1312
- const cp = c < fast ? c : decode(s.input, pos, end);
1313
- if (cp < 0 || test(cp) === negate)
1314
- return fail(s);
1315
- s.pos = pos + (c < fast ? 1 : width(cp));
1316
- return used ? charOf(cp) : undefined;
1317
- };
1318
- }
1319
- case "Take": {
1320
- const count = node.count;
1321
- return (s) => {
1322
- const start = s.pos;
1323
- const end = s.end;
1324
- const input = s.input;
1325
- let pos = start;
1326
- for (let got = 0; got < count; got++) {
1327
- if (pos >= end)
1328
- return failAt(s, pos);
1329
- const c = unitAt(input, pos);
1330
- if (c < fast)
1331
- pos++;
1332
- else {
1333
- const cp = decode(input, pos, end);
1334
- if (cp < 0)
1335
- return failAt(s, pos);
1336
- pos += width(cp);
1337
- }
1338
- }
1339
- s.pos = pos;
1340
- return used ? toText(input, start, pos) : undefined;
1341
- };
1342
- }
1343
- case "TakeWhile": {
1344
- const { max, min, negate } = node;
1345
- const set = textSet(node.set);
1346
- const accept = acceptTable(set, negate);
1347
- const test = set.test;
1348
- const small = Math.min(fast, TableSize);
1349
- return (s) => {
1350
- const input = s.input;
1351
- const start = s.pos;
1352
- const end = s.end;
1353
- let i = start;
1354
- let count = 0;
1355
- while (count < max && i < end) {
1356
- const c = unitAt(input, i);
1357
- if (c < small) {
1358
- if (accept[c] === 0)
1359
- break;
1360
- i++;
1361
- }
1362
- else if (c < fast) {
1363
- if (test(c) === negate)
1364
- break;
1365
- i++;
1366
- }
1367
- else {
1368
- const cp = decode(input, i, end);
1369
- if (cp < 0 || test(cp) === negate)
1370
- break;
1371
- i += width(cp);
1372
- }
1373
- count++;
1374
- }
1375
- if (count < min)
1376
- return failAt(s, i);
1377
- s.pos = i;
1378
- return used ? toText(input, start, i) : undefined;
1379
- };
1380
- }
1381
- case "TakeUntil":
1382
- case "Rest":
1383
- return this.fallback(p, node, "Text parser without a compiled form");
1384
- }
1385
- }
1386
- taken(node, used) {
1387
- const c = this.compile(node.self, false);
1388
- const enc = node.encoding;
1389
- if (enc === undefined) {
1390
- if (!used)
1391
- return c;
1392
- if (this.kind === 0) {
1393
- return (s) => {
1394
- const start = s.pos;
1395
- return c(s) === Fail ? Fail : s.input.slice(start, s.pos);
1396
- };
1397
- }
1398
- return (s) => {
1399
- const start = s.pos;
1400
- return c(s) === Fail ? Fail : s.slice(start, s.pos);
1401
- };
1402
- }
1403
- // `Text.taken` checks that the text is well formed, then decodes it
1404
- const fast = fastLimit(enc);
1405
- const toText = enc.text;
1406
- const unitAt = this.kind === 0
1407
- ? (input, i) => input.charCodeAt(i)
1408
- : (input, i) => input[i];
1409
- return (s) => {
1410
- const start = s.pos;
1411
- if (c(s) === Fail)
1412
- return Fail;
1413
- const end = s.pos;
1414
- const input = s.input;
1415
- let i = start;
1416
- while (i < end && unitAt(input, i) < fast)
1417
- i++;
1418
- if (i < end && validate(enc, s, i, end) < 0)
1419
- return fail(s);
1420
- return used ? toText(input, start, end) : undefined;
1421
- };
1422
- }
1423
- /**
1424
- * `Ascii.float` and `Text.float` (`map(floatText, toFloat)`): numbers in
1425
- * decimal notation are matched and converted in one pass, without
1426
- * slicing the input; the rest runs the compiled parser (see the JIT).
1427
- */
1428
- float(node) {
1429
- if (!floatTexts.has(node.self) || this.kind === 2)
1430
- return undefined;
1431
- let taken = nodeOf(node.self);
1432
- while (taken._tag === "Expected")
1433
- taken = nodeOf(taken.self);
1434
- if (taken._tag !== "Taken")
1435
- return undefined;
1436
- const enc = taken.encoding;
1437
- if (enc !== undefined && !(this.native(enc) && enc.unit === 1 && enc.asciiCompatible))
1438
- return undefined;
1439
- const c = this.compile(node.self, true);
1440
- const scan = (this.kind === 0 ? scanFloatString : scanFloatBytes);
1441
- const resumable = this.resumable;
1442
- return (s) => {
1443
- const v = scan(s.input, s.pos, s.end);
1444
- // Near the end of a partial input, the parser may have to report `Incomplete`
1445
- if (v === undefined || (resumable && s.partial && floatScan.read + Margin > s.end)) {
1446
- const t = c(s);
1447
- return t === Fail ? Fail : toFloat(t);
1448
- }
1449
- if (v === Fail)
1450
- return fail(s);
1451
- s.pos = floatScan.end;
1452
- return v;
1453
- };
1454
- }
1455
- escaped(node) {
1456
- const raw = node.raw;
1457
- const normal = this.compile(node.normal, !raw);
1458
- const escape = this.compile(node.escape, !raw);
1459
- const enc = node.encoding;
1460
- const ctrl = node.control;
1461
- const kind = this.kind;
1462
- // Matches the control character, advancing past it
1463
- let control;
1464
- if (enc === undefined || (ctrl < fastLimit(enc) && ctrl < TableSize)) {
1465
- control = kind === 0
1466
- ? (s) => {
1467
- if (s.pos < s.end && s.input.charCodeAt(s.pos) === ctrl) {
1468
- s.pos++;
1469
- return true;
1470
- }
1471
- return false;
1472
- }
1473
- : (s) => {
1474
- if (s.pos < s.end && s.input[s.pos] === ctrl) {
1475
- s.pos++;
1476
- return true;
1477
- }
1478
- return false;
1479
- };
1480
- }
1481
- else {
1482
- control = (s) => {
1483
- if (s.pos >= s.end)
1484
- return false;
1485
- const cp = enc.decode(s.input, s.pos, s.end);
1486
- if (cp !== ctrl)
1487
- return false;
1488
- s.pos += enc.width(cp);
1489
- return true;
1490
- };
1491
- }
1492
- const resumable = this.resumable;
1493
- const key = {};
1494
- /** Fails as incomplete, keeping a checkpoint in a streaming parse. */
1495
- const incomplete = (s, start, checkpoint) => {
1496
- if (s.resume !== undefined)
1497
- Resume.save(s, key, start, checkpoint);
1498
- s.mode = INC;
1499
- return Fail;
1500
- };
1501
- if (raw) {
1502
- const slice = enc === undefined
1503
- ? (s, start) => s.slice(start, s.pos)
1504
- : (s, start) => enc.text(s.input, start, s.pos);
1505
- return (s) => {
1506
- const start = s.pos;
1507
- let resumed = false;
1508
- if (resumable && s.resume !== undefined) {
1509
- const cp = Resume.take(s, key, start);
1510
- if (cp instanceof Resume.Done) {
1511
- s.pos = cp.pos;
1512
- return cp.value;
1513
- }
1514
- if (cp !== undefined) {
1515
- s.pos = cp;
1516
- resumed = true;
1517
- }
1518
- }
1519
- while (s.pos < s.end) {
1520
- const before = s.pos;
1521
- if (normal(s) !== Fail) {
1522
- if (s.pos === before) {
1523
- s.mode = CUT;
1524
- return Fail;
1525
- }
1526
- continue;
1527
- }
1528
- if (s.mode === INC)
1529
- return incomplete(s, start, before);
1530
- if (s.mode !== BT)
1531
- return Fail;
1532
- s.pos = before;
1533
- if (control(s)) {
1534
- if (escape(s) === Fail)
1535
- return s.mode === INC ? incomplete(s, start, before) : Fail;
1536
- }
1537
- else {
1538
- return resumed ? Resume.done(s, key, start, true, slice(s, start)) : slice(s, start);
1539
- }
1540
- }
1541
- if (s.partial)
1542
- return incomplete(s, start, s.pos);
1543
- return resumed ? Resume.done(s, key, start, true, slice(s, start)) : slice(s, start);
1544
- };
1545
- }
1546
- return (s) => {
1547
- const start = s.pos;
1548
- let out = "";
1549
- let resumed = false;
1550
- if (resumable && s.resume !== undefined) {
1551
- const cp = Resume.take(s, key, start);
1552
- if (cp instanceof Resume.Done) {
1553
- s.pos = cp.pos;
1554
- return cp.value;
1555
- }
1556
- if (cp !== undefined) {
1557
- out = cp.out;
1558
- s.pos = cp.pos;
1559
- resumed = true;
1560
- }
1561
- }
1562
- while (s.pos < s.end) {
1563
- const before = s.pos;
1564
- const a = normal(s);
1565
- if (a !== Fail) {
1566
- if (s.pos !== before) {
1567
- out += a;
1568
- continue;
1569
- }
1570
- }
1571
- else {
1572
- if (s.mode === INC)
1573
- return incomplete(s, start, { out, pos: before });
1574
- if (s.mode !== BT)
1575
- return Fail;
1576
- s.pos = before;
1577
- }
1578
- if (control(s)) {
1579
- const b = escape(s);
1580
- if (b === Fail)
1581
- return s.mode === INC ? incomplete(s, start, { out, pos: before }) : Fail;
1582
- out += b;
1583
- }
1584
- else {
1585
- return resumed ? Resume.done(s, key, start, true, out) : out;
1586
- }
1587
- }
1588
- if (s.partial)
1589
- return incomplete(s, start, { out, pos: s.pos });
1590
- return resumed ? Resume.done(s, key, start, true, out) : out;
1591
- };
1592
- }
1593
- }
38
+ var Compiler = class {
39
+ kind;
40
+ resumable;
41
+ used = /* @__PURE__ */ new Map();
42
+ unused = /* @__PURE__ */ new Map();
43
+ firsts;
44
+ fallbacks = [];
45
+ fellBack = /* @__PURE__ */ new Set();
46
+ budget = maxNodes;
47
+ /**
48
+ * `resumable`: compile for streaming parses, which may be partial (see
49
+ * `state.partial`) and keep checkpoints (see `internal/resume.ts`).
50
+ */
51
+ constructor(kind, resumable = false) {
52
+ this.kind = kind;
53
+ this.resumable = resumable;
54
+ this.firsts = new FirstSets(kind);
55
+ }
56
+ /**
57
+ * In a resumable build, runs the compiled token parser `step`, and falls
58
+ * back to the interpreted one when it read within `lookahead` units of
59
+ * the end of a partial input, where it might have to report `Incomplete`.
60
+ * Compiled token parsers leave `state.pos` where they stopped reading,
61
+ * even when they fail.
62
+ */
63
+ partialSafe(p, step, lookahead) {
64
+ if (!this.resumable) return step;
65
+ const interpreted = p.step;
66
+ const ahead = Math.max(lookahead, Margin);
67
+ return (s) => {
68
+ if (!s.partial) return step(s);
69
+ const start = s.pos;
70
+ const r = step(s);
71
+ if (s.pos + ahead <= s.end) return r;
72
+ s.pos = start;
73
+ return interpreted(s);
74
+ };
75
+ }
76
+ /** Compiles `p`; when `used` is false its output is not needed. */
77
+ compile(p, used) {
78
+ const memo = used ? this.used : this.unused;
79
+ const slot = memo.get(p);
80
+ if (slot !== void 0) {
81
+ if (slot.fn !== void 0) return slot.fn;
82
+ return (s) => (slot.fn ?? p.step)(s);
83
+ }
84
+ const fresh = { fn: void 0 };
85
+ memo.set(p, fresh);
86
+ const node = nodeOf(p);
87
+ const fn = --this.budget < 0 ? this.fallback(p, node, "node budget exceeded") : this.build(p, node, used);
88
+ fresh.fn = fn;
89
+ return fn;
90
+ }
91
+ fallback(p, node, reason) {
92
+ this.note(p, node, reason);
93
+ return p.step;
94
+ }
95
+ /** Records that (part of) `p` runs interpreted. */
96
+ note(p, node, reason) {
97
+ if (!this.fellBack.has(p)) {
98
+ this.fellBack.add(p);
99
+ this.fallbacks.push({
100
+ name: p.name,
101
+ tag: node._tag,
102
+ reason
103
+ });
104
+ }
105
+ }
106
+ /** Whether a token node reads this input kind natively. */
107
+ native(enc) {
108
+ return enc === void 0 ? this.kind !== 2 : kindOfEncoding(enc) === this.kind;
109
+ }
110
+ build(p, node, used) {
111
+ switch (node._tag) {
112
+ case "Opaque": return this.fallback(p, node, "not describable (Parser.make, gen, ...)");
113
+ case "Succeed": {
114
+ const value = node.value;
115
+ return () => value;
116
+ }
117
+ case "Sync": {
118
+ const evaluate = node.evaluate;
119
+ return used ? () => evaluate() : () => void 0;
120
+ }
121
+ case "Fail": {
122
+ const mode = node.mode;
123
+ return (s) => {
124
+ s.mode = mode;
125
+ return Fail;
126
+ };
127
+ }
128
+ case "Eof": return (s) => {
129
+ if (s.pos < s.end) {
130
+ s.mode = BT;
131
+ return Fail;
132
+ }
133
+ if (s.partial) {
134
+ s.mode = INC;
135
+ return Fail;
136
+ }
137
+ };
138
+ case "Location": return (s) => s.pos;
139
+ case "RestLen": return (s) => s.end - s.pos;
140
+ case "Suspend": return this.compile(node.resolve(), used);
141
+ case "Any":
142
+ case "Literal":
143
+ case "OneOf":
144
+ case "Take":
145
+ case "TakeWhile":
146
+ case "TakeUntil":
147
+ case "Rest":
148
+ if (!this.native(node.encoding)) return this.fallback(p, node, "token parser on array input");
149
+ return this.partialSafe(p, node.encoding === void 0 ? this.token(p, node, used) : this.text(p, node, node.encoding, used), node._tag === "Literal" || node._tag === "TakeUntil" ? node.literal.length * 4 : Margin);
150
+ case "TillLineEnding":
151
+ case "Identifier":
152
+ case "Bom": return this.fallback(p, node, "leaf parser without a compiled form");
153
+ case "Escaped":
154
+ if (!this.native(node.encoding)) return this.fallback(p, node, "token parser on array input");
155
+ return this.escaped(node);
156
+ case "Map": {
157
+ if (!used) return this.compile(node.self, false);
158
+ if (node.f === toFloat) {
159
+ const step = this.float(node);
160
+ if (step !== void 0) return step;
161
+ }
162
+ if (node.f === fromEntries && !this.resumable && buildsEntries(node.self)) return this.entries(node.self);
163
+ const c = this.compile(node.self, true);
164
+ const f = node.f;
165
+ return (s) => {
166
+ const a = c(s);
167
+ return a === Fail ? Fail : f(a);
168
+ };
169
+ }
170
+ case "As": {
171
+ const c = this.compile(node.self, false);
172
+ if (!used) return c;
173
+ const value = node.value;
174
+ return (s) => c(s) === Fail ? Fail : value;
175
+ }
176
+ case "Tap": {
177
+ const c = this.compile(node.self, true);
178
+ const f = node.f;
179
+ return (s) => {
180
+ const a = c(s);
181
+ if (a !== Fail) f(a);
182
+ return a;
183
+ };
184
+ }
185
+ case "TryMap": {
186
+ const c = this.compile(node.self, true);
187
+ const f = node.f;
188
+ return (s) => {
189
+ const a = c(s);
190
+ if (a === Fail) return Fail;
191
+ const r = f(a);
192
+ if (isSuccess(r)) return r.success;
193
+ s.mode = BT;
194
+ return Fail;
195
+ };
196
+ }
197
+ case "FilterMap": {
198
+ const c = this.compile(node.self, true);
199
+ const f = node.f;
200
+ return (s) => {
201
+ const a = c(s);
202
+ if (a === Fail) return Fail;
203
+ const o = f(a);
204
+ if (isSome(o)) return o.value;
205
+ s.mode = BT;
206
+ return Fail;
207
+ };
208
+ }
209
+ case "Filter": {
210
+ const c = this.compile(node.self, true);
211
+ const predicate = node.predicate;
212
+ return (s) => {
213
+ const a = c(s);
214
+ if (a === Fail) return Fail;
215
+ if (predicate(a)) return a;
216
+ s.mode = BT;
217
+ return Fail;
218
+ };
219
+ }
220
+ case "FlatMap": {
221
+ const c = this.compile(node.self, true);
222
+ const f = node.f;
223
+ this.note(p, node, "the parser returned by the function runs interpreted");
224
+ return (s) => {
225
+ const a = c(s);
226
+ return a === Fail ? Fail : f(a).step(s);
227
+ };
228
+ }
229
+ case "Taken":
230
+ if (node.encoding !== void 0 && !this.native(node.encoding)) return this.fallback(p, node, "Text parser on another input kind");
231
+ return this.taken(node, used);
232
+ case "WithTaken": {
233
+ const c = this.compile(node.self, true);
234
+ return (s) => {
235
+ const start = s.pos;
236
+ const a = c(s);
237
+ return a === Fail ? Fail : [a, s.slice(start, s.pos)];
238
+ };
239
+ }
240
+ case "Span": {
241
+ const c = this.compile(node.self, false);
242
+ if (!used) return c;
243
+ return (s) => {
244
+ const start = s.pos;
245
+ return c(s) === Fail ? Fail : {
246
+ start,
247
+ end: s.pos
248
+ };
249
+ };
250
+ }
251
+ case "WithSpan": {
252
+ const c = this.compile(node.self, true);
253
+ return (s) => {
254
+ const start = s.pos;
255
+ const a = c(s);
256
+ return a === Fail ? Fail : [a, {
257
+ start,
258
+ end: s.pos
259
+ }];
260
+ };
261
+ }
262
+ case "Mode": {
263
+ const c = this.compile(node.self, used);
264
+ const from = node.from;
265
+ const to = node.to;
266
+ return (s) => {
267
+ const a = c(s);
268
+ if (a === Fail && s.mode === from) s.mode = to;
269
+ return a;
270
+ };
271
+ }
272
+ case "Context":
273
+ case "Expected":
274
+ case "MapError":
275
+ case "OrFail":
276
+ case "Trace":
277
+ case "Syntax":
278
+ case "RetryAfter": return this.compile(node.self, used);
279
+ case "ResumeAfter": {
280
+ const c = this.compile(node.self, used);
281
+ if (!used) return c;
282
+ return (s) => {
283
+ const a = c(s);
284
+ return a === Fail ? Fail : Option.some(a);
285
+ };
286
+ }
287
+ case "Opt":
288
+ case "OrElseSucceed": {
289
+ const c = this.compile(node.self, used);
290
+ const orElse = !used ? void 0 : node._tag === "Opt" ? Option.none : node.value;
291
+ const some = used && node._tag === "Opt";
292
+ return (s) => {
293
+ const start = s.pos;
294
+ const a = c(s);
295
+ if (a !== Fail) return some ? Option.some(a) : a;
296
+ if (s.mode !== BT) return Fail;
297
+ s.pos = start;
298
+ return orElse === void 0 ? void 0 : orElse();
299
+ };
300
+ }
301
+ case "Peek": {
302
+ const c = this.compile(node.self, used);
303
+ return (s) => {
304
+ const start = s.pos;
305
+ const a = c(s);
306
+ if (a !== Fail) s.pos = start;
307
+ return a;
308
+ };
309
+ }
310
+ case "Not": {
311
+ const c = this.compile(node.self, false);
312
+ return (s) => {
313
+ const start = s.pos;
314
+ if (c(s) !== Fail) {
315
+ s.pos = start;
316
+ s.mode = BT;
317
+ return Fail;
318
+ }
319
+ if (s.mode !== BT) return Fail;
320
+ s.pos = start;
321
+ };
322
+ }
323
+ case "Seq": return this.seq(node, used);
324
+ case "Struct": {
325
+ const keys = node.keys;
326
+ const steps = node.parsers.map((q) => this.compile(q, used));
327
+ const n = steps.length;
328
+ if (!used) return this.chain(steps);
329
+ return (s) => {
330
+ const out = {};
331
+ for (let i = 0; i < n; i++) {
332
+ const a = steps[i](s);
333
+ if (a === Fail) return Fail;
334
+ out[keys[i]] = a;
335
+ }
336
+ return out;
337
+ };
338
+ }
339
+ case "ZipWith": {
340
+ const c1 = this.compile(node.self, used);
341
+ const c2 = this.compile(node.that, used);
342
+ if (!used) return this.chain([c1, c2]);
343
+ const f = node.f;
344
+ return (s) => {
345
+ const a = c1(s);
346
+ if (a === Fail) return Fail;
347
+ const b = c2(s);
348
+ return b === Fail ? Fail : f(a, b);
349
+ };
350
+ }
351
+ case "Alt": return this.alt(node, used);
352
+ case "Dispatch": return this.dispatch(p, node, used);
353
+ case "Repeat":
354
+ case "Fold": return this.repeat(node, used);
355
+ case "RepeatTill": return this.repeatTill(node);
356
+ case "Separated": return this.separated(node, used);
357
+ case "SeparatedFold": return this.separatedFold(node);
358
+ case "Service":
359
+ case "Provide": return this.fallback(p, node, "services stay interpreted");
360
+ }
361
+ }
362
+ /** Runs steps in order, for their effect on the cursor only. */
363
+ chain(steps) {
364
+ const n = steps.length;
365
+ if (n === 0) return () => void 0;
366
+ if (n === 1) return steps[0];
367
+ if (n === 2) {
368
+ const [a, b] = steps;
369
+ return (s) => a(s) === Fail ? Fail : b(s);
370
+ }
371
+ return (s) => {
372
+ for (let i = 0; i < n; i++) if (steps[i](s) === Fail) return Fail;
373
+ };
374
+ }
375
+ seq(node, used) {
376
+ const output = node.output;
377
+ const keep = (i) => used && (output === "tuple" || output === i || Array.isArray(output) && output.includes(i));
378
+ const steps = node.parsers.map((q, i) => this.compile(q, keep(i)));
379
+ const n = steps.length;
380
+ if (!used) return this.chain(steps);
381
+ if (output === "tuple") return (s) => {
382
+ const out = new Array(n);
383
+ for (let i = 0; i < n; i++) {
384
+ const a = steps[i](s);
385
+ if (a === Fail) return Fail;
386
+ out[i] = a;
387
+ }
388
+ return out;
389
+ };
390
+ if (Predicate.isNumber(output)) {
391
+ if (n === 2) {
392
+ const [a, b] = steps;
393
+ return output === 0 ? (s) => {
394
+ const x = a(s);
395
+ if (x === Fail) return Fail;
396
+ return b(s) === Fail ? Fail : x;
397
+ } : (s) => a(s) === Fail ? Fail : b(s);
398
+ }
399
+ return (s) => {
400
+ let out;
401
+ for (let i = 0; i < n; i++) {
402
+ const a = steps[i](s);
403
+ if (a === Fail) return Fail;
404
+ if (i === output) out = a;
405
+ }
406
+ return out;
407
+ };
408
+ }
409
+ const [i0, i1] = output;
410
+ return (s) => {
411
+ let x;
412
+ let y;
413
+ for (let i = 0; i < n; i++) {
414
+ const a = steps[i](s);
415
+ if (a === Fail) return Fail;
416
+ if (i === i0) x = a;
417
+ else if (i === i1) y = a;
418
+ }
419
+ return [x, y];
420
+ };
421
+ }
422
+ /** The unit at the cursor, or -1 at the end of the input. */
423
+ unitReader() {
424
+ return this.kind === 0 ? (s) => s.pos < s.end ? s.input.charCodeAt(s.pos) : -1 : (s) => s.pos < s.end ? s.input[s.pos] : -1;
425
+ }
426
+ alt(node, used) {
427
+ const steps = node.parsers.map((q) => this.compile(q, used));
428
+ const n = steps.length;
429
+ if (n === 0) return (s) => {
430
+ s.mode = BT;
431
+ return Fail;
432
+ };
433
+ if (n === 1) return steps[0];
434
+ const plan = this.kind === 2 ? void 0 : planAlt(node.parsers.map((q) => this.firsts.of(q)));
435
+ if (plan === void 0) return (s) => {
436
+ const start = s.pos;
437
+ for (let i = 0; i < n; i++) {
438
+ const a = steps[i](s);
439
+ if (a !== Fail) return a;
440
+ if (s.mode !== BT) return Fail;
441
+ s.pos = start;
442
+ }
443
+ s.mode = BT;
444
+ return Fail;
445
+ };
446
+ const lists = plan.lists.map((l) => l.map((i) => steps[i]));
447
+ const { byUnit, end, high } = plan;
448
+ const unit = this.unitReader();
449
+ const resumable = this.resumable;
450
+ return (s) => {
451
+ const u = resumable && s.partial && s.pos + Margin > s.end ? -2 : unit(s);
452
+ const candidates = u === -2 ? steps : lists[u < 0 ? end : u < TableSize ? byUnit[u] : high];
453
+ const start = s.pos;
454
+ for (let i = 0; i < candidates.length; i++) {
455
+ const a = candidates[i](s);
456
+ if (a !== Fail) return a;
457
+ if (s.mode !== BT) return Fail;
458
+ s.pos = start;
459
+ }
460
+ s.mode = BT;
461
+ return Fail;
462
+ };
463
+ }
464
+ dispatch(p, node, used) {
465
+ const selector = this.compile(node.selector, true);
466
+ const choose = node.choose;
467
+ const compiled = /* @__PURE__ */ new Map();
468
+ if (node.cases !== void 0) for (const key of Reflect.ownKeys(node.cases)) {
469
+ const q = node.cases[key];
470
+ if (!compiled.has(q)) compiled.set(q, this.compile(q, used));
471
+ }
472
+ if (node.otherwise !== void 0 && !compiled.has(node.otherwise)) compiled.set(node.otherwise, this.compile(node.otherwise, used));
473
+ const general = (s) => {
474
+ const start = s.pos;
475
+ const key = selector(s);
476
+ if (key === Fail) return Fail;
477
+ const q = choose(key);
478
+ if (q === void 0) {
479
+ s.pos = start;
480
+ s.mode = BT;
481
+ return Fail;
482
+ }
483
+ return (compiled.get(q) ?? q.step)(s);
484
+ };
485
+ if (node.cases === void 0) {
486
+ this.note(p, node, "the parser returned by the function of cases runs interpreted");
487
+ return general;
488
+ }
489
+ let sel = nodeOf(node.selector);
490
+ const peek = sel._tag === "Peek";
491
+ if (peek) sel = nodeOf(sel.self);
492
+ if (sel._tag !== "Any" || !this.native(sel.encoding)) return general;
493
+ const enc = sel.encoding;
494
+ const limit = enc === void 0 ? this.kind === 0 ? 55296 : TableSize : Math.min(fastLimit(enc), 55296);
495
+ const size = Math.min(limit, TableSize);
496
+ if (size === 0) return general;
497
+ const table = [];
498
+ for (let u = 0; u < size; u++) {
499
+ const q = choose(enc === void 0 && this.kind === 1 ? u : charOf(u));
500
+ table.push(q === void 0 ? null : compiled.get(q) ?? q.step);
501
+ }
502
+ const unit = this.unitReader();
503
+ const advance = peek ? 0 : 1;
504
+ const resumable = this.resumable;
505
+ return (s) => {
506
+ if (resumable && s.partial && s.pos + Margin > s.end) return general(s);
507
+ const u = unit(s);
508
+ if (u < 0) {
509
+ s.mode = BT;
510
+ return Fail;
511
+ }
512
+ if (u >= size) return general(s);
513
+ const q = table[u];
514
+ if (q === null) {
515
+ s.mode = BT;
516
+ return Fail;
517
+ }
518
+ s.pos += advance;
519
+ return q(s);
520
+ };
521
+ }
522
+ repeat(node, used) {
523
+ const { max, min } = node;
524
+ const checkLoop = max === Infinity;
525
+ const isFold = node._tag === "Fold";
526
+ const cond = isFold ? node.while : void 0;
527
+ const c = this.compile(node.self, used);
528
+ const resumable = this.resumable;
529
+ const key = {};
530
+ const tracked = used || cond !== void 0;
531
+ const init = !tracked ? () => void 0 : isFold ? node.init : () => [];
532
+ const add = !tracked ? (acc) => acc : isFold ? node.f : (acc, a) => {
533
+ acc.push(a);
534
+ return acc;
535
+ };
536
+ return (s) => {
537
+ const entry = s.pos;
538
+ let acc;
539
+ let count = 0;
540
+ let resumed = false;
541
+ if (resumable && s.resume !== void 0) {
542
+ const cp = Resume.take(s, key, entry);
543
+ if (cp instanceof Resume.Done) {
544
+ s.pos = cp.pos;
545
+ return cp.value;
546
+ }
547
+ if (cp !== void 0) {
548
+ acc = cp.acc;
549
+ count = cp.count;
550
+ s.pos = cp.pos;
551
+ resumed = true;
552
+ }
553
+ }
554
+ if (!resumed) acc = init();
555
+ for (; count < max; count++) {
556
+ if (cond !== void 0 && count >= min && !cond(acc)) break;
557
+ const start = s.pos;
558
+ const a = c(s);
559
+ if (a === Fail) {
560
+ if (s.mode === INC && s.resume !== void 0) Resume.save(s, key, entry, {
561
+ acc,
562
+ count,
563
+ pos: start
564
+ });
565
+ if (s.mode !== BT || count < min) return Fail;
566
+ s.pos = start;
567
+ return resumed ? Resume.done(s, key, entry, true, acc) : acc;
568
+ }
569
+ if (checkLoop && s.pos === start) {
570
+ s.mode = CUT;
571
+ return Fail;
572
+ }
573
+ acc = add(acc, a);
574
+ }
575
+ return resumed ? Resume.done(s, key, entry, true, acc) : acc;
576
+ };
577
+ }
578
+ /**
579
+ * `map(self, Object.fromEntries)`, where `buildsEntries(self)`: builds the
580
+ * object directly (see the JIT).
581
+ */
582
+ entries(p) {
583
+ const node = nodeOf(p);
584
+ switch (node._tag) {
585
+ case "Mode": {
586
+ const c = this.entries(node.self);
587
+ const from = node.from;
588
+ const to = node.to;
589
+ return (s) => {
590
+ const a = c(s);
591
+ if (a === Fail && s.mode === from) s.mode = to;
592
+ return a;
593
+ };
594
+ }
595
+ case "Seq": {
596
+ const i = node.output;
597
+ const steps = node.parsers.map((q, j) => j === i ? this.entries(q) : this.compile(q, false));
598
+ return (s) => {
599
+ let out;
600
+ for (let j = 0; j < steps.length; j++) {
601
+ const a = steps[j](s);
602
+ if (a === Fail) return Fail;
603
+ if (j === i) out = a;
604
+ }
605
+ return out;
606
+ };
607
+ }
608
+ case "Repeat":
609
+ case "Separated": {
610
+ const pair = pairOf(node.self);
611
+ if (pair !== void 0) return this.entriesLoop(node, pair);
612
+ const c = this.compile(p, true);
613
+ return (s) => {
614
+ const a = c(s);
615
+ return a === Fail ? Fail : fromEntries(a);
616
+ };
617
+ }
618
+ default: return this.entries(node.self);
619
+ }
620
+ }
621
+ entriesLoop(node, pair) {
622
+ const parts = pair.parsers.map((q, j) => this.compile(q, j === pair.key || j === pair.value));
623
+ const { key: ki, value: vi } = pair;
624
+ const entry = (s, acc) => {
625
+ let key;
626
+ let value;
627
+ for (let j = 0; j < parts.length; j++) {
628
+ const a = parts[j](s);
629
+ if (a === Fail) return false;
630
+ if (j === ki) key = a;
631
+ else if (j === vi) value = a;
632
+ }
633
+ acc.add(key, value);
634
+ return true;
635
+ };
636
+ const { max, min } = node;
637
+ const checkLoop = max === Infinity;
638
+ if (node._tag === "Repeat") return (s) => {
639
+ const acc = new EntriesAcc();
640
+ for (let count = 0; count < max; count++) {
641
+ const start = s.pos;
642
+ let key;
643
+ let value;
644
+ let ok = true;
645
+ for (let j = 0; j < parts.length; j++) {
646
+ const a = parts[j](s);
647
+ if (a === Fail) {
648
+ ok = false;
649
+ break;
650
+ }
651
+ if (j === ki) key = a;
652
+ else if (j === vi) value = a;
653
+ }
654
+ if (!ok) {
655
+ if (s.mode !== BT || count < min) return Fail;
656
+ s.pos = start;
657
+ return acc.result();
658
+ }
659
+ if (checkLoop && s.pos === start) {
660
+ s.mode = CUT;
661
+ return Fail;
662
+ }
663
+ acc.add(key, value);
664
+ }
665
+ return acc.result();
666
+ };
667
+ const sep = this.compile(node.separator, false);
668
+ return (s) => {
669
+ const acc = new EntriesAcc();
670
+ let count = 0;
671
+ if (max === 0) return acc.result();
672
+ let start = s.pos;
673
+ if (!entry(s, acc)) {
674
+ if (s.mode !== BT || min > 0) return Fail;
675
+ s.pos = start;
676
+ return acc.result();
677
+ }
678
+ count++;
679
+ while (count < max) {
680
+ start = s.pos;
681
+ if (sep(s) === Fail) {
682
+ if (s.mode !== BT || count < min) return Fail;
683
+ s.pos = start;
684
+ return acc.result();
685
+ }
686
+ if (checkLoop && s.pos === start) {
687
+ s.mode = CUT;
688
+ return Fail;
689
+ }
690
+ if (!entry(s, acc)) {
691
+ if (s.mode !== BT || count < min) return Fail;
692
+ s.pos = start;
693
+ return acc.result();
694
+ }
695
+ count++;
696
+ }
697
+ return acc.result();
698
+ };
699
+ }
700
+ repeatTill(node) {
701
+ const { max, min } = node;
702
+ const c = this.compile(node.self, true);
703
+ const end = this.compile(node.end, true);
704
+ return (s) => {
705
+ const acc = [];
706
+ while (true) {
707
+ const start = s.pos;
708
+ if (acc.length >= min) {
709
+ const b = end(s);
710
+ if (b !== Fail) return [acc, b];
711
+ if (s.mode !== BT) return Fail;
712
+ s.pos = start;
713
+ if (acc.length >= max) return Fail;
714
+ }
715
+ const a = c(s);
716
+ if (a === Fail) return Fail;
717
+ if (s.pos === start) {
718
+ s.mode = CUT;
719
+ return Fail;
720
+ }
721
+ acc.push(a);
722
+ }
723
+ };
724
+ }
725
+ separated(node, used) {
726
+ const { max, min } = node;
727
+ const checkLoop = max === Infinity;
728
+ const c = this.compile(node.self, used);
729
+ const sep = this.compile(node.separator, false);
730
+ const resumable = this.resumable;
731
+ const key = {};
732
+ return (s) => {
733
+ const entry = s.pos;
734
+ let acc;
735
+ let count = 0;
736
+ let resumed = false;
737
+ if (resumable && s.resume !== void 0) {
738
+ const cp = Resume.take(s, key, entry);
739
+ if (cp instanceof Resume.Done) {
740
+ s.pos = cp.pos;
741
+ return cp.value;
742
+ }
743
+ if (cp !== void 0) {
744
+ acc = cp.acc;
745
+ count = cp.count;
746
+ s.pos = cp.pos;
747
+ resumed = true;
748
+ }
749
+ }
750
+ if (!resumed) {
751
+ acc = used ? [] : void 0;
752
+ if (max === 0) return acc;
753
+ const start = s.pos;
754
+ const first = c(s);
755
+ if (first === Fail) {
756
+ if (s.mode !== BT || min > 0) return Fail;
757
+ s.pos = start;
758
+ return acc;
759
+ }
760
+ acc?.push(first);
761
+ count = 1;
762
+ }
763
+ while (count < max) {
764
+ const start = s.pos;
765
+ if (sep(s) === Fail) {
766
+ if (s.mode === INC && s.resume !== void 0) Resume.save(s, key, entry, {
767
+ acc,
768
+ count,
769
+ pos: start
770
+ });
771
+ if (s.mode !== BT || count < min) return Fail;
772
+ s.pos = start;
773
+ return resumed ? Resume.done(s, key, entry, true, acc) : acc;
774
+ }
775
+ if (checkLoop && s.pos === start) {
776
+ s.mode = CUT;
777
+ return Fail;
778
+ }
779
+ const a = c(s);
780
+ if (a === Fail) {
781
+ if (s.mode === INC && s.resume !== void 0) Resume.save(s, key, entry, {
782
+ acc,
783
+ count,
784
+ pos: start
785
+ });
786
+ if (s.mode !== BT || count < min) return Fail;
787
+ s.pos = start;
788
+ return resumed ? Resume.done(s, key, entry, true, acc) : acc;
789
+ }
790
+ acc?.push(a);
791
+ count++;
792
+ }
793
+ return resumed ? Resume.done(s, key, entry, true, acc) : acc;
794
+ };
795
+ }
796
+ separatedFold(node) {
797
+ const c = this.compile(node.self, true);
798
+ const sep = this.compile(node.separator, true);
799
+ const op = node.op;
800
+ const resumable = this.resumable;
801
+ const key = {};
802
+ if (!node.right) return (s) => {
803
+ const entry = s.pos;
804
+ let acc;
805
+ let resumed = false;
806
+ if (resumable && s.resume !== void 0) {
807
+ const cp = Resume.take(s, key, entry);
808
+ if (cp instanceof Resume.Done) {
809
+ s.pos = cp.pos;
810
+ return cp.value;
811
+ }
812
+ if (cp !== void 0) {
813
+ acc = cp.acc;
814
+ s.pos = cp.pos;
815
+ resumed = true;
816
+ }
817
+ }
818
+ if (!resumed) {
819
+ acc = c(s);
820
+ if (acc === Fail) return Fail;
821
+ }
822
+ while (true) {
823
+ const start = s.pos;
824
+ const x = sep(s);
825
+ if (x === Fail) {
826
+ if (s.mode === INC && s.resume !== void 0) Resume.save(s, key, entry, {
827
+ acc,
828
+ pos: start
829
+ });
830
+ if (s.mode !== BT) return Fail;
831
+ s.pos = start;
832
+ return resumed ? Resume.done(s, key, entry, true, acc) : acc;
833
+ }
834
+ if (s.pos === start) {
835
+ s.mode = CUT;
836
+ return Fail;
837
+ }
838
+ const a = c(s);
839
+ if (a === Fail) {
840
+ if (s.mode === INC && s.resume !== void 0) Resume.save(s, key, entry, {
841
+ acc,
842
+ pos: start
843
+ });
844
+ if (s.mode !== BT) return Fail;
845
+ s.pos = start;
846
+ return resumed ? Resume.done(s, key, entry, true, acc) : acc;
847
+ }
848
+ acc = op(acc, x, a);
849
+ }
850
+ };
851
+ return (s) => {
852
+ const first = c(s);
853
+ if (first === Fail) return Fail;
854
+ const values = [first];
855
+ const seps = [];
856
+ while (true) {
857
+ const start = s.pos;
858
+ const x = sep(s);
859
+ if (x === Fail) {
860
+ if (s.mode !== BT) return Fail;
861
+ s.pos = start;
862
+ break;
863
+ }
864
+ if (s.pos === start) {
865
+ s.mode = CUT;
866
+ return Fail;
867
+ }
868
+ const a = c(s);
869
+ if (a === Fail) {
870
+ if (s.mode !== BT) return Fail;
871
+ s.pos = start;
872
+ break;
873
+ }
874
+ seps.push(x);
875
+ values.push(a);
876
+ }
877
+ let acc = values[values.length - 1];
878
+ for (let i = seps.length - 1; i >= 0; i--) acc = op(values[i], seps[i], acc);
879
+ return acc;
880
+ };
881
+ }
882
+ token(p, node, used) {
883
+ const kind = this.kind;
884
+ switch (node._tag) {
885
+ case "Any":
886
+ if (kind === 1) return (s) => {
887
+ const pos = s.pos;
888
+ if (pos >= s.end) return fail(s);
889
+ s.pos = pos + 1;
890
+ return s.input[pos];
891
+ };
892
+ return (s) => {
893
+ const pos = s.pos;
894
+ if (pos >= s.end) return fail(s);
895
+ const str = s.input;
896
+ const c = str.charCodeAt(pos);
897
+ if (c >= 55296 && c <= 56319 && pos + 1 < str.length && (str.charCodeAt(pos + 1) & 64512) === 56320) {
898
+ s.pos = pos + 2;
899
+ return used ? str.slice(pos, pos + 2) : void 0;
900
+ }
901
+ s.pos = pos + 1;
902
+ return used ? str[pos] : void 0;
903
+ };
904
+ case "Literal": return this.tokenLiteral(p, node);
905
+ case "OneOf": {
906
+ const set = tokenSet(node.set, kind);
907
+ const negate = node.negate;
908
+ const accept = acceptTable(set, negate);
909
+ const test = set.test;
910
+ if (kind === 1) return (s) => {
911
+ const pos = s.pos;
912
+ if (pos >= s.end) return fail(s);
913
+ const b = s.input[pos];
914
+ if (accept[b] === 0) return fail(s);
915
+ s.pos = pos + 1;
916
+ return b;
917
+ };
918
+ return (s) => {
919
+ const pos = s.pos;
920
+ if (pos >= s.end) return fail(s);
921
+ const str = s.input;
922
+ const c = str.charCodeAt(pos);
923
+ if (c < TableSize) {
924
+ if (accept[c] === 0) return fail(s);
925
+ s.pos = pos + 1;
926
+ return used ? str[pos] : void 0;
927
+ }
928
+ let cp = c;
929
+ if (c >= 55296 && c <= 56319 && pos + 1 < str.length) {
930
+ const d = str.charCodeAt(pos + 1);
931
+ if ((d & 64512) === 56320) cp = (c - 55296 << 10) + (d - 56320) + 65536;
932
+ }
933
+ if (test(cp) === negate) return fail(s);
934
+ const len = cp > 65535 ? 2 : 1;
935
+ s.pos = pos + len;
936
+ return !used ? void 0 : len === 1 ? str[pos] : str.slice(pos, pos + 2);
937
+ };
938
+ }
939
+ case "Take": {
940
+ const count = node.count;
941
+ if (kind === 1) return (s) => {
942
+ const start = s.pos;
943
+ if (s.end - start < count) return failAt(s, s.end);
944
+ s.pos = start + count;
945
+ return used ? s.input.subarray(start, start + count) : void 0;
946
+ };
947
+ return (s) => {
948
+ const str = s.input;
949
+ const start = s.pos;
950
+ const end = s.end;
951
+ let i = start;
952
+ let got = 0;
953
+ while (got < count && i < end) {
954
+ const c = str.charCodeAt(i);
955
+ i += c >= 55296 && c <= 56319 && i + 1 < str.length && (str.charCodeAt(i + 1) & 64512) === 56320 ? 2 : 1;
956
+ got++;
957
+ }
958
+ if (got < count) return failAt(s, i);
959
+ s.pos = i;
960
+ return used ? str.slice(start, i) : void 0;
961
+ };
962
+ }
963
+ case "TakeWhile": return this.tokenTakeWhile(node, used);
964
+ case "TakeUntil": {
965
+ const { literal, max, min } = node;
966
+ const bounded = min > 0 || max !== Infinity;
967
+ return (s) => {
968
+ const start = s.pos;
969
+ const idx = indexOf(s, literal, start);
970
+ if (idx < 0) return failAt(s, s.end);
971
+ if (bounded) {
972
+ const count = countTokens(s, start, idx);
973
+ if (count < min || count > max) return failAt(s, idx);
974
+ }
975
+ s.pos = idx;
976
+ return used ? s.slice(start, idx) : void 0;
977
+ };
978
+ }
979
+ case "Rest": return (s) => {
980
+ const start = s.pos;
981
+ s.pos = s.end;
982
+ return used ? s.slice(start, s.end) : void 0;
983
+ };
984
+ }
985
+ }
986
+ tokenLiteral(p, node) {
987
+ const lit = node.literal;
988
+ const literalKind = Predicate.isString(lit) ? 0 : lit instanceof Uint8Array ? 1 : 2;
989
+ if (this.kind === 0) {
990
+ if (literalKind !== 0) return this.fallback(p, node, "byte or array literal on string input");
991
+ const str = lit;
992
+ const len = str.length;
993
+ if (node.caseless) {
994
+ const lowered = Array.from({ length: len }, (_, i) => lowerAscii(str.charCodeAt(i)));
995
+ return (s) => {
996
+ const pos = s.pos;
997
+ if (s.end - pos < len) return fail(s);
998
+ const input = s.input;
999
+ for (let i = 0; i < len; i++) if (lowerAscii(input.charCodeAt(pos + i)) !== lowered[i]) return fail(s);
1000
+ s.pos = pos + len;
1001
+ return input.slice(pos, pos + len);
1002
+ };
1003
+ }
1004
+ return stringLiteral(str, str);
1005
+ }
1006
+ if (literalKind === 2) return this.fallback(p, node, "array literal on byte input");
1007
+ const bytes = literalKind === 0 ? new TextEncoder().encode(lit) : lit;
1008
+ const len = bytes.length;
1009
+ const sameKind = literalKind === 1 && !node.caseless;
1010
+ const expect = node.caseless ? Array.from(bytes, lowerAscii) : Array.from(bytes);
1011
+ const caseless = node.caseless;
1012
+ return (s) => {
1013
+ const pos = s.pos;
1014
+ if (s.end - pos < len) return fail(s);
1015
+ const input = s.input;
1016
+ for (let i = 0; i < len; i++) {
1017
+ const b = input[pos + i];
1018
+ if ((caseless ? lowerAscii(b) : b) !== expect[i]) return fail(s);
1019
+ }
1020
+ s.pos = pos + len;
1021
+ return sameKind ? lit : input.subarray(pos, pos + len);
1022
+ };
1023
+ }
1024
+ tokenTakeWhile(node, used) {
1025
+ const kind = this.kind;
1026
+ const { max, min, negate } = node;
1027
+ const set = tokenSet(node.set, kind);
1028
+ const accept = acceptTable(set, negate);
1029
+ if (kind === 1) return (s) => {
1030
+ const bytes = s.input;
1031
+ const start = s.pos;
1032
+ const limit = max === Infinity ? s.end : Math.min(s.end, start + max);
1033
+ let i = start;
1034
+ while (i < limit && accept[bytes[i]] === 1) i++;
1035
+ if (i - start < min) return failAt(s, i);
1036
+ s.pos = i;
1037
+ return used ? bytes.subarray(start, i) : void 0;
1038
+ };
1039
+ const test = set.test;
1040
+ return (s) => {
1041
+ const str = s.input;
1042
+ const start = s.pos;
1043
+ const end = s.end;
1044
+ let i = start;
1045
+ let count = 0;
1046
+ while (count < max && i < end) {
1047
+ const c = str.charCodeAt(i);
1048
+ if (c < TableSize) {
1049
+ if (accept[c] === 0) break;
1050
+ i++;
1051
+ } else if (c < 55296 || c > 56319) {
1052
+ if (test(c) === negate) break;
1053
+ i++;
1054
+ } else {
1055
+ let cp = c;
1056
+ if (i + 1 < str.length) {
1057
+ const d = str.charCodeAt(i + 1);
1058
+ if ((d & 64512) === 56320) cp = (c - 55296 << 10) + (d - 56320) + 65536;
1059
+ }
1060
+ if (test(cp) === negate) break;
1061
+ i += cp > 65535 ? 2 : 1;
1062
+ }
1063
+ count++;
1064
+ }
1065
+ if (count < min) return failAt(s, i);
1066
+ s.pos = i;
1067
+ return used ? str.slice(start, i) : void 0;
1068
+ };
1069
+ }
1070
+ text(p, node, enc, used) {
1071
+ const kind = this.kind;
1072
+ const fast = fastLimit(enc);
1073
+ const decode = enc.decode;
1074
+ const width = enc.width;
1075
+ const toText = enc.text;
1076
+ const unitAt = kind === 0 ? (input, i) => input.charCodeAt(i) : (input, i) => input[i];
1077
+ switch (node._tag) {
1078
+ case "Any": return (s) => {
1079
+ const pos = s.pos;
1080
+ const end = s.end;
1081
+ if (pos >= end) return fail(s);
1082
+ const c = unitAt(s.input, pos);
1083
+ if (c < fast) {
1084
+ s.pos = pos + 1;
1085
+ return used ? charOf(c) : void 0;
1086
+ }
1087
+ const cp = decode(s.input, pos, end);
1088
+ if (cp < 0) return fail(s);
1089
+ s.pos = pos + width(cp);
1090
+ return used ? charOf(cp) : void 0;
1091
+ };
1092
+ case "Literal": {
1093
+ const lit = node.literal;
1094
+ if (node.caseless) {
1095
+ const folded = Array.from(lit, (c) => fold(firstCodePoint(c)));
1096
+ const n = folded.length;
1097
+ return (s) => {
1098
+ const start = s.pos;
1099
+ const end = s.end;
1100
+ const input = s.input;
1101
+ let pos = start;
1102
+ for (let i = 0; i < n; i++) {
1103
+ if (pos >= end) return failAt(s, pos);
1104
+ const c = unitAt(input, pos);
1105
+ let cp;
1106
+ if (c < fast) {
1107
+ cp = c;
1108
+ pos++;
1109
+ } else {
1110
+ cp = decode(input, pos, end);
1111
+ if (cp < 0) return failAt(s, pos);
1112
+ pos += width(cp);
1113
+ }
1114
+ if (fold(cp) !== folded[i]) return failAt(s, pos);
1115
+ }
1116
+ s.pos = pos;
1117
+ return used ? toText(input, start, pos) : void 0;
1118
+ };
1119
+ }
1120
+ const encoded = enc.encode(lit);
1121
+ if (Predicate.isString(encoded)) return stringLiteral(encoded, lit);
1122
+ const bytes = encoded;
1123
+ const len = bytes.length;
1124
+ if (len === 1) {
1125
+ const b0 = bytes[0];
1126
+ return (s) => {
1127
+ const pos = s.pos;
1128
+ if (pos < s.end && s.input[pos] === b0) {
1129
+ s.pos = pos + 1;
1130
+ return lit;
1131
+ }
1132
+ return fail(s);
1133
+ };
1134
+ }
1135
+ return (s) => {
1136
+ const pos = s.pos;
1137
+ if (s.end - pos < len) return fail(s);
1138
+ const input = s.input;
1139
+ for (let i = 0; i < len; i++) if (input[pos + i] !== bytes[i]) return fail(s);
1140
+ s.pos = pos + len;
1141
+ return lit;
1142
+ };
1143
+ }
1144
+ case "OneOf": {
1145
+ const set = textSet(node.set);
1146
+ const negate = node.negate;
1147
+ const accept = acceptTable(set, negate);
1148
+ const test = set.test;
1149
+ return (s) => {
1150
+ const pos = s.pos;
1151
+ const end = s.end;
1152
+ if (pos >= end) return fail(s);
1153
+ const c = unitAt(s.input, pos);
1154
+ if (c < fast && c < TableSize) {
1155
+ if (accept[c] === 0) return fail(s);
1156
+ s.pos = pos + 1;
1157
+ return used ? charOf(c) : void 0;
1158
+ }
1159
+ const cp = c < fast ? c : decode(s.input, pos, end);
1160
+ if (cp < 0 || test(cp) === negate) return fail(s);
1161
+ s.pos = pos + (c < fast ? 1 : width(cp));
1162
+ return used ? charOf(cp) : void 0;
1163
+ };
1164
+ }
1165
+ case "Take": {
1166
+ const count = node.count;
1167
+ return (s) => {
1168
+ const start = s.pos;
1169
+ const end = s.end;
1170
+ const input = s.input;
1171
+ let pos = start;
1172
+ for (let got = 0; got < count; got++) {
1173
+ if (pos >= end) return failAt(s, pos);
1174
+ if (unitAt(input, pos) < fast) pos++;
1175
+ else {
1176
+ const cp = decode(input, pos, end);
1177
+ if (cp < 0) return failAt(s, pos);
1178
+ pos += width(cp);
1179
+ }
1180
+ }
1181
+ s.pos = pos;
1182
+ return used ? toText(input, start, pos) : void 0;
1183
+ };
1184
+ }
1185
+ case "TakeWhile": {
1186
+ const { max, min, negate } = node;
1187
+ const set = textSet(node.set);
1188
+ const accept = acceptTable(set, negate);
1189
+ const test = set.test;
1190
+ const small = Math.min(fast, TableSize);
1191
+ return (s) => {
1192
+ const input = s.input;
1193
+ const start = s.pos;
1194
+ const end = s.end;
1195
+ let i = start;
1196
+ let count = 0;
1197
+ while (count < max && i < end) {
1198
+ const c = unitAt(input, i);
1199
+ if (c < small) {
1200
+ if (accept[c] === 0) break;
1201
+ i++;
1202
+ } else if (c < fast) {
1203
+ if (test(c) === negate) break;
1204
+ i++;
1205
+ } else {
1206
+ const cp = decode(input, i, end);
1207
+ if (cp < 0 || test(cp) === negate) break;
1208
+ i += width(cp);
1209
+ }
1210
+ count++;
1211
+ }
1212
+ if (count < min) return failAt(s, i);
1213
+ s.pos = i;
1214
+ return used ? toText(input, start, i) : void 0;
1215
+ };
1216
+ }
1217
+ case "TakeUntil":
1218
+ case "Rest": return this.fallback(p, node, "Text parser without a compiled form");
1219
+ }
1220
+ }
1221
+ taken(node, used) {
1222
+ const c = this.compile(node.self, false);
1223
+ const enc = node.encoding;
1224
+ if (enc === void 0) {
1225
+ if (!used) return c;
1226
+ if (this.kind === 0) return (s) => {
1227
+ const start = s.pos;
1228
+ return c(s) === Fail ? Fail : s.input.slice(start, s.pos);
1229
+ };
1230
+ return (s) => {
1231
+ const start = s.pos;
1232
+ return c(s) === Fail ? Fail : s.slice(start, s.pos);
1233
+ };
1234
+ }
1235
+ const fast = fastLimit(enc);
1236
+ const toText = enc.text;
1237
+ const unitAt = this.kind === 0 ? (input, i) => input.charCodeAt(i) : (input, i) => input[i];
1238
+ return (s) => {
1239
+ const start = s.pos;
1240
+ if (c(s) === Fail) return Fail;
1241
+ const end = s.pos;
1242
+ const input = s.input;
1243
+ let i = start;
1244
+ while (i < end && unitAt(input, i) < fast) i++;
1245
+ if (i < end && validate(enc, s, i, end) < 0) return fail(s);
1246
+ return used ? toText(input, start, end) : void 0;
1247
+ };
1248
+ }
1249
+ /**
1250
+ * `Ascii.float` and `Text.float` (`map(floatText, toFloat)`): numbers in
1251
+ * decimal notation are matched and converted in one pass, without
1252
+ * slicing the input; the rest runs the compiled parser (see the JIT).
1253
+ */
1254
+ float(node) {
1255
+ if (!floatTexts.has(node.self) || this.kind === 2) return void 0;
1256
+ let taken = nodeOf(node.self);
1257
+ while (taken._tag === "Expected") taken = nodeOf(taken.self);
1258
+ if (taken._tag !== "Taken") return void 0;
1259
+ const enc = taken.encoding;
1260
+ if (enc !== void 0 && !(this.native(enc) && enc.unit === 1 && enc.asciiCompatible)) return void 0;
1261
+ const c = this.compile(node.self, true);
1262
+ const scan = this.kind === 0 ? scanFloatString : scanFloatBytes;
1263
+ const resumable = this.resumable;
1264
+ return (s) => {
1265
+ const v = scan(s.input, s.pos, s.end);
1266
+ if (v === void 0 || resumable && s.partial && floatScan.read + Margin > s.end) {
1267
+ const t = c(s);
1268
+ return t === Fail ? Fail : toFloat(t);
1269
+ }
1270
+ if (v === Fail) return fail(s);
1271
+ s.pos = floatScan.end;
1272
+ return v;
1273
+ };
1274
+ }
1275
+ escaped(node) {
1276
+ const raw = node.raw;
1277
+ const normal = this.compile(node.normal, !raw);
1278
+ const escape = this.compile(node.escape, !raw);
1279
+ const enc = node.encoding;
1280
+ const ctrl = node.control;
1281
+ const kind = this.kind;
1282
+ let control;
1283
+ if (enc === void 0 || ctrl < fastLimit(enc) && ctrl < TableSize) control = kind === 0 ? (s) => {
1284
+ if (s.pos < s.end && s.input.charCodeAt(s.pos) === ctrl) {
1285
+ s.pos++;
1286
+ return true;
1287
+ }
1288
+ return false;
1289
+ } : (s) => {
1290
+ if (s.pos < s.end && s.input[s.pos] === ctrl) {
1291
+ s.pos++;
1292
+ return true;
1293
+ }
1294
+ return false;
1295
+ };
1296
+ else control = (s) => {
1297
+ if (s.pos >= s.end) return false;
1298
+ const cp = enc.decode(s.input, s.pos, s.end);
1299
+ if (cp !== ctrl) return false;
1300
+ s.pos += enc.width(cp);
1301
+ return true;
1302
+ };
1303
+ const resumable = this.resumable;
1304
+ const key = {};
1305
+ /** Fails as incomplete, keeping a checkpoint in a streaming parse. */
1306
+ const incomplete = (s, start, checkpoint) => {
1307
+ if (s.resume !== void 0) Resume.save(s, key, start, checkpoint);
1308
+ s.mode = INC;
1309
+ return Fail;
1310
+ };
1311
+ if (raw) {
1312
+ const slice = enc === void 0 ? (s, start) => s.slice(start, s.pos) : (s, start) => enc.text(s.input, start, s.pos);
1313
+ return (s) => {
1314
+ const start = s.pos;
1315
+ let resumed = false;
1316
+ if (resumable && s.resume !== void 0) {
1317
+ const cp = Resume.take(s, key, start);
1318
+ if (cp instanceof Resume.Done) {
1319
+ s.pos = cp.pos;
1320
+ return cp.value;
1321
+ }
1322
+ if (cp !== void 0) {
1323
+ s.pos = cp;
1324
+ resumed = true;
1325
+ }
1326
+ }
1327
+ while (s.pos < s.end) {
1328
+ const before = s.pos;
1329
+ if (normal(s) !== Fail) {
1330
+ if (s.pos === before) {
1331
+ s.mode = CUT;
1332
+ return Fail;
1333
+ }
1334
+ continue;
1335
+ }
1336
+ if (s.mode === INC) return incomplete(s, start, before);
1337
+ if (s.mode !== BT) return Fail;
1338
+ s.pos = before;
1339
+ if (control(s)) {
1340
+ if (escape(s) === Fail) return s.mode === INC ? incomplete(s, start, before) : Fail;
1341
+ } else return resumed ? Resume.done(s, key, start, true, slice(s, start)) : slice(s, start);
1342
+ }
1343
+ if (s.partial) return incomplete(s, start, s.pos);
1344
+ return resumed ? Resume.done(s, key, start, true, slice(s, start)) : slice(s, start);
1345
+ };
1346
+ }
1347
+ return (s) => {
1348
+ const start = s.pos;
1349
+ let out = "";
1350
+ let resumed = false;
1351
+ if (resumable && s.resume !== void 0) {
1352
+ const cp = Resume.take(s, key, start);
1353
+ if (cp instanceof Resume.Done) {
1354
+ s.pos = cp.pos;
1355
+ return cp.value;
1356
+ }
1357
+ if (cp !== void 0) {
1358
+ out = cp.out;
1359
+ s.pos = cp.pos;
1360
+ resumed = true;
1361
+ }
1362
+ }
1363
+ while (s.pos < s.end) {
1364
+ const before = s.pos;
1365
+ const a = normal(s);
1366
+ if (a !== Fail) {
1367
+ if (s.pos !== before) {
1368
+ out += a;
1369
+ continue;
1370
+ }
1371
+ } else {
1372
+ if (s.mode === INC) return incomplete(s, start, {
1373
+ out,
1374
+ pos: before
1375
+ });
1376
+ if (s.mode !== BT) return Fail;
1377
+ s.pos = before;
1378
+ }
1379
+ if (control(s)) {
1380
+ const b = escape(s);
1381
+ if (b === Fail) return s.mode === INC ? incomplete(s, start, {
1382
+ out,
1383
+ pos: before
1384
+ }) : Fail;
1385
+ out += b;
1386
+ } else return resumed ? Resume.done(s, key, start, true, out) : out;
1387
+ }
1388
+ if (s.partial) return incomplete(s, start, {
1389
+ out,
1390
+ pos: s.pos
1391
+ });
1392
+ return resumed ? Resume.done(s, key, start, true, out) : out;
1393
+ };
1394
+ }
1395
+ };
1594
1396
  const fail = (s) => {
1595
- s.mode = BT;
1596
- return Fail;
1397
+ s.mode = BT;
1398
+ return Fail;
1597
1399
  };
1598
1400
  /** Fails, leaving the cursor at `pos`: how far a token parser read (see `partialSafe`). */
1599
1401
  const failAt = (s, pos) => {
1600
- s.pos = pos;
1601
- s.mode = BT;
1602
- return Fail;
1402
+ s.pos = pos;
1403
+ s.mode = BT;
1404
+ return Fail;
1603
1405
  };
1604
1406
  /** 1 where a small code is accepted (taking `negate` into account). */
1605
1407
  const acceptTable = (set, negate) => {
1606
- const t = new Uint8Array(TableSize);
1607
- for (let c = 0; c < TableSize; c++)
1608
- t[c] = (set.table[c] === 1) !== negate ? 1 : 0;
1609
- return t;
1408
+ const t = new Uint8Array(TableSize);
1409
+ for (let c = 0; c < TableSize; c++) t[c] = set.table[c] === 1 !== negate ? 1 : 0;
1410
+ return t;
1610
1411
  };
1611
1412
  /** A literal matched against a string input, returning `value`. */
1612
1413
  const stringLiteral = (str, value) => {
1613
- const len = str.length;
1614
- if (len === 0)
1615
- return () => value;
1616
- if (len === 1) {
1617
- const c0 = str.charCodeAt(0);
1618
- return (s) => {
1619
- const pos = s.pos;
1620
- if (pos < s.end && s.input.charCodeAt(pos) === c0) {
1621
- s.pos = pos + 1;
1622
- return value;
1623
- }
1624
- return fail(s);
1625
- };
1626
- }
1627
- return (s) => {
1628
- const pos = s.pos;
1629
- if (s.end - pos >= len && s.input.startsWith(str, pos)) {
1630
- s.pos = pos + len;
1631
- return value;
1632
- }
1633
- return fail(s);
1634
- };
1414
+ const len = str.length;
1415
+ if (len === 0) return () => value;
1416
+ if (len === 1) {
1417
+ const c0 = str.charCodeAt(0);
1418
+ return (s) => {
1419
+ const pos = s.pos;
1420
+ if (pos < s.end && s.input.charCodeAt(pos) === c0) {
1421
+ s.pos = pos + 1;
1422
+ return value;
1423
+ }
1424
+ return fail(s);
1425
+ };
1426
+ }
1427
+ return (s) => {
1428
+ const pos = s.pos;
1429
+ if (s.end - pos >= len && s.input.startsWith(str, pos)) {
1430
+ s.pos = pos + len;
1431
+ return value;
1432
+ }
1433
+ return fail(s);
1434
+ };
1635
1435
  };
1636
1436
  /** A closure compiler for one input kind; it memoizes what it compiles. */
1637
1437
  /** The object of `Object.fromEntries`, built an entry at a time (see `internal/entries.ts`). */
1638
- class EntriesAcc {
1639
- o = {};
1640
- deferred = undefined;
1641
- add(key, value) {
1642
- if (this.deferred === undefined && isPlainKey(key))
1643
- this.o[key] = value;
1644
- else
1645
- this.deferred = addEntry(this.o, this.deferred, key, value);
1646
- }
1647
- result() {
1648
- if (this.deferred !== undefined)
1649
- flushEntries(this.o, this.deferred);
1650
- return this.o;
1651
- }
1652
- }
1653
- export const createClosureCompiler = (kind, resumable = false) => {
1654
- const compiler = new Compiler(kind, resumable);
1655
- return {
1656
- compile: (p, used) => compiler.compile(p, used),
1657
- note: (p, node, reason) => compiler.note(p, node, reason),
1658
- firsts: compiler.firsts,
1659
- fallbacks: compiler.fallbacks
1660
- };
1438
+ var EntriesAcc = class {
1439
+ o = {};
1440
+ deferred = void 0;
1441
+ add(key, value) {
1442
+ if (this.deferred === void 0 && isPlainKey(key)) this.o[key] = value;
1443
+ else this.deferred = addEntry(this.o, this.deferred, key, value);
1444
+ }
1445
+ result() {
1446
+ if (this.deferred !== void 0) flushEntries(this.o, this.deferred);
1447
+ return this.o;
1448
+ }
1449
+ };
1450
+ const createClosureCompiler = (kind, resumable = false) => {
1451
+ const compiler = new Compiler(kind, resumable);
1452
+ return {
1453
+ compile: (p, used) => compiler.compile(p, used),
1454
+ note: (p, node, reason) => compiler.note(p, node, reason),
1455
+ firsts: compiler.firsts,
1456
+ fallbacks: compiler.fallbacks
1457
+ };
1661
1458
  };
1662
1459
  /** Compiles a root parser for one input kind. */
1663
- export const compileClosure = (root, kind, resumable = false) => {
1664
- const compiler = new Compiler(kind, resumable);
1665
- const step = compiler.compile(root, true);
1666
- return { step, fallbacks: compiler.fallbacks };
1460
+ const compileClosure = (root, kind, resumable = false) => {
1461
+ const compiler = new Compiler(kind, resumable);
1462
+ return {
1463
+ step: compiler.compile(root, true),
1464
+ fallbacks: compiler.fallbacks
1465
+ };
1667
1466
  };
1467
+ /** The closure compiler as a backend. */
1468
+ const backend = { build: (p, kind, resumable) => {
1469
+ try {
1470
+ const { fallbacks, step } = compileClosure(p, kind, resumable);
1471
+ return {
1472
+ backend: "closure",
1473
+ step,
1474
+ fallbacks,
1475
+ error: void 0
1476
+ };
1477
+ } catch (error) {
1478
+ return {
1479
+ backend: void 0,
1480
+ step: void 0,
1481
+ fallbacks: [],
1482
+ error
1483
+ };
1484
+ }
1485
+ } };
1486
+ //#endregion
1487
+ export { backend, createClosureCompiler };
1488
+
1668
1489
  //# sourceMappingURL=closure.js.map