@thomasfosterau/effect-parse 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/CHANGELOG.md +202 -0
  2. package/README.md +56 -14
  3. package/dist/Ascii.d.ts +11 -4
  4. package/dist/Ascii.d.ts.map +1 -1
  5. package/dist/Ascii.js +12 -4
  6. package/dist/Ascii.js.map +1 -1
  7. package/dist/Binary.d.ts +5 -2
  8. package/dist/Binary.d.ts.map +1 -1
  9. package/dist/Binary.js +83 -37
  10. package/dist/Binary.js.map +1 -1
  11. package/dist/Bits.d.ts.map +1 -1
  12. package/dist/Bits.js +11 -4
  13. package/dist/Bits.js.map +1 -1
  14. package/dist/Compiler.d.ts +74 -2
  15. package/dist/Compiler.d.ts.map +1 -1
  16. package/dist/Compiler.js +78 -1
  17. package/dist/Compiler.js.map +1 -1
  18. package/dist/Expression.d.ts.map +1 -1
  19. package/dist/Expression.js +86 -74
  20. package/dist/Expression.js.map +1 -1
  21. package/dist/Input.d.ts +56 -5
  22. package/dist/Input.d.ts.map +1 -1
  23. package/dist/Input.js +70 -1
  24. package/dist/Input.js.map +1 -1
  25. package/dist/Nom.d.ts +5 -15
  26. package/dist/Nom.d.ts.map +1 -1
  27. package/dist/Nom.js.map +1 -1
  28. package/dist/ParseError.d.ts +69 -11
  29. package/dist/ParseError.d.ts.map +1 -1
  30. package/dist/ParseError.js +129 -28
  31. package/dist/ParseError.js.map +1 -1
  32. package/dist/Parser.d.ts +375 -29
  33. package/dist/Parser.d.ts.map +1 -1
  34. package/dist/Parser.js +394 -37
  35. package/dist/Parser.js.map +1 -1
  36. package/dist/ParserSchema.d.ts.map +1 -1
  37. package/dist/ParserSchema.js +2 -3
  38. package/dist/ParserSchema.js.map +1 -1
  39. package/dist/ParserStream.d.ts +122 -14
  40. package/dist/ParserStream.d.ts.map +1 -1
  41. package/dist/ParserStream.js +293 -62
  42. package/dist/ParserStream.js.map +1 -1
  43. package/dist/Syntax.d.ts +23 -5
  44. package/dist/Syntax.d.ts.map +1 -1
  45. package/dist/Syntax.js +1 -1
  46. package/dist/Syntax.js.map +1 -1
  47. package/dist/Text.d.ts.map +1 -1
  48. package/dist/Text.js +21 -15
  49. package/dist/Text.js.map +1 -1
  50. package/dist/Token.d.ts +65 -11
  51. package/dist/Token.d.ts.map +1 -1
  52. package/dist/Token.js +73 -26
  53. package/dist/Token.js.map +1 -1
  54. package/dist/internal/compiler/closure.d.ts +1 -1
  55. package/dist/internal/compiler/closure.d.ts.map +1 -1
  56. package/dist/internal/compiler/closure.js +263 -113
  57. package/dist/internal/compiler/closure.js.map +1 -1
  58. package/dist/internal/compiler/entries.d.ts +3 -1
  59. package/dist/internal/compiler/entries.d.ts.map +1 -1
  60. package/dist/internal/compiler/entries.js +3 -2
  61. package/dist/internal/compiler/entries.js.map +1 -1
  62. package/dist/internal/compiler/first.d.ts.map +1 -1
  63. package/dist/internal/compiler/first.js +9 -2
  64. package/dist/internal/compiler/first.js.map +1 -1
  65. package/dist/internal/compiler/graph.d.ts +39 -0
  66. package/dist/internal/compiler/graph.d.ts.map +1 -0
  67. package/dist/internal/compiler/graph.js +78 -0
  68. package/dist/internal/compiler/graph.js.map +1 -0
  69. package/dist/internal/compiler/jit.d.ts +5 -0
  70. package/dist/internal/compiler/jit.d.ts.map +1 -1
  71. package/dist/internal/compiler/jit.js +208 -106
  72. package/dist/internal/compiler/jit.js.map +1 -1
  73. package/dist/internal/compiler/registry.d.ts +11 -3
  74. package/dist/internal/compiler/registry.d.ts.map +1 -1
  75. package/dist/internal/compiler/registry.js.map +1 -1
  76. package/dist/internal/compiler/search.d.ts +32 -0
  77. package/dist/internal/compiler/search.d.ts.map +1 -0
  78. package/dist/internal/compiler/search.js +68 -0
  79. package/dist/internal/compiler/search.js.map +1 -0
  80. package/dist/internal/compiler/sets.d.ts.map +1 -1
  81. package/dist/internal/compiler/sets.js +1 -1
  82. package/dist/internal/compiler/sets.js.map +1 -1
  83. package/dist/internal/compiler/wasm.d.ts +8 -0
  84. package/dist/internal/compiler/wasm.d.ts.map +1 -0
  85. package/dist/internal/compiler/wasm.js +2840 -0
  86. package/dist/internal/compiler/wasm.js.map +1 -0
  87. package/dist/internal/compiler/wasmAsm.d.ts +199 -0
  88. package/dist/internal/compiler/wasmAsm.d.ts.map +1 -0
  89. package/dist/internal/compiler/wasmAsm.js +427 -0
  90. package/dist/internal/compiler/wasmAsm.js.map +1 -0
  91. package/dist/internal/entries.d.ts +3 -1
  92. package/dist/internal/entries.d.ts.map +1 -1
  93. package/dist/internal/entries.js.map +1 -1
  94. package/dist/internal/node.d.ts +77 -3
  95. package/dist/internal/node.d.ts.map +1 -1
  96. package/dist/internal/node.js +54 -10
  97. package/dist/internal/node.js.map +1 -1
  98. package/dist/internal/numbers.d.ts.map +1 -1
  99. package/dist/internal/numbers.js.map +1 -1
  100. package/dist/internal/run.d.ts +14 -0
  101. package/dist/internal/run.d.ts.map +1 -1
  102. package/dist/internal/run.js +53 -11
  103. package/dist/internal/run.js.map +1 -1
  104. package/dist/internal/stack.d.ts +14 -0
  105. package/dist/internal/stack.d.ts.map +1 -1
  106. package/dist/internal/stack.js +24 -2
  107. package/dist/internal/stack.js.map +1 -1
  108. package/dist/internal/syntax.d.ts +4 -4
  109. package/dist/internal/syntax.d.ts.map +1 -1
  110. package/dist/internal/syntax.js +18 -10
  111. package/dist/internal/syntax.js.map +1 -1
  112. package/dist/internal/text.d.ts +32 -0
  113. package/dist/internal/text.d.ts.map +1 -1
  114. package/dist/internal/text.js +68 -14
  115. package/dist/internal/text.js.map +1 -1
  116. package/dist/internal/tokens.d.ts +20 -0
  117. package/dist/internal/tokens.d.ts.map +1 -1
  118. package/dist/internal/tokens.js +72 -39
  119. package/dist/internal/tokens.js.map +1 -1
  120. package/dist/internal/tuple.d.ts +6 -0
  121. package/dist/internal/tuple.d.ts.map +1 -0
  122. package/dist/internal/tuple.js +170 -0
  123. package/dist/internal/tuple.js.map +1 -0
  124. package/package.json +18 -10
  125. package/src/Ascii.ts +47 -12
  126. package/src/Binary.ts +174 -73
  127. package/src/Bits.ts +16 -6
  128. package/src/Compiler.ts +101 -10
  129. package/src/Expression.ts +94 -81
  130. package/src/Input.ts +99 -7
  131. package/src/Nom.ts +15 -5
  132. package/src/ParseError.ts +209 -52
  133. package/src/Parser.ts +684 -143
  134. package/src/ParserSchema.ts +1 -2
  135. package/src/ParserStream.ts +361 -68
  136. package/src/Syntax.ts +60 -36
  137. package/src/Text.ts +32 -27
  138. package/src/Token.ts +152 -34
  139. package/src/internal/compiler/closure.ts +371 -153
  140. package/src/internal/compiler/entries.ts +4 -2
  141. package/src/internal/compiler/first.ts +16 -0
  142. package/src/internal/compiler/graph.ts +96 -0
  143. package/src/internal/compiler/jit.ts +319 -169
  144. package/src/internal/compiler/registry.ts +10 -2
  145. package/src/internal/compiler/search.ts +68 -0
  146. package/src/internal/compiler/sets.ts +7 -3
  147. package/src/internal/compiler/wasm.ts +3276 -0
  148. package/src/internal/compiler/wasmAsm.ts +484 -0
  149. package/src/internal/entries.ts +8 -2
  150. package/src/internal/node.ts +103 -7
  151. package/src/internal/numbers.ts +3 -1
  152. package/src/internal/run.ts +73 -12
  153. package/src/internal/stack.ts +25 -1
  154. package/src/internal/syntax.ts +39 -18
  155. package/src/internal/text.ts +97 -9
  156. package/src/internal/tokens.ts +106 -14
  157. package/src/internal/tuple.ts +141 -0
@@ -3,14 +3,16 @@ import * as Result from "effect/Result";
3
3
  import { Fail } from "../../Input.js";
4
4
  import { floatScan, floatTexts, scanFloatBytes, scanFloatString, toFloat } from "../numbers.js";
5
5
  import { Key } from "../key.js";
6
+ import { Defer, nodeOf, scansFloat } from "../node.js";
6
7
  import * as Resume from "../resume.js";
7
- import { countTokens, indexOf } from "../tokens.js";
8
+ import { countTokens, indexOf, indexOfAny } from "../tokens.js";
8
9
  import * as Option from "effect/Option";
9
- import { charOf, fastLimit, firstCodePoint, fold, utf16be, utf16le, validate } from "../text.js";
10
+ import { charOf, fastLimit, firstCodePoint, fold, textIn, utf16be, utf16le, utf8, utf8Text, validate } from "../text.js";
10
11
  import { addEntry, flushEntries, fromEntries, isPlainKey } from "../entries.js";
11
- import { nodeOf, scansFloat } from "../node.js";
12
+ import { tupleStep } from "../tuple.js";
12
13
  import { buildsEntries, pairOf } from "./entries.js";
13
14
  import { FirstSets, planAlt } from "./first.js";
15
+ import { SearchHead, StopCache, nextStop, stopChars } from "./search.js";
14
16
  import { TableSize, acceptTable, kindOfEncoding, textSet, tokenSet } from "./sets.js";
15
17
  // src/internal/compiler/closure.ts
16
18
  /**
@@ -110,6 +112,8 @@ var Compiler = class {
110
112
  build(p, node, used) {
111
113
  switch (node._tag) {
112
114
  case "Opaque": return this.fallback(p, node, "not describable (Parser.make, gen, ...)");
115
+ case "Fixed": return p.step;
116
+ case "Combinator": return node.build(node.parsers.map((q) => this.compile(q, true)));
113
117
  case "Succeed": {
114
118
  const value = node.value;
115
119
  return () => value;
@@ -130,10 +134,7 @@ var Compiler = class {
130
134
  s.mode = BT;
131
135
  return Fail;
132
136
  }
133
- if (s.partial) {
134
- s.mode = INC;
135
- return Fail;
136
- }
137
+ if (s.partial) return s.incomplete(1);
137
138
  };
138
139
  case "Location": return (s) => s.pos;
139
140
  case "RestLen": return (s) => s.end - s.pos;
@@ -144,9 +145,10 @@ var Compiler = class {
144
145
  case "Take":
145
146
  case "TakeWhile":
146
147
  case "TakeUntil":
148
+ case "TakeUntilAny":
147
149
  case "Rest":
148
150
  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), Predicate.isTagged(node, "Literal") || Predicate.isTagged(node, "TakeUntil") ? node.literal.length * 4 : Margin);
151
+ return this.partialSafe(p, node.encoding === void 0 ? this.token(p, node, used) : this.text(p, node, node.encoding, used), marginOf(node));
150
152
  case "TillLineEnding":
151
153
  case "Identifier":
152
154
  case "Bom": return this.fallback(p, node, "leaf parser without a compiled form");
@@ -159,7 +161,7 @@ var Compiler = class {
159
161
  const step = this.float(node);
160
162
  if (step !== void 0) return step;
161
163
  }
162
- if (node.f === fromEntries && !this.resumable && buildsEntries(node.self)) return this.entries(node.self);
164
+ if (node.f === fromEntries && buildsEntries(node.self)) return this.entries(node.self);
163
165
  const c = this.compile(node.self, true);
164
166
  const f = node.f;
165
167
  return (s) => {
@@ -206,6 +208,28 @@ var Compiler = class {
206
208
  return Fail;
207
209
  };
208
210
  }
211
+ case "FastPath": {
212
+ const c = this.compile(node.self, used);
213
+ const fast = node.fast;
214
+ return (s) => {
215
+ const start = s.pos;
216
+ const a = fast(s);
217
+ if (a !== Defer) return a;
218
+ s.pos = start;
219
+ return c(s);
220
+ };
221
+ }
222
+ case "MapOrFail": {
223
+ const c = this.compile(node.self, true);
224
+ const f = node.f;
225
+ return (s) => {
226
+ const a = c(s);
227
+ if (a === Fail) return Fail;
228
+ const b = f(a);
229
+ if (b === Fail) s.mode = BT;
230
+ return b;
231
+ };
232
+ }
209
233
  case "Filter": {
210
234
  const c = this.compile(node.self, true);
211
235
  const predicate = node.predicate;
@@ -237,6 +261,16 @@ var Compiler = class {
237
261
  return a === Fail ? Fail : [a, s.slice(start, s.pos)];
238
262
  };
239
263
  }
264
+ case "MapSpan": {
265
+ const c = this.compile(node.self, used);
266
+ if (!used) return c;
267
+ const f = node.f;
268
+ return (s) => {
269
+ const start = s.pos;
270
+ const a = c(s);
271
+ return a === Fail ? Fail : f(a, start, s.pos);
272
+ };
273
+ }
240
274
  case "Span": {
241
275
  const c = this.compile(node.self, false);
242
276
  if (!used) return c;
@@ -271,6 +305,7 @@ var Compiler = class {
271
305
  }
272
306
  case "Context":
273
307
  case "Expected":
308
+ case "Quiet":
274
309
  case "MapError":
275
310
  case "OrFail":
276
311
  case "Trace":
@@ -336,6 +371,11 @@ var Compiler = class {
336
371
  return out;
337
372
  };
338
373
  }
374
+ case "SeqWith": {
375
+ const steps = node.parsers.map((q) => this.compile(q, used));
376
+ if (!used) return this.chain(steps);
377
+ return this.seqWith(steps, node.f);
378
+ }
339
379
  case "ZipWith": {
340
380
  const c1 = this.compile(node.self, used);
341
381
  const c2 = this.compile(node.that, used);
@@ -351,7 +391,22 @@ var Compiler = class {
351
391
  case "Alt": return this.alt(node, used);
352
392
  case "Dispatch": return this.dispatch(p, node, used);
353
393
  case "Repeat":
354
- case "Fold": return this.repeat(node, used);
394
+ case "Fold": {
395
+ const element = Predicate.isTagged(node, "Repeat") && !used ? nodeOf(node.self) : void 0;
396
+ if (element !== void 0 && Predicate.isTagged(element, "OneOf") && this.kind !== 2 && this.native(element.encoding)) {
397
+ const { encoding, negate, set } = element;
398
+ const run = {
399
+ _tag: "TakeWhile",
400
+ set,
401
+ negate,
402
+ encoding,
403
+ min: node.min,
404
+ max: node.max
405
+ };
406
+ return this.partialSafe(p, encoding === void 0 ? this.token(p, run, false) : this.text(p, run, encoding, false), Margin);
407
+ }
408
+ return this.repeat(node, used);
409
+ }
355
410
  case "RepeatTill": return this.repeatTill(node);
356
411
  case "Separated": return this.separated(node, used);
357
412
  case "SeparatedFold": return this.separatedFold(node);
@@ -359,13 +414,47 @@ var Compiler = class {
359
414
  case "Provide": return this.fallback(p, node, "services stay interpreted");
360
415
  }
361
416
  }
417
+ /** `seqWith`: up to three parsers without an array of values. */
418
+ seqWith(steps, f) {
419
+ const n = steps.length;
420
+ if (n === 0) return () => f();
421
+ const [c1, c2, c3] = steps;
422
+ if (n === 1) return (s) => {
423
+ const a = c1(s);
424
+ return a === Fail ? Fail : f(a);
425
+ };
426
+ if (n === 2) return (s) => {
427
+ const a = c1(s);
428
+ if (a === Fail) return Fail;
429
+ const b = c2(s);
430
+ return b === Fail ? Fail : f(a, b);
431
+ };
432
+ if (n === 3) return (s) => {
433
+ const a = c1(s);
434
+ if (a === Fail) return Fail;
435
+ const b = c2(s);
436
+ if (b === Fail) return Fail;
437
+ const c = c3(s);
438
+ return c === Fail ? Fail : f(a, b, c);
439
+ };
440
+ return (s) => {
441
+ const values = new Array(n);
442
+ for (let i = 0; i < n; i++) {
443
+ const a = steps[i](s);
444
+ if (a === Fail) return Fail;
445
+ values[i] = a;
446
+ }
447
+ return f(...values);
448
+ };
449
+ }
362
450
  /** Runs steps in order, for their effect on the cursor only. */
363
451
  chain(steps) {
364
452
  const n = steps.length;
365
453
  if (n === 0) return () => void 0;
366
454
  if (n === 1) return steps[0];
367
455
  if (n === 2) {
368
- const [a, b] = steps;
456
+ const a = steps[0];
457
+ const b = steps[1];
369
458
  return (s) => a(s) === Fail ? Fail : b(s);
370
459
  }
371
460
  return (s) => {
@@ -378,18 +467,11 @@ var Compiler = class {
378
467
  const steps = node.parsers.map((q, i) => this.compile(q, keep(i)));
379
468
  const n = steps.length;
380
469
  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
- };
470
+ if (output === "tuple") return tupleStep(steps);
390
471
  if (Predicate.isNumber(output)) {
391
472
  if (n === 2) {
392
- const [a, b] = steps;
473
+ const a = steps[0];
474
+ const b = steps[1];
393
475
  return output === 0 ? (s) => {
394
476
  const x = a(s);
395
477
  if (x === Fail) return Fail;
@@ -486,9 +568,9 @@ var Compiler = class {
486
568
  this.note(p, node, "the parser returned by the function of cases runs interpreted");
487
569
  return general;
488
570
  }
489
- let sel = nodeOf(node.selector);
490
- const peek = Predicate.isTagged(sel, "Peek");
491
- if (peek) sel = nodeOf(sel.self);
571
+ const top = nodeOf(node.selector);
572
+ const peek = Predicate.isTagged(top, "Peek");
573
+ const sel = peek ? nodeOf(top.self) : top;
492
574
  if (!Predicate.isTagged(sel, "Any") || !this.native(sel.encoding)) return general;
493
575
  const enc = sel.encoding;
494
576
  const limit = enc === void 0 ? this.kind === 0 ? 55296 : TableSize : Math.min(fastLimit(enc), 55296);
@@ -521,7 +603,6 @@ var Compiler = class {
521
603
  }
522
604
  repeat(node, used) {
523
605
  const { max, min } = node;
524
- const checkLoop = max === Infinity;
525
606
  const isFold = Predicate.isTagged(node, "Fold");
526
607
  const cond = isFold ? node.while : void 0;
527
608
  const c = this.compile(node.self, used);
@@ -566,7 +647,7 @@ var Compiler = class {
566
647
  s.pos = start;
567
648
  return resumed ? Resume.done(s, key, entry, true, acc) : acc;
568
649
  }
569
- if (checkLoop && s.pos === start) {
650
+ if (s.pos === start) {
570
651
  s.mode = CUT;
571
652
  return Fail;
572
653
  }
@@ -581,42 +662,39 @@ var Compiler = class {
581
662
  */
582
663
  entries(p) {
583
664
  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);
665
+ if (Predicate.isTagged(node, "Mode")) {
666
+ const c = this.entries(node.self);
667
+ const from = node.from;
668
+ const to = node.to;
669
+ return (s) => {
670
+ const a = c(s);
671
+ if (a === Fail && s.mode === from) s.mode = to;
672
+ return a;
673
+ };
674
+ }
675
+ if (Predicate.isTagged(node, "Seq")) {
676
+ const i = node.output;
677
+ const steps = node.parsers.map((q, j) => j === i ? this.entries(q) : this.compile(q, false));
678
+ return (s) => {
679
+ let out;
680
+ for (let j = 0; j < steps.length; j++) {
681
+ const a = steps[j](s);
682
+ if (a === Fail) return Fail;
683
+ if (j === i) out = a;
684
+ }
685
+ return out;
686
+ };
687
+ }
688
+ if (Predicate.isTagged(node, "Repeat") || Predicate.isTagged(node, "Separated")) {
689
+ const pair = pairOf(node.self);
690
+ if (pair !== void 0) return this.entriesLoop(node, pair);
691
+ const c = this.compile(p, true);
692
+ return (s) => {
693
+ const a = c(s);
694
+ return a === Fail ? Fail : fromEntries(a);
695
+ };
619
696
  }
697
+ return this.entries(node.self);
620
698
  }
621
699
  entriesLoop(node, pair) {
622
700
  const parts = pair.parsers.map((q, j) => this.compile(q, j === pair.key || j === pair.value));
@@ -634,10 +712,15 @@ var Compiler = class {
634
712
  return true;
635
713
  };
636
714
  const { max, min } = node;
637
- const checkLoop = max === Infinity;
715
+ const resumable = this.resumable;
716
+ const site = new Key();
638
717
  if (Predicate.isTagged(node, "Repeat")) return (s) => {
639
- const acc = new EntriesAcc();
640
- for (let count = 0; count < max; count++) {
718
+ const at = s.pos;
719
+ const cp = resumable && s.resume !== void 0 ? resumeEntries(s, site, at) : void 0;
720
+ if (cp instanceof Resume.Done) return cp.value;
721
+ const resumed = cp !== void 0;
722
+ const acc = cp?.acc ?? new EntriesAcc();
723
+ for (let count = cp?.count ?? 0; count < max; count++) {
641
724
  const start = s.pos;
642
725
  let key;
643
726
  let value;
@@ -651,50 +734,44 @@ var Compiler = class {
651
734
  if (j === ki) key = a;
652
735
  else if (j === vi) value = a;
653
736
  }
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) {
737
+ if (!ok) return stopEntries(s, site, at, resumed, acc, count, start, min);
738
+ if (s.pos === start) {
660
739
  s.mode = CUT;
661
740
  return Fail;
662
741
  }
663
742
  acc.add(key, value);
664
743
  }
665
- return acc.result();
744
+ return entriesDone(s, site, at, resumed, acc);
666
745
  };
667
746
  const sep = this.compile(node.separator, false);
668
747
  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;
748
+ const at = s.pos;
749
+ const cp = resumable && s.resume !== void 0 ? resumeEntries(s, site, at) : void 0;
750
+ if (cp instanceof Resume.Done) return cp.value;
751
+ const resumed = cp !== void 0;
752
+ const acc = cp?.acc ?? new EntriesAcc();
753
+ let count = cp?.count ?? 0;
754
+ if (!resumed) {
755
+ if (max === 0) return acc.result();
756
+ const start = s.pos;
757
+ if (!entry(s, acc)) {
758
+ if (s.mode !== BT || min > 0) return Fail;
683
759
  s.pos = start;
684
760
  return acc.result();
685
761
  }
686
- if (checkLoop && s.pos === start) {
762
+ count++;
763
+ }
764
+ while (count < max) {
765
+ const start = s.pos;
766
+ if (sep(s) === Fail) return stopEntries(s, site, at, resumed, acc, count, start, min);
767
+ if (s.pos === start) {
687
768
  s.mode = CUT;
688
769
  return Fail;
689
770
  }
690
- if (!entry(s, acc)) {
691
- if (s.mode !== BT || count < min) return Fail;
692
- s.pos = start;
693
- return acc.result();
694
- }
771
+ if (!entry(s, acc)) return stopEntries(s, site, at, resumed, acc, count, start, min);
695
772
  count++;
696
773
  }
697
- return acc.result();
774
+ return entriesDone(s, site, at, resumed, acc);
698
775
  };
699
776
  }
700
777
  repeatTill(node) {
@@ -724,7 +801,6 @@ var Compiler = class {
724
801
  }
725
802
  separated(node, used) {
726
803
  const { max, min } = node;
727
- const checkLoop = max === Infinity;
728
804
  const c = this.compile(node.self, used);
729
805
  const sep = this.compile(node.separator, false);
730
806
  const resumable = this.resumable;
@@ -772,7 +848,7 @@ var Compiler = class {
772
848
  s.pos = start;
773
849
  return resumed ? Resume.done(s, key, entry, true, acc) : acc;
774
850
  }
775
- if (checkLoop && s.pos === start) {
851
+ if (s.pos === start) {
776
852
  s.mode = CUT;
777
853
  return Fail;
778
854
  }
@@ -961,12 +1037,14 @@ var Compiler = class {
961
1037
  };
962
1038
  }
963
1039
  case "TakeWhile": return this.tokenTakeWhile(node, used);
964
- case "TakeUntil": {
965
- const { literal, max, min } = node;
1040
+ case "TakeUntil":
1041
+ case "TakeUntilAny": {
1042
+ const { max, min } = node;
966
1043
  const bounded = min > 0 || max !== Infinity;
1044
+ const search = Predicate.isTagged(node, "TakeUntil") ? (s, from) => indexOf(s, node.literal, from) : (s, from) => indexOfAny(s, node.literals, from);
967
1045
  return (s) => {
968
1046
  const start = s.pos;
969
- const idx = indexOf(s, literal, start);
1047
+ const idx = search(s, start);
970
1048
  if (idx < 0) return failAt(s, s.end);
971
1049
  if (bounded) {
972
1050
  const count = countTokens(s, start, idx);
@@ -987,7 +1065,7 @@ var Compiler = class {
987
1065
  const lit = node.literal;
988
1066
  const literalKind = Predicate.isString(lit) ? 0 : lit instanceof Uint8Array ? 1 : 2;
989
1067
  if (this.kind === 0) {
990
- if (literalKind !== 0) return this.fallback(p, node, "byte or array literal on string input");
1068
+ if (!Predicate.isString(lit)) return this.fallback(p, node, "byte or array literal on string input");
991
1069
  const str = lit;
992
1070
  const len = str.length;
993
1071
  if (node.caseless) {
@@ -1003,8 +1081,8 @@ var Compiler = class {
1003
1081
  }
1004
1082
  return stringLiteral(str, str);
1005
1083
  }
1006
- if (literalKind === 2) return this.fallback(p, node, "array literal on byte input");
1007
- const bytes = literalKind === 0 ? new TextEncoder().encode(lit) : lit;
1084
+ const bytes = Predicate.isString(lit) ? new TextEncoder().encode(lit) : lit instanceof Uint8Array ? lit : void 0;
1085
+ if (bytes === void 0) return this.fallback(p, node, "array literal on byte input");
1008
1086
  const len = bytes.length;
1009
1087
  const sameKind = literalKind === 1 && !node.caseless;
1010
1088
  const expect = node.caseless ? Array.from(bytes, lowerAscii) : Array.from(bytes);
@@ -1036,6 +1114,8 @@ var Compiler = class {
1036
1114
  s.pos = i;
1037
1115
  return used ? bytes.subarray(start, i) : void 0;
1038
1116
  };
1117
+ const stops = negate && min <= 1 && max === Infinity ? stopChars(set) : void 0;
1118
+ if (stops !== void 0) return stopTakeTill(stops, min, used);
1039
1119
  const test = set.test;
1040
1120
  return (s) => {
1041
1121
  const str = s.input;
@@ -1071,7 +1151,7 @@ var Compiler = class {
1071
1151
  const { fast, unitAt, width: unitWidth } = unitReader(this.kind, enc);
1072
1152
  const decode = enc.decode;
1073
1153
  const width = enc.width;
1074
- const toText = enc.text;
1154
+ const toText = enc === utf8 ? utf8Text : (s, start, end) => enc.text(s.input, start, end);
1075
1155
  switch (node._tag) {
1076
1156
  case "Any": return (s) => {
1077
1157
  const pos = s.pos;
@@ -1112,7 +1192,7 @@ var Compiler = class {
1112
1192
  if (fold(cp) !== folded[i]) return failAt(s, pos);
1113
1193
  }
1114
1194
  s.pos = pos;
1115
- return used ? toText(input, start, pos) : void 0;
1195
+ return used ? toText(s, start, pos) : void 0;
1116
1196
  };
1117
1197
  }
1118
1198
  const encoded = enc.encode(lit);
@@ -1177,7 +1257,7 @@ var Compiler = class {
1177
1257
  }
1178
1258
  }
1179
1259
  s.pos = pos;
1180
- return used ? toText(input, start, pos) : void 0;
1260
+ return used ? toText(s, start, pos) : void 0;
1181
1261
  };
1182
1262
  }
1183
1263
  case "TakeWhile": {
@@ -1197,6 +1277,7 @@ var Compiler = class {
1197
1277
  return this.kind === 0 ? takeWhileString(loop, enc) : takeWhileBytes(loop, enc);
1198
1278
  }
1199
1279
  case "TakeUntil":
1280
+ case "TakeUntilAny":
1200
1281
  case "Rest": return this.fallback(p, node, "Text parser without a compiled form");
1201
1282
  }
1202
1283
  }
@@ -1215,7 +1296,7 @@ var Compiler = class {
1215
1296
  };
1216
1297
  }
1217
1298
  const { fast, unitAt, width } = unitReader(this.kind, enc);
1218
- const toText = enc.text;
1299
+ const toText = enc === utf8 ? utf8Text : (s, start, end) => enc.text(s.input, start, end);
1219
1300
  return (s) => {
1220
1301
  const start = s.pos;
1221
1302
  if (c(s) === Fail) return Fail;
@@ -1224,7 +1305,7 @@ var Compiler = class {
1224
1305
  let i = start;
1225
1306
  while (i < end && unitAt(input, i, end) < fast) i += width;
1226
1307
  if (i < end && validate(enc, s, i, end) < 0) return fail(s);
1227
- return used ? toText(input, start, end) : void 0;
1308
+ return used ? toText(s, start, end) : void 0;
1228
1309
  };
1229
1310
  }
1230
1311
  /**
@@ -1295,7 +1376,7 @@ var Compiler = class {
1295
1376
  return Fail;
1296
1377
  };
1297
1378
  if (raw) {
1298
- const slice = enc === void 0 ? (s, start) => s.slice(start, s.pos) : (s, start) => enc.text(s.input, start, s.pos);
1379
+ const slice = enc === void 0 ? (s, start) => s.slice(start, s.pos) : (s, start) => textIn(enc, s, start, s.pos);
1299
1380
  return (s) => {
1300
1381
  const start = s.pos;
1301
1382
  let resumed = false;
@@ -1326,7 +1407,10 @@ var Compiler = class {
1326
1407
  if (escape(s) === Fail) return s.mode === INC ? incomplete(s, start, before) : Fail;
1327
1408
  } else return resumed ? Resume.done(s, key, start, true, slice(s, start)) : slice(s, start);
1328
1409
  }
1329
- if (s.partial) return incomplete(s, start, s.pos);
1410
+ if (s.partial) {
1411
+ s.incomplete(0);
1412
+ return incomplete(s, start, s.pos);
1413
+ }
1330
1414
  return resumed ? Resume.done(s, key, start, true, slice(s, start)) : slice(s, start);
1331
1415
  };
1332
1416
  }
@@ -1371,14 +1455,23 @@ var Compiler = class {
1371
1455
  out += b;
1372
1456
  } else return resumed ? Resume.done(s, key, start, true, out) : out;
1373
1457
  }
1374
- if (s.partial) return incomplete(s, start, {
1375
- out,
1376
- pos: s.pos
1377
- });
1458
+ if (s.partial) {
1459
+ s.incomplete(0);
1460
+ return incomplete(s, start, {
1461
+ out,
1462
+ pos: s.pos
1463
+ });
1464
+ }
1378
1465
  return resumed ? Resume.done(s, key, start, true, out) : out;
1379
1466
  };
1380
1467
  }
1381
1468
  };
1469
+ /** How far past the cursor a token parser may read: its literals' length in UTF-8 at most, or `Margin`. */
1470
+ const marginOf = (node) => {
1471
+ if (Predicate.isTagged(node, "Literal") || Predicate.isTagged(node, "TakeUntil")) return node.literal.length * 4;
1472
+ if (Predicate.isTagged(node, "TakeUntilAny")) return Math.max(0, ...node.literals.map((lit) => lit.length)) * 4;
1473
+ return Margin;
1474
+ };
1382
1475
  const fail = (s) => {
1383
1476
  s.mode = BT;
1384
1477
  return Fail;
@@ -1506,7 +1599,62 @@ const stringLiteral = (str, value) => {
1506
1599
  return fail(s);
1507
1600
  };
1508
1601
  };
1509
- /** A closure compiler for one input kind; it memoizes what it compiles. */
1602
+ /**
1603
+ * `Token.takeTill` on a string, of one to three stop characters that are
1604
+ * whole code points (see `search.ts`): every other unit, surrogates
1605
+ * included, is accepted, so the run ends at the first stop character, or
1606
+ * at the state's end.
1607
+ */
1608
+ const stopTakeTill = (stops, min, used) => {
1609
+ const head = stops.length === 1 ? SearchHead : 2 * SearchHead;
1610
+ const c0 = stops[0];
1611
+ const c1 = stops.length > 1 ? stops[1] : -1;
1612
+ const c2 = stops.length > 2 ? stops[2] : -1;
1613
+ const one = String.fromCharCode(c0);
1614
+ const site = new StopCache(stops.map((u) => String.fromCharCode(u)));
1615
+ return (s) => {
1616
+ const str = s.input;
1617
+ const start = s.pos;
1618
+ const end = s.end;
1619
+ const h = start + head < end ? start + head : end;
1620
+ let i = start;
1621
+ let c = -1;
1622
+ while (i < h && (c = str.charCodeAt(i)) !== c0 && c !== c1 && c !== c2) i++;
1623
+ if (i === h && i < end && (c = str.charCodeAt(i)) !== c0 && c !== c1 && c !== c2) {
1624
+ if (stops.length === 1) {
1625
+ const at = str.indexOf(one, i);
1626
+ i = at < 0 || at > end ? end : at;
1627
+ } else i = nextStop(site, s, i);
1628
+ }
1629
+ if (i - start < min) return failAt(s, i);
1630
+ s.pos = i;
1631
+ return used ? str.slice(start, i) : void 0;
1632
+ };
1633
+ };
1634
+ /** Takes the checkpoint `entriesLoop` saved at `at`, restoring the position of a completed one. */
1635
+ const resumeEntries = (s, key, at) => {
1636
+ const cp = Resume.take(s, key, at);
1637
+ if (cp instanceof Resume.Done) s.pos = cp.pos;
1638
+ else if (cp !== void 0) s.pos = cp.pos;
1639
+ return cp;
1640
+ };
1641
+ /** The object `entriesLoop` built, recorded as done when the loop resumed. */
1642
+ const entriesDone = (s, key, at, resumed, acc) => resumed ? Resume.done(s, key, at, true, acc.result()) : acc.result();
1643
+ /**
1644
+ * Where `entriesLoop` stops at an entry (or separator) that failed at
1645
+ * `start`: a checkpoint when the input ran out, `Fail` unless the failure
1646
+ * backtracks after `min` entries, otherwise the object.
1647
+ */
1648
+ const stopEntries = (s, site, at, resumed, acc, count, start, min) => {
1649
+ if (s.mode === INC && s.resume !== void 0) Resume.save(s, site, at, {
1650
+ acc,
1651
+ count,
1652
+ pos: start
1653
+ });
1654
+ if (s.mode !== BT || count < min) return Fail;
1655
+ s.pos = start;
1656
+ return entriesDone(s, site, at, resumed, acc);
1657
+ };
1510
1658
  /** The object of `Object.fromEntries`, built an entry at a time (see `internal/entries.ts`). */
1511
1659
  var EntriesAcc = class {
1512
1660
  o = {};
@@ -1542,12 +1690,14 @@ const backend = { build: (p, kind, resumable) => Result.match(Result.try(() => c
1542
1690
  onSuccess: ({ fallbacks, step }) => ({
1543
1691
  backend: "closure",
1544
1692
  step,
1693
+ guarded: false,
1545
1694
  fallbacks,
1546
1695
  error: void 0
1547
1696
  }),
1548
1697
  onFailure: (error) => ({
1549
- backend: void 0,
1698
+ backend: "interpreted",
1550
1699
  step: void 0,
1700
+ guarded: false,
1551
1701
  fallbacks: [],
1552
1702
  error
1553
1703
  })