@thomasfosterau/effect-parse 0.4.0 → 0.5.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 (148) hide show
  1. package/README.md +40 -14
  2. package/dist/Ascii.d.ts +11 -4
  3. package/dist/Ascii.d.ts.map +1 -1
  4. package/dist/Ascii.js +7 -1
  5. package/dist/Ascii.js.map +1 -1
  6. package/dist/Binary.d.ts.map +1 -1
  7. package/dist/Binary.js +64 -35
  8. package/dist/Binary.js.map +1 -1
  9. package/dist/Bits.d.ts.map +1 -1
  10. package/dist/Bits.js +7 -4
  11. package/dist/Bits.js.map +1 -1
  12. package/dist/Compiler.d.ts +74 -2
  13. package/dist/Compiler.d.ts.map +1 -1
  14. package/dist/Compiler.js +78 -1
  15. package/dist/Compiler.js.map +1 -1
  16. package/dist/Expression.d.ts.map +1 -1
  17. package/dist/Expression.js +86 -74
  18. package/dist/Expression.js.map +1 -1
  19. package/dist/Input.d.ts +37 -4
  20. package/dist/Input.d.ts.map +1 -1
  21. package/dist/Input.js +42 -0
  22. package/dist/Input.js.map +1 -1
  23. package/dist/Nom.d.ts +5 -15
  24. package/dist/Nom.d.ts.map +1 -1
  25. package/dist/Nom.js.map +1 -1
  26. package/dist/ParseError.d.ts +2 -2
  27. package/dist/ParseError.d.ts.map +1 -1
  28. package/dist/ParseError.js +1 -1
  29. package/dist/ParseError.js.map +1 -1
  30. package/dist/Parser.d.ts +370 -28
  31. package/dist/Parser.d.ts.map +1 -1
  32. package/dist/Parser.js +390 -19
  33. package/dist/Parser.js.map +1 -1
  34. package/dist/ParserSchema.js +2 -2
  35. package/dist/ParserSchema.js.map +1 -1
  36. package/dist/ParserStream.d.ts +3 -2
  37. package/dist/ParserStream.d.ts.map +1 -1
  38. package/dist/ParserStream.js +15 -10
  39. package/dist/ParserStream.js.map +1 -1
  40. package/dist/Syntax.d.ts +23 -5
  41. package/dist/Syntax.d.ts.map +1 -1
  42. package/dist/Syntax.js.map +1 -1
  43. package/dist/Text.d.ts.map +1 -1
  44. package/dist/Text.js +9 -9
  45. package/dist/Text.js.map +1 -1
  46. package/dist/Token.d.ts +55 -10
  47. package/dist/Token.d.ts.map +1 -1
  48. package/dist/Token.js +59 -21
  49. package/dist/Token.js.map +1 -1
  50. package/dist/internal/compiler/closure.d.ts.map +1 -1
  51. package/dist/internal/compiler/closure.js +257 -97
  52. package/dist/internal/compiler/closure.js.map +1 -1
  53. package/dist/internal/compiler/entries.d.ts +3 -1
  54. package/dist/internal/compiler/entries.d.ts.map +1 -1
  55. package/dist/internal/compiler/entries.js +3 -2
  56. package/dist/internal/compiler/entries.js.map +1 -1
  57. package/dist/internal/compiler/first.d.ts.map +1 -1
  58. package/dist/internal/compiler/first.js +7 -1
  59. package/dist/internal/compiler/first.js.map +1 -1
  60. package/dist/internal/compiler/graph.d.ts +17 -0
  61. package/dist/internal/compiler/graph.d.ts.map +1 -0
  62. package/dist/internal/compiler/graph.js +56 -0
  63. package/dist/internal/compiler/graph.js.map +1 -0
  64. package/dist/internal/compiler/jit.d.ts +5 -0
  65. package/dist/internal/compiler/jit.d.ts.map +1 -1
  66. package/dist/internal/compiler/jit.js +185 -96
  67. package/dist/internal/compiler/jit.js.map +1 -1
  68. package/dist/internal/compiler/registry.d.ts +10 -2
  69. package/dist/internal/compiler/registry.d.ts.map +1 -1
  70. package/dist/internal/compiler/registry.js.map +1 -1
  71. package/dist/internal/compiler/search.d.ts +32 -0
  72. package/dist/internal/compiler/search.d.ts.map +1 -0
  73. package/dist/internal/compiler/search.js +68 -0
  74. package/dist/internal/compiler/search.js.map +1 -0
  75. package/dist/internal/compiler/sets.d.ts.map +1 -1
  76. package/dist/internal/compiler/sets.js +1 -1
  77. package/dist/internal/compiler/sets.js.map +1 -1
  78. package/dist/internal/compiler/wasm.d.ts +8 -0
  79. package/dist/internal/compiler/wasm.d.ts.map +1 -0
  80. package/dist/internal/compiler/wasm.js +2769 -0
  81. package/dist/internal/compiler/wasm.js.map +1 -0
  82. package/dist/internal/compiler/wasmAsm.d.ts +199 -0
  83. package/dist/internal/compiler/wasmAsm.d.ts.map +1 -0
  84. package/dist/internal/compiler/wasmAsm.js +427 -0
  85. package/dist/internal/compiler/wasmAsm.js.map +1 -0
  86. package/dist/internal/entries.d.ts +3 -1
  87. package/dist/internal/entries.d.ts.map +1 -1
  88. package/dist/internal/entries.js +1 -2
  89. package/dist/internal/entries.js.map +1 -1
  90. package/dist/internal/node.d.ts +58 -2
  91. package/dist/internal/node.d.ts.map +1 -1
  92. package/dist/internal/node.js +13 -3
  93. package/dist/internal/node.js.map +1 -1
  94. package/dist/internal/numbers.d.ts.map +1 -1
  95. package/dist/internal/numbers.js.map +1 -1
  96. package/dist/internal/run.d.ts +12 -0
  97. package/dist/internal/run.d.ts.map +1 -1
  98. package/dist/internal/run.js +51 -11
  99. package/dist/internal/run.js.map +1 -1
  100. package/dist/internal/stack.d.ts +6 -0
  101. package/dist/internal/stack.d.ts.map +1 -1
  102. package/dist/internal/stack.js +8 -2
  103. package/dist/internal/stack.js.map +1 -1
  104. package/dist/internal/syntax.d.ts +4 -4
  105. package/dist/internal/syntax.d.ts.map +1 -1
  106. package/dist/internal/syntax.js +18 -10
  107. package/dist/internal/syntax.js.map +1 -1
  108. package/dist/internal/text.d.ts +32 -0
  109. package/dist/internal/text.d.ts.map +1 -1
  110. package/dist/internal/text.js +68 -14
  111. package/dist/internal/text.js.map +1 -1
  112. package/dist/internal/tokens.d.ts +13 -0
  113. package/dist/internal/tokens.d.ts.map +1 -1
  114. package/dist/internal/tokens.js +59 -39
  115. package/dist/internal/tokens.js.map +1 -1
  116. package/package.json +5 -4
  117. package/src/Ascii.ts +42 -9
  118. package/src/Binary.ts +151 -71
  119. package/src/Bits.ts +12 -6
  120. package/src/Compiler.ts +101 -10
  121. package/src/Expression.ts +94 -81
  122. package/src/Input.ts +65 -6
  123. package/src/Nom.ts +15 -5
  124. package/src/ParseError.ts +9 -4
  125. package/src/Parser.ts +682 -129
  126. package/src/ParserSchema.ts +1 -1
  127. package/src/ParserStream.ts +40 -19
  128. package/src/Syntax.ts +60 -36
  129. package/src/Text.ts +16 -15
  130. package/src/Token.ts +138 -29
  131. package/src/internal/compiler/closure.ts +362 -135
  132. package/src/internal/compiler/entries.ts +4 -2
  133. package/src/internal/compiler/first.ts +10 -0
  134. package/src/internal/compiler/graph.ts +68 -0
  135. package/src/internal/compiler/jit.ts +284 -154
  136. package/src/internal/compiler/registry.ts +10 -2
  137. package/src/internal/compiler/search.ts +68 -0
  138. package/src/internal/compiler/sets.ts +7 -3
  139. package/src/internal/compiler/wasm.ts +3203 -0
  140. package/src/internal/compiler/wasmAsm.ts +484 -0
  141. package/src/internal/entries.ts +10 -4
  142. package/src/internal/node.ts +54 -4
  143. package/src/internal/numbers.ts +3 -1
  144. package/src/internal/run.ts +71 -12
  145. package/src/internal/stack.ts +8 -1
  146. package/src/internal/syntax.ts +39 -18
  147. package/src/internal/text.ts +97 -9
  148. package/src/internal/tokens.ts +96 -14
@@ -4,13 +4,14 @@ import { Fail } from "../../Input.js";
4
4
  import { floatScan, floatTexts, scanFloatBytes, scanFloatString, toFloat } from "../numbers.js";
5
5
  import { Key } from "../key.js";
6
6
  import * as Resume from "../resume.js";
7
- import { countTokens, indexOf } from "../tokens.js";
7
+ import { countTokens, indexOf, indexOfAny } from "../tokens.js";
8
8
  import * as Option from "effect/Option";
9
- import { charOf, fastLimit, firstCodePoint, fold, utf16be, utf16le, validate } from "../text.js";
9
+ import { charOf, fastLimit, firstCodePoint, fold, textIn, utf16be, utf16le, utf8, utf8Text, validate } from "../text.js";
10
10
  import { addEntry, flushEntries, fromEntries, isPlainKey } from "../entries.js";
11
- import { nodeOf, scansFloat } from "../node.js";
11
+ import { Defer, nodeOf, scansFloat } from "../node.js";
12
12
  import { buildsEntries, pairOf } from "./entries.js";
13
13
  import { FirstSets, planAlt } from "./first.js";
14
+ import { SearchHead, StopCache, nextStop, stopChars } from "./search.js";
14
15
  import { TableSize, acceptTable, kindOfEncoding, textSet, tokenSet } from "./sets.js";
15
16
  // src/internal/compiler/closure.ts
16
17
  /**
@@ -110,6 +111,8 @@ var Compiler = class {
110
111
  build(p, node, used) {
111
112
  switch (node._tag) {
112
113
  case "Opaque": return this.fallback(p, node, "not describable (Parser.make, gen, ...)");
114
+ case "Fixed": return p.step;
115
+ case "Combinator": return node.build(node.parsers.map((q) => this.compile(q, true)));
113
116
  case "Succeed": {
114
117
  const value = node.value;
115
118
  return () => value;
@@ -130,10 +133,7 @@ var Compiler = class {
130
133
  s.mode = BT;
131
134
  return Fail;
132
135
  }
133
- if (s.partial) {
134
- s.mode = INC;
135
- return Fail;
136
- }
136
+ if (s.partial) return s.incomplete(1);
137
137
  };
138
138
  case "Location": return (s) => s.pos;
139
139
  case "RestLen": return (s) => s.end - s.pos;
@@ -144,9 +144,10 @@ var Compiler = class {
144
144
  case "Take":
145
145
  case "TakeWhile":
146
146
  case "TakeUntil":
147
+ case "TakeUntilAny":
147
148
  case "Rest":
148
149
  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);
150
+ return this.partialSafe(p, node.encoding === void 0 ? this.token(p, node, used) : this.text(p, node, node.encoding, used), marginOf(node));
150
151
  case "TillLineEnding":
151
152
  case "Identifier":
152
153
  case "Bom": return this.fallback(p, node, "leaf parser without a compiled form");
@@ -159,7 +160,7 @@ var Compiler = class {
159
160
  const step = this.float(node);
160
161
  if (step !== void 0) return step;
161
162
  }
162
- if (node.f === fromEntries && !this.resumable && buildsEntries(node.self)) return this.entries(node.self);
163
+ if (node.f === fromEntries && buildsEntries(node.self)) return this.entries(node.self);
163
164
  const c = this.compile(node.self, true);
164
165
  const f = node.f;
165
166
  return (s) => {
@@ -206,6 +207,28 @@ var Compiler = class {
206
207
  return Fail;
207
208
  };
208
209
  }
210
+ case "FastPath": {
211
+ const c = this.compile(node.self, used);
212
+ const fast = node.fast;
213
+ return (s) => {
214
+ const start = s.pos;
215
+ const a = fast(s);
216
+ if (a !== Defer) return a;
217
+ s.pos = start;
218
+ return c(s);
219
+ };
220
+ }
221
+ case "MapOrFail": {
222
+ const c = this.compile(node.self, true);
223
+ const f = node.f;
224
+ return (s) => {
225
+ const a = c(s);
226
+ if (a === Fail) return Fail;
227
+ const b = f(a);
228
+ if (b === Fail) s.mode = BT;
229
+ return b;
230
+ };
231
+ }
209
232
  case "Filter": {
210
233
  const c = this.compile(node.self, true);
211
234
  const predicate = node.predicate;
@@ -237,6 +260,16 @@ var Compiler = class {
237
260
  return a === Fail ? Fail : [a, s.slice(start, s.pos)];
238
261
  };
239
262
  }
263
+ case "MapSpan": {
264
+ const c = this.compile(node.self, used);
265
+ if (!used) return c;
266
+ const f = node.f;
267
+ return (s) => {
268
+ const start = s.pos;
269
+ const a = c(s);
270
+ return a === Fail ? Fail : f(a, start, s.pos);
271
+ };
272
+ }
240
273
  case "Span": {
241
274
  const c = this.compile(node.self, false);
242
275
  if (!used) return c;
@@ -271,6 +304,7 @@ var Compiler = class {
271
304
  }
272
305
  case "Context":
273
306
  case "Expected":
307
+ case "Quiet":
274
308
  case "MapError":
275
309
  case "OrFail":
276
310
  case "Trace":
@@ -336,6 +370,11 @@ var Compiler = class {
336
370
  return out;
337
371
  };
338
372
  }
373
+ case "SeqWith": {
374
+ const steps = node.parsers.map((q) => this.compile(q, used));
375
+ if (!used) return this.chain(steps);
376
+ return this.seqWith(steps, node.f);
377
+ }
339
378
  case "ZipWith": {
340
379
  const c1 = this.compile(node.self, used);
341
380
  const c2 = this.compile(node.that, used);
@@ -351,7 +390,22 @@ var Compiler = class {
351
390
  case "Alt": return this.alt(node, used);
352
391
  case "Dispatch": return this.dispatch(p, node, used);
353
392
  case "Repeat":
354
- case "Fold": return this.repeat(node, used);
393
+ case "Fold": {
394
+ const element = Predicate.isTagged(node, "Repeat") && !used ? nodeOf(node.self) : void 0;
395
+ if (element !== void 0 && Predicate.isTagged(element, "OneOf") && this.kind !== 2 && this.native(element.encoding)) {
396
+ const { encoding, negate, set } = element;
397
+ const run = {
398
+ _tag: "TakeWhile",
399
+ set,
400
+ negate,
401
+ encoding,
402
+ min: node.min,
403
+ max: node.max
404
+ };
405
+ return this.partialSafe(p, encoding === void 0 ? this.token(p, run, false) : this.text(p, run, encoding, false), Margin);
406
+ }
407
+ return this.repeat(node, used);
408
+ }
355
409
  case "RepeatTill": return this.repeatTill(node);
356
410
  case "Separated": return this.separated(node, used);
357
411
  case "SeparatedFold": return this.separatedFold(node);
@@ -359,13 +413,47 @@ var Compiler = class {
359
413
  case "Provide": return this.fallback(p, node, "services stay interpreted");
360
414
  }
361
415
  }
416
+ /** `seqWith`: up to three parsers without an array of values. */
417
+ seqWith(steps, f) {
418
+ const n = steps.length;
419
+ if (n === 0) return () => f();
420
+ const [c1, c2, c3] = steps;
421
+ if (n === 1) return (s) => {
422
+ const a = c1(s);
423
+ return a === Fail ? Fail : f(a);
424
+ };
425
+ if (n === 2) return (s) => {
426
+ const a = c1(s);
427
+ if (a === Fail) return Fail;
428
+ const b = c2(s);
429
+ return b === Fail ? Fail : f(a, b);
430
+ };
431
+ if (n === 3) return (s) => {
432
+ const a = c1(s);
433
+ if (a === Fail) return Fail;
434
+ const b = c2(s);
435
+ if (b === Fail) return Fail;
436
+ const c = c3(s);
437
+ return c === Fail ? Fail : f(a, b, c);
438
+ };
439
+ return (s) => {
440
+ const values = new Array(n);
441
+ for (let i = 0; i < n; i++) {
442
+ const a = steps[i](s);
443
+ if (a === Fail) return Fail;
444
+ values[i] = a;
445
+ }
446
+ return f(...values);
447
+ };
448
+ }
362
449
  /** Runs steps in order, for their effect on the cursor only. */
363
450
  chain(steps) {
364
451
  const n = steps.length;
365
452
  if (n === 0) return () => void 0;
366
453
  if (n === 1) return steps[0];
367
454
  if (n === 2) {
368
- const [a, b] = steps;
455
+ const a = steps[0];
456
+ const b = steps[1];
369
457
  return (s) => a(s) === Fail ? Fail : b(s);
370
458
  }
371
459
  return (s) => {
@@ -389,7 +477,8 @@ var Compiler = class {
389
477
  };
390
478
  if (Predicate.isNumber(output)) {
391
479
  if (n === 2) {
392
- const [a, b] = steps;
480
+ const a = steps[0];
481
+ const b = steps[1];
393
482
  return output === 0 ? (s) => {
394
483
  const x = a(s);
395
484
  if (x === Fail) return Fail;
@@ -486,9 +575,9 @@ var Compiler = class {
486
575
  this.note(p, node, "the parser returned by the function of cases runs interpreted");
487
576
  return general;
488
577
  }
489
- let sel = nodeOf(node.selector);
490
- const peek = Predicate.isTagged(sel, "Peek");
491
- if (peek) sel = nodeOf(sel.self);
578
+ const top = nodeOf(node.selector);
579
+ const peek = Predicate.isTagged(top, "Peek");
580
+ const sel = peek ? nodeOf(top.self) : top;
492
581
  if (!Predicate.isTagged(sel, "Any") || !this.native(sel.encoding)) return general;
493
582
  const enc = sel.encoding;
494
583
  const limit = enc === void 0 ? this.kind === 0 ? 55296 : TableSize : Math.min(fastLimit(enc), 55296);
@@ -581,42 +670,39 @@ var Compiler = class {
581
670
  */
582
671
  entries(p) {
583
672
  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);
673
+ if (Predicate.isTagged(node, "Mode")) {
674
+ const c = this.entries(node.self);
675
+ const from = node.from;
676
+ const to = node.to;
677
+ return (s) => {
678
+ const a = c(s);
679
+ if (a === Fail && s.mode === from) s.mode = to;
680
+ return a;
681
+ };
682
+ }
683
+ if (Predicate.isTagged(node, "Seq")) {
684
+ const i = node.output;
685
+ const steps = node.parsers.map((q, j) => j === i ? this.entries(q) : this.compile(q, false));
686
+ return (s) => {
687
+ let out;
688
+ for (let j = 0; j < steps.length; j++) {
689
+ const a = steps[j](s);
690
+ if (a === Fail) return Fail;
691
+ if (j === i) out = a;
692
+ }
693
+ return out;
694
+ };
695
+ }
696
+ if (Predicate.isTagged(node, "Repeat") || Predicate.isTagged(node, "Separated")) {
697
+ const pair = pairOf(node.self);
698
+ if (pair !== void 0) return this.entriesLoop(node, pair);
699
+ const c = this.compile(p, true);
700
+ return (s) => {
701
+ const a = c(s);
702
+ return a === Fail ? Fail : fromEntries(a);
703
+ };
619
704
  }
705
+ return this.entries(node.self);
620
706
  }
621
707
  entriesLoop(node, pair) {
622
708
  const parts = pair.parsers.map((q, j) => this.compile(q, j === pair.key || j === pair.value));
@@ -635,9 +721,15 @@ var Compiler = class {
635
721
  };
636
722
  const { max, min } = node;
637
723
  const checkLoop = max === Infinity;
724
+ const resumable = this.resumable;
725
+ const site = new Key();
638
726
  if (Predicate.isTagged(node, "Repeat")) return (s) => {
639
- const acc = new EntriesAcc();
640
- for (let count = 0; count < max; count++) {
727
+ const at = s.pos;
728
+ const cp = resumable && s.resume !== void 0 ? resumeEntries(s, site, at) : void 0;
729
+ if (cp instanceof Resume.Done) return cp.value;
730
+ const resumed = cp !== void 0;
731
+ const acc = cp?.acc ?? new EntriesAcc();
732
+ for (let count = cp?.count ?? 0; count < max; count++) {
641
733
  const start = s.pos;
642
734
  let key;
643
735
  let value;
@@ -651,50 +743,44 @@ var Compiler = class {
651
743
  if (j === ki) key = a;
652
744
  else if (j === vi) value = a;
653
745
  }
654
- if (!ok) {
655
- if (s.mode !== BT || count < min) return Fail;
656
- s.pos = start;
657
- return acc.result();
658
- }
746
+ if (!ok) return stopEntries(s, site, at, resumed, acc, count, start, min);
659
747
  if (checkLoop && s.pos === start) {
660
748
  s.mode = CUT;
661
749
  return Fail;
662
750
  }
663
751
  acc.add(key, value);
664
752
  }
665
- return acc.result();
753
+ return entriesDone(s, site, at, resumed, acc);
666
754
  };
667
755
  const sep = this.compile(node.separator, false);
668
756
  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;
757
+ const at = s.pos;
758
+ const cp = resumable && s.resume !== void 0 ? resumeEntries(s, site, at) : void 0;
759
+ if (cp instanceof Resume.Done) return cp.value;
760
+ const resumed = cp !== void 0;
761
+ const acc = cp?.acc ?? new EntriesAcc();
762
+ let count = cp?.count ?? 0;
763
+ if (!resumed) {
764
+ if (max === 0) return acc.result();
765
+ const start = s.pos;
766
+ if (!entry(s, acc)) {
767
+ if (s.mode !== BT || min > 0) return Fail;
683
768
  s.pos = start;
684
769
  return acc.result();
685
770
  }
771
+ count++;
772
+ }
773
+ while (count < max) {
774
+ const start = s.pos;
775
+ if (sep(s) === Fail) return stopEntries(s, site, at, resumed, acc, count, start, min);
686
776
  if (checkLoop && s.pos === start) {
687
777
  s.mode = CUT;
688
778
  return Fail;
689
779
  }
690
- if (!entry(s, acc)) {
691
- if (s.mode !== BT || count < min) return Fail;
692
- s.pos = start;
693
- return acc.result();
694
- }
780
+ if (!entry(s, acc)) return stopEntries(s, site, at, resumed, acc, count, start, min);
695
781
  count++;
696
782
  }
697
- return acc.result();
783
+ return entriesDone(s, site, at, resumed, acc);
698
784
  };
699
785
  }
700
786
  repeatTill(node) {
@@ -961,12 +1047,14 @@ var Compiler = class {
961
1047
  };
962
1048
  }
963
1049
  case "TakeWhile": return this.tokenTakeWhile(node, used);
964
- case "TakeUntil": {
965
- const { literal, max, min } = node;
1050
+ case "TakeUntil":
1051
+ case "TakeUntilAny": {
1052
+ const { max, min } = node;
966
1053
  const bounded = min > 0 || max !== Infinity;
1054
+ const search = Predicate.isTagged(node, "TakeUntil") ? (s, from) => indexOf(s, node.literal, from) : (s, from) => indexOfAny(s, node.literals, from);
967
1055
  return (s) => {
968
1056
  const start = s.pos;
969
- const idx = indexOf(s, literal, start);
1057
+ const idx = search(s, start);
970
1058
  if (idx < 0) return failAt(s, s.end);
971
1059
  if (bounded) {
972
1060
  const count = countTokens(s, start, idx);
@@ -987,7 +1075,7 @@ var Compiler = class {
987
1075
  const lit = node.literal;
988
1076
  const literalKind = Predicate.isString(lit) ? 0 : lit instanceof Uint8Array ? 1 : 2;
989
1077
  if (this.kind === 0) {
990
- if (literalKind !== 0) return this.fallback(p, node, "byte or array literal on string input");
1078
+ if (!Predicate.isString(lit)) return this.fallback(p, node, "byte or array literal on string input");
991
1079
  const str = lit;
992
1080
  const len = str.length;
993
1081
  if (node.caseless) {
@@ -1003,8 +1091,8 @@ var Compiler = class {
1003
1091
  }
1004
1092
  return stringLiteral(str, str);
1005
1093
  }
1006
- if (literalKind === 2) return this.fallback(p, node, "array literal on byte input");
1007
- const bytes = literalKind === 0 ? new TextEncoder().encode(lit) : lit;
1094
+ const bytes = Predicate.isString(lit) ? new TextEncoder().encode(lit) : lit instanceof Uint8Array ? lit : void 0;
1095
+ if (bytes === void 0) return this.fallback(p, node, "array literal on byte input");
1008
1096
  const len = bytes.length;
1009
1097
  const sameKind = literalKind === 1 && !node.caseless;
1010
1098
  const expect = node.caseless ? Array.from(bytes, lowerAscii) : Array.from(bytes);
@@ -1036,6 +1124,8 @@ var Compiler = class {
1036
1124
  s.pos = i;
1037
1125
  return used ? bytes.subarray(start, i) : void 0;
1038
1126
  };
1127
+ const stops = negate && min <= 1 && max === Infinity ? stopChars(set) : void 0;
1128
+ if (stops !== void 0) return stopTakeTill(stops, min, used);
1039
1129
  const test = set.test;
1040
1130
  return (s) => {
1041
1131
  const str = s.input;
@@ -1071,7 +1161,7 @@ var Compiler = class {
1071
1161
  const { fast, unitAt, width: unitWidth } = unitReader(this.kind, enc);
1072
1162
  const decode = enc.decode;
1073
1163
  const width = enc.width;
1074
- const toText = enc.text;
1164
+ const toText = enc === utf8 ? utf8Text : (s, start, end) => enc.text(s.input, start, end);
1075
1165
  switch (node._tag) {
1076
1166
  case "Any": return (s) => {
1077
1167
  const pos = s.pos;
@@ -1112,7 +1202,7 @@ var Compiler = class {
1112
1202
  if (fold(cp) !== folded[i]) return failAt(s, pos);
1113
1203
  }
1114
1204
  s.pos = pos;
1115
- return used ? toText(input, start, pos) : void 0;
1205
+ return used ? toText(s, start, pos) : void 0;
1116
1206
  };
1117
1207
  }
1118
1208
  const encoded = enc.encode(lit);
@@ -1177,7 +1267,7 @@ var Compiler = class {
1177
1267
  }
1178
1268
  }
1179
1269
  s.pos = pos;
1180
- return used ? toText(input, start, pos) : void 0;
1270
+ return used ? toText(s, start, pos) : void 0;
1181
1271
  };
1182
1272
  }
1183
1273
  case "TakeWhile": {
@@ -1197,6 +1287,7 @@ var Compiler = class {
1197
1287
  return this.kind === 0 ? takeWhileString(loop, enc) : takeWhileBytes(loop, enc);
1198
1288
  }
1199
1289
  case "TakeUntil":
1290
+ case "TakeUntilAny":
1200
1291
  case "Rest": return this.fallback(p, node, "Text parser without a compiled form");
1201
1292
  }
1202
1293
  }
@@ -1215,7 +1306,7 @@ var Compiler = class {
1215
1306
  };
1216
1307
  }
1217
1308
  const { fast, unitAt, width } = unitReader(this.kind, enc);
1218
- const toText = enc.text;
1309
+ const toText = enc === utf8 ? utf8Text : (s, start, end) => enc.text(s.input, start, end);
1219
1310
  return (s) => {
1220
1311
  const start = s.pos;
1221
1312
  if (c(s) === Fail) return Fail;
@@ -1224,7 +1315,7 @@ var Compiler = class {
1224
1315
  let i = start;
1225
1316
  while (i < end && unitAt(input, i, end) < fast) i += width;
1226
1317
  if (i < end && validate(enc, s, i, end) < 0) return fail(s);
1227
- return used ? toText(input, start, end) : void 0;
1318
+ return used ? toText(s, start, end) : void 0;
1228
1319
  };
1229
1320
  }
1230
1321
  /**
@@ -1295,7 +1386,7 @@ var Compiler = class {
1295
1386
  return Fail;
1296
1387
  };
1297
1388
  if (raw) {
1298
- const slice = enc === void 0 ? (s, start) => s.slice(start, s.pos) : (s, start) => enc.text(s.input, start, s.pos);
1389
+ const slice = enc === void 0 ? (s, start) => s.slice(start, s.pos) : (s, start) => textIn(enc, s, start, s.pos);
1299
1390
  return (s) => {
1300
1391
  const start = s.pos;
1301
1392
  let resumed = false;
@@ -1326,7 +1417,10 @@ var Compiler = class {
1326
1417
  if (escape(s) === Fail) return s.mode === INC ? incomplete(s, start, before) : Fail;
1327
1418
  } else return resumed ? Resume.done(s, key, start, true, slice(s, start)) : slice(s, start);
1328
1419
  }
1329
- if (s.partial) return incomplete(s, start, s.pos);
1420
+ if (s.partial) {
1421
+ s.incomplete(0);
1422
+ return incomplete(s, start, s.pos);
1423
+ }
1330
1424
  return resumed ? Resume.done(s, key, start, true, slice(s, start)) : slice(s, start);
1331
1425
  };
1332
1426
  }
@@ -1371,14 +1465,23 @@ var Compiler = class {
1371
1465
  out += b;
1372
1466
  } else return resumed ? Resume.done(s, key, start, true, out) : out;
1373
1467
  }
1374
- if (s.partial) return incomplete(s, start, {
1375
- out,
1376
- pos: s.pos
1377
- });
1468
+ if (s.partial) {
1469
+ s.incomplete(0);
1470
+ return incomplete(s, start, {
1471
+ out,
1472
+ pos: s.pos
1473
+ });
1474
+ }
1378
1475
  return resumed ? Resume.done(s, key, start, true, out) : out;
1379
1476
  };
1380
1477
  }
1381
1478
  };
1479
+ /** How far past the cursor a token parser may read: its literals' length in UTF-8 at most, or `Margin`. */
1480
+ const marginOf = (node) => {
1481
+ if (Predicate.isTagged(node, "Literal") || Predicate.isTagged(node, "TakeUntil")) return node.literal.length * 4;
1482
+ if (Predicate.isTagged(node, "TakeUntilAny")) return Math.max(0, ...node.literals.map((lit) => lit.length)) * 4;
1483
+ return Margin;
1484
+ };
1382
1485
  const fail = (s) => {
1383
1486
  s.mode = BT;
1384
1487
  return Fail;
@@ -1506,7 +1609,62 @@ const stringLiteral = (str, value) => {
1506
1609
  return fail(s);
1507
1610
  };
1508
1611
  };
1509
- /** A closure compiler for one input kind; it memoizes what it compiles. */
1612
+ /**
1613
+ * `Token.takeTill` on a string, of one to three stop characters that are
1614
+ * whole code points (see `search.ts`): every other unit, surrogates
1615
+ * included, is accepted, so the run ends at the first stop character, or
1616
+ * at the state's end.
1617
+ */
1618
+ const stopTakeTill = (stops, min, used) => {
1619
+ const head = stops.length === 1 ? SearchHead : 2 * SearchHead;
1620
+ const c0 = stops[0];
1621
+ const c1 = stops.length > 1 ? stops[1] : -1;
1622
+ const c2 = stops.length > 2 ? stops[2] : -1;
1623
+ const one = String.fromCharCode(c0);
1624
+ const site = new StopCache(stops.map((u) => String.fromCharCode(u)));
1625
+ return (s) => {
1626
+ const str = s.input;
1627
+ const start = s.pos;
1628
+ const end = s.end;
1629
+ const h = start + head < end ? start + head : end;
1630
+ let i = start;
1631
+ let c = -1;
1632
+ while (i < h && (c = str.charCodeAt(i)) !== c0 && c !== c1 && c !== c2) i++;
1633
+ if (i === h && i < end && (c = str.charCodeAt(i)) !== c0 && c !== c1 && c !== c2) {
1634
+ if (stops.length === 1) {
1635
+ const at = str.indexOf(one, i);
1636
+ i = at < 0 || at > end ? end : at;
1637
+ } else i = nextStop(site, s, i);
1638
+ }
1639
+ if (i - start < min) return failAt(s, i);
1640
+ s.pos = i;
1641
+ return used ? str.slice(start, i) : void 0;
1642
+ };
1643
+ };
1644
+ /** Takes the checkpoint `entriesLoop` saved at `at`, restoring the position of a completed one. */
1645
+ const resumeEntries = (s, key, at) => {
1646
+ const cp = Resume.take(s, key, at);
1647
+ if (cp instanceof Resume.Done) s.pos = cp.pos;
1648
+ else if (cp !== void 0) s.pos = cp.pos;
1649
+ return cp;
1650
+ };
1651
+ /** The object `entriesLoop` built, recorded as done when the loop resumed. */
1652
+ const entriesDone = (s, key, at, resumed, acc) => resumed ? Resume.done(s, key, at, true, acc.result()) : acc.result();
1653
+ /**
1654
+ * Where `entriesLoop` stops at an entry (or separator) that failed at
1655
+ * `start`: a checkpoint when the input ran out, `Fail` unless the failure
1656
+ * backtracks after `min` entries, otherwise the object.
1657
+ */
1658
+ const stopEntries = (s, site, at, resumed, acc, count, start, min) => {
1659
+ if (s.mode === INC && s.resume !== void 0) Resume.save(s, site, at, {
1660
+ acc,
1661
+ count,
1662
+ pos: start
1663
+ });
1664
+ if (s.mode !== BT || count < min) return Fail;
1665
+ s.pos = start;
1666
+ return entriesDone(s, site, at, resumed, acc);
1667
+ };
1510
1668
  /** The object of `Object.fromEntries`, built an entry at a time (see `internal/entries.ts`). */
1511
1669
  var EntriesAcc = class {
1512
1670
  o = {};
@@ -1542,12 +1700,14 @@ const backend = { build: (p, kind, resumable) => Result.match(Result.try(() => c
1542
1700
  onSuccess: ({ fallbacks, step }) => ({
1543
1701
  backend: "closure",
1544
1702
  step,
1703
+ guarded: false,
1545
1704
  fallbacks,
1546
1705
  error: void 0
1547
1706
  }),
1548
1707
  onFailure: (error) => ({
1549
- backend: void 0,
1708
+ backend: "interpreted",
1550
1709
  step: void 0,
1710
+ guarded: false,
1551
1711
  fallbacks: [],
1552
1712
  error
1553
1713
  })