@thomasfosterau/effect-parse 0.4.1 → 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 (143) hide show
  1. package/README.md +37 -13
  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.map +1 -1
  27. package/dist/ParseError.js.map +1 -1
  28. package/dist/Parser.d.ts +366 -26
  29. package/dist/Parser.d.ts.map +1 -1
  30. package/dist/Parser.js +390 -19
  31. package/dist/Parser.js.map +1 -1
  32. package/dist/ParserSchema.js +1 -1
  33. package/dist/ParserStream.d.ts +3 -2
  34. package/dist/ParserStream.d.ts.map +1 -1
  35. package/dist/ParserStream.js +13 -9
  36. package/dist/ParserStream.js.map +1 -1
  37. package/dist/Syntax.d.ts +23 -5
  38. package/dist/Syntax.d.ts.map +1 -1
  39. package/dist/Syntax.js.map +1 -1
  40. package/dist/Text.d.ts.map +1 -1
  41. package/dist/Text.js +9 -9
  42. package/dist/Text.js.map +1 -1
  43. package/dist/Token.d.ts +55 -10
  44. package/dist/Token.d.ts.map +1 -1
  45. package/dist/Token.js +59 -21
  46. package/dist/Token.js.map +1 -1
  47. package/dist/internal/compiler/closure.d.ts.map +1 -1
  48. package/dist/internal/compiler/closure.js +257 -97
  49. package/dist/internal/compiler/closure.js.map +1 -1
  50. package/dist/internal/compiler/entries.d.ts +3 -1
  51. package/dist/internal/compiler/entries.d.ts.map +1 -1
  52. package/dist/internal/compiler/entries.js +3 -2
  53. package/dist/internal/compiler/entries.js.map +1 -1
  54. package/dist/internal/compiler/first.d.ts.map +1 -1
  55. package/dist/internal/compiler/first.js +7 -1
  56. package/dist/internal/compiler/first.js.map +1 -1
  57. package/dist/internal/compiler/graph.d.ts +17 -0
  58. package/dist/internal/compiler/graph.d.ts.map +1 -0
  59. package/dist/internal/compiler/graph.js +56 -0
  60. package/dist/internal/compiler/graph.js.map +1 -0
  61. package/dist/internal/compiler/jit.d.ts +5 -0
  62. package/dist/internal/compiler/jit.d.ts.map +1 -1
  63. package/dist/internal/compiler/jit.js +185 -96
  64. package/dist/internal/compiler/jit.js.map +1 -1
  65. package/dist/internal/compiler/registry.d.ts +10 -2
  66. package/dist/internal/compiler/registry.d.ts.map +1 -1
  67. package/dist/internal/compiler/registry.js.map +1 -1
  68. package/dist/internal/compiler/search.d.ts +32 -0
  69. package/dist/internal/compiler/search.d.ts.map +1 -0
  70. package/dist/internal/compiler/search.js +68 -0
  71. package/dist/internal/compiler/search.js.map +1 -0
  72. package/dist/internal/compiler/sets.d.ts.map +1 -1
  73. package/dist/internal/compiler/sets.js +1 -1
  74. package/dist/internal/compiler/sets.js.map +1 -1
  75. package/dist/internal/compiler/wasm.d.ts +8 -0
  76. package/dist/internal/compiler/wasm.d.ts.map +1 -0
  77. package/dist/internal/compiler/wasm.js +2769 -0
  78. package/dist/internal/compiler/wasm.js.map +1 -0
  79. package/dist/internal/compiler/wasmAsm.d.ts +199 -0
  80. package/dist/internal/compiler/wasmAsm.d.ts.map +1 -0
  81. package/dist/internal/compiler/wasmAsm.js +427 -0
  82. package/dist/internal/compiler/wasmAsm.js.map +1 -0
  83. package/dist/internal/entries.d.ts +3 -1
  84. package/dist/internal/entries.d.ts.map +1 -1
  85. package/dist/internal/entries.js.map +1 -1
  86. package/dist/internal/node.d.ts +58 -2
  87. package/dist/internal/node.d.ts.map +1 -1
  88. package/dist/internal/node.js +13 -3
  89. package/dist/internal/node.js.map +1 -1
  90. package/dist/internal/numbers.d.ts.map +1 -1
  91. package/dist/internal/numbers.js.map +1 -1
  92. package/dist/internal/run.d.ts +12 -0
  93. package/dist/internal/run.d.ts.map +1 -1
  94. package/dist/internal/run.js +51 -11
  95. package/dist/internal/run.js.map +1 -1
  96. package/dist/internal/stack.d.ts +6 -0
  97. package/dist/internal/stack.d.ts.map +1 -1
  98. package/dist/internal/stack.js +8 -2
  99. package/dist/internal/stack.js.map +1 -1
  100. package/dist/internal/syntax.d.ts +4 -4
  101. package/dist/internal/syntax.d.ts.map +1 -1
  102. package/dist/internal/syntax.js +18 -10
  103. package/dist/internal/syntax.js.map +1 -1
  104. package/dist/internal/text.d.ts +32 -0
  105. package/dist/internal/text.d.ts.map +1 -1
  106. package/dist/internal/text.js +68 -14
  107. package/dist/internal/text.js.map +1 -1
  108. package/dist/internal/tokens.d.ts +13 -0
  109. package/dist/internal/tokens.d.ts.map +1 -1
  110. package/dist/internal/tokens.js +59 -39
  111. package/dist/internal/tokens.js.map +1 -1
  112. package/package.json +5 -4
  113. package/src/Ascii.ts +42 -9
  114. package/src/Binary.ts +151 -71
  115. package/src/Bits.ts +12 -6
  116. package/src/Compiler.ts +101 -10
  117. package/src/Expression.ts +94 -81
  118. package/src/Input.ts +65 -6
  119. package/src/Nom.ts +15 -5
  120. package/src/ParseError.ts +3 -0
  121. package/src/Parser.ts +678 -127
  122. package/src/ParserStream.ts +37 -18
  123. package/src/Syntax.ts +60 -36
  124. package/src/Text.ts +16 -15
  125. package/src/Token.ts +138 -29
  126. package/src/internal/compiler/closure.ts +362 -135
  127. package/src/internal/compiler/entries.ts +4 -2
  128. package/src/internal/compiler/first.ts +10 -0
  129. package/src/internal/compiler/graph.ts +68 -0
  130. package/src/internal/compiler/jit.ts +284 -154
  131. package/src/internal/compiler/registry.ts +10 -2
  132. package/src/internal/compiler/search.ts +68 -0
  133. package/src/internal/compiler/sets.ts +7 -3
  134. package/src/internal/compiler/wasm.ts +3203 -0
  135. package/src/internal/compiler/wasmAsm.ts +484 -0
  136. package/src/internal/entries.ts +8 -2
  137. package/src/internal/node.ts +54 -4
  138. package/src/internal/numbers.ts +3 -1
  139. package/src/internal/run.ts +71 -12
  140. package/src/internal/stack.ts +8 -1
  141. package/src/internal/syntax.ts +39 -18
  142. package/src/internal/text.ts +97 -9
  143. package/src/internal/tokens.ts +96 -14
@@ -2,7 +2,7 @@ import * as Predicate from "effect/Predicate";
2
2
  import * as Result from "effect/Result";
3
3
  import { charOf, firstCodePoint } from "./text.js";
4
4
  // src/internal/tokens.ts
5
- const isRange = (u) => Predicate.isObjectOrArray(u) && u._tag === "TokenRange";
5
+ const isRange = (u) => Predicate.isObjectOrArray(u) && Predicate.isTagged(u, "TokenRange");
6
6
  const toCode = (u) => Predicate.isNumber(u) ? u : firstCodePoint(u);
7
7
  /** @internal */
8
8
  const describeChar = (s) => JSON.stringify(s);
@@ -89,8 +89,9 @@ const PredicateRanges = /*#__PURE__*/ Symbol.for("effect-parse/PredicateRanges")
89
89
  */
90
90
  const codePointPredicate = (name, f, ranges) => {
91
91
  Object.defineProperty(f, "name", { value: name });
92
- f[CodePointPredicate] = true;
93
- if (ranges !== void 0) f[PredicateRanges] = ranges;
92
+ const marked = f;
93
+ marked[CodePointPredicate] = true;
94
+ if (ranges !== void 0) marked[PredicateRanges] = ranges;
94
95
  return f;
95
96
  };
96
97
  /**
@@ -202,10 +203,29 @@ const nextIf = (state, m, negate) => {
202
203
  }
203
204
  }
204
205
  };
206
+ /** The one record {@link scan} fills; see there. */
207
+ var ScanResult = class {
208
+ offset = 0;
209
+ count = 0;
210
+ hitEnd = false;
211
+ };
212
+ const scanned = /*#__PURE__*/ new ScanResult();
213
+ /** Fills {@link scanned} and returns it. */
214
+ const scannedAt = (offset, count, hitEnd) => {
215
+ scanned.offset = offset;
216
+ scanned.count = count;
217
+ scanned.hitEnd = hitEnd;
218
+ return scanned;
219
+ };
205
220
  /**
206
221
  * Scans forward while tokens satisfy the matcher (xor `negate`), up to `max`
207
222
  * tokens. Returns the offset reached, the number of tokens matched, and
208
223
  * whether the end of input was hit before `max` tokens.
224
+ *
225
+ * The result is one shared record, overwritten by the next scan: read it
226
+ * before running anything else. Allocating one per call cost the
227
+ * interpreter a record per token, since `scan` (shared by every `takeWhile`)
228
+ * is too polymorphic for V8 to inline and remove it.
209
229
  */
210
230
  const scan = (state, m, negate, max) => {
211
231
  let i = state.pos;
@@ -216,70 +236,42 @@ const scan = (state, m, negate, max) => {
216
236
  const s = state.input;
217
237
  const test = m.forString.code;
218
238
  while (count < max) {
219
- if (i >= end) return {
220
- offset: i,
221
- count,
222
- hitEnd: true
223
- };
239
+ if (i >= end) return scannedAt(i, count, true);
224
240
  const c = s.charCodeAt(i);
225
241
  if (c < 55296 || c > 56319) {
226
242
  if (test(c) === negate) break;
227
243
  i++;
228
244
  } else {
229
- if (splitSurrogate(state, i)) return {
230
- offset: i,
231
- count,
232
- hitEnd: true
233
- };
245
+ if (splitSurrogate(state, i)) return scannedAt(i, count, true);
234
246
  const cp = codePointAt(s, i);
235
247
  if (test(cp) === negate) break;
236
248
  i += cp > 65535 ? 2 : 1;
237
249
  }
238
250
  count++;
239
251
  }
240
- return {
241
- offset: i,
242
- count,
243
- hitEnd: false
244
- };
252
+ return scannedAt(i, count, false);
245
253
  }
246
254
  case 1: {
247
255
  const bytes = state.input;
248
256
  const test = m.forCode.code;
249
257
  while (count < max) {
250
- if (i >= end) return {
251
- offset: i,
252
- count,
253
- hitEnd: true
254
- };
258
+ if (i >= end) return scannedAt(i, count, true);
255
259
  if (test(bytes[i]) === negate) break;
256
260
  i++;
257
261
  count++;
258
262
  }
259
- return {
260
- offset: i,
261
- count,
262
- hitEnd: false
263
- };
263
+ return scannedAt(i, count, false);
264
264
  }
265
265
  default: {
266
266
  const arr = state.input;
267
267
  const test = m.forCode.token;
268
268
  while (count < max) {
269
- if (i >= end) return {
270
- offset: i,
271
- count,
272
- hitEnd: true
273
- };
269
+ if (i >= end) return scannedAt(i, count, true);
274
270
  if (test(arr[i]) === negate) break;
275
271
  i++;
276
272
  count++;
277
273
  }
278
- return {
279
- offset: i,
280
- count,
281
- hitEnd: false
282
- };
274
+ return scannedAt(i, count, false);
283
275
  }
284
276
  }
285
277
  };
@@ -318,6 +310,34 @@ const countTokens = (state, start, end) => {
318
310
  }
319
311
  return count;
320
312
  };
313
+ /**
314
+ * The first index at or after `from` of any of `needles` within
315
+ * `[from, state.end)`, or -1. The state remembers, under `needles`, where
316
+ * each one next occurs (`[from, at]` at `2 * i`), so successive searches
317
+ * forwards over one input search each needle once per occurrence rather
318
+ * than once per call (as `nextStop` does for `takeTill`).
319
+ */
320
+ const indexOfAny = (state, needles, from) => {
321
+ const searches = state.searches ??= /* @__PURE__ */ new Map();
322
+ let memo = searches.get(needles);
323
+ if (memo === void 0) {
324
+ memo = needles.flatMap(() => [-1, -1]);
325
+ searches.set(needles, memo);
326
+ }
327
+ let best = -1;
328
+ for (let i = 0; i < needles.length; i++) {
329
+ const known = memo[2 * i] ?? -1;
330
+ let at = memo[2 * i + 1] ?? -1;
331
+ const needle = needles[i] ?? "";
332
+ if (known < 0 || from < known || at >= 0 && (at < from || at > state.end - needle.length)) {
333
+ at = indexOf(state, needle, from);
334
+ memo[2 * i] = from;
335
+ memo[2 * i + 1] = at;
336
+ }
337
+ if (at >= 0 && (best < 0 || at < best)) best = at;
338
+ }
339
+ return best;
340
+ };
321
341
  /** Finds `needle` within `[from, state.end)`; returns -1 if absent. */
322
342
  const indexOf = (state, needle, from) => {
323
343
  const last = state.end - needle.length;
@@ -397,6 +417,6 @@ const match = (state, lit, caseless) => {
397
417
  }
398
418
  };
399
419
  const lowerAscii = (c) => c >= 65 && c <= 90 ? c + 32 : c;
400
- export { End, NoMatch, PredicateRanges, advance, codePointPredicate, compile, compileAny, countTokens, describeChar, describeLiteral, indexOf, matchLiteral, nextIf, scan, splitSurrogate };
420
+ export { End, NoMatch, PredicateRanges, advance, codePointPredicate, compile, compileAny, countTokens, describeChar, describeLiteral, indexOf, indexOfAny, matchLiteral, nextIf, scan, splitSurrogate };
401
421
 
402
422
  //# sourceMappingURL=tokens.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.js","names":[],"sources":["../../src/internal/tokens.ts"],"sourcesContent":["// fallow-ignore-file duplicate-export -- `End` and `scan` here are the token-set versions of the text\n// helpers in ./text.ts; both are internal modules, imported by path, never re-exported from one barrel.\nimport * as Predicate from \"effect/Predicate\"\nimport * as Result from \"effect/Result\"\nimport type { Input, State } from \"../Input.js\"\nimport { charOf, firstCodePoint } from \"./text.js\"\n\n/** A compiled token set. */\nexport interface Matcher {\n /** Tests a code point (string input) or a byte (Uint8Array input). */\n readonly code: (code: number) => boolean\n /** Tests an element of an array input. */\n readonly token: (token: unknown) => boolean\n /** Human readable description, used in error messages. */\n readonly description: string\n}\n\n/** @internal */\nexport interface TokenRangeLike {\n readonly _tag: \"TokenRange\"\n readonly from: string | number\n readonly to: string | number\n}\n\nconst isRange = (u: unknown): u is TokenRangeLike => Predicate.isObjectOrArray(u) && (u as any)._tag === \"TokenRange\"\n\nconst toCode = (u: string | number): number => (Predicate.isNumber(u) ? u : firstCodePoint(u))\n\n/** @internal */\nexport const describeChar = (s: string): string => JSON.stringify(s)\n\nconst describeSet = (u: unknown): string => {\n if (Predicate.isString(u)) {\n const chars = Array.from(u)\n return chars.length === 1 ? describeChar(u) : `one of ${JSON.stringify(u)}`\n }\n if (Predicate.isNumber(u)) return `0x${u.toString(16).padStart(2, \"0\")}`\n if (Predicate.isFunction(u)) return u.name ? u.name : \"a matching token\"\n if (u instanceof Uint8Array) return `one of ${describeBytes(u)}`\n if (isRange(u)) return `${describeSet(u.from)}..=${describeSet(u.to)}`\n if (Array.isArray(u)) return u.map(describeSet).join(\" or \")\n return JSON.stringify(u)\n}\n\n/** Renders bytes as a Rust-style byte string literal: b\"GET\\r\\n\". */\nconst describeBytes = (bytes: Uint8Array): string => {\n let out = 'b\"'\n for (const b of bytes) {\n if (b === 0x22) out += '\\\\\"'\n else if (b === 0x5c) out += \"\\\\\\\\\"\n else if (b === 0x0a) out += \"\\\\n\"\n else if (b === 0x0d) out += \"\\\\r\"\n else if (b === 0x09) out += \"\\\\t\"\n else if (b >= 0x20 && b < 0x7f) out += String.fromCharCode(b)\n else out += `\\\\x${b.toString(16).padStart(2, \"0\")}`\n }\n return out + '\"'\n}\n\nconst compileCode = (u: unknown): ((code: number) => boolean) => {\n if (Predicate.isString(u)) {\n const codes = Array.from(u, firstCodePoint)\n if (codes.length === 1) {\n const c = codes[0]\n return (x) => x === c\n }\n return bitmap(codes)\n }\n if (Predicate.isNumber(u)) return (x) => x === u\n if (Predicate.isFunction(u)) return u as (code: number) => boolean\n if (u instanceof Uint8Array) return bitmap(Array.from(u))\n if (isRange(u)) {\n const from = toCode(u.from)\n const to = toCode(u.to)\n return (x) => x >= from && x <= to\n }\n if (Array.isArray(u)) {\n const tests = u.map(compileCode)\n if (tests.length === 1) return tests[0]\n return (x) => {\n for (let i = 0; i < tests.length; i++) if (tests[i](x)) return true\n return false\n }\n }\n throw new TypeError(`invalid token set: ${String(u)}`)\n}\n\nconst bitmap = (codes: ReadonlyArray<number>): ((code: number) => boolean) => {\n const ascii = new Uint8Array(256)\n let other: Set<number> | undefined\n for (const c of codes) {\n if (c < 256) ascii[c] = 1\n else (other ??= new Set()).add(c)\n }\n if (other === undefined) return (x) => x < 256 && ascii[x] === 1\n const set = other\n return (x) => (x < 256 ? ascii[x] === 1 : set.has(x))\n}\n\nconst compileToken = (u: unknown): ((token: unknown) => boolean) => {\n if (Predicate.isFunction(u)) return u as (token: unknown) => boolean\n if (Array.isArray(u)) {\n const set = new Set(u)\n return (t) => set.has(t)\n }\n return (t) => t === u\n}\n\n/**\n * Marks a predicate over characters that also accepts a code point (a\n * number), so string inputs can call it without allocating a string per\n * character.\n */\nconst CodePointPredicate: unique symbol = /*#__PURE__*/ Symbol.for(\"effect-parse/CodePointPredicate\")\n\n/**\n * The code points accepted by a predicate, as sorted, disjoint, inclusive\n * ranges, when they are known. The compiler turns such predicates into\n * comparisons or tables.\n */\nexport const PredicateRanges: unique symbol = /*#__PURE__*/ Symbol.for(\"effect-parse/PredicateRanges\")\n\n/**\n * Marks `f` as a {@link CodePointPredicate} named `name` (used in error\n * messages), optionally recording the code point ranges it accepts.\n */\nexport const codePointPredicate = <F extends (c: never) => boolean>(\n name: string,\n f: F,\n ranges?: ReadonlyArray<readonly [number, number]>\n): F => {\n Object.defineProperty(f, \"name\", { value: name })\n ;(f as any)[CodePointPredicate] = true\n if (ranges !== undefined) (f as any)[PredicateRanges] = ranges\n return f\n}\n\n/**\n * Compiles a token set. Predicates for string inputs receive the token as a\n * string, so they are wrapped here; `charOf` avoids `String.fromCodePoint`,\n * which is several times slower, for the Basic Multilingual Plane.\n */\nexport const compile = (set: unknown, kind: \"string\" | \"code\" = \"code\"): Matcher => {\n const description = describeSet(set)\n let code: (code: number) => boolean\n if (Predicate.isFunction(set) && kind === \"string\" && !(CodePointPredicate in set)) {\n const pred = set as (c: string) => boolean\n code = (x) => pred(charOf(x))\n } else {\n code = compileCodeSafe(set, kind)\n }\n return { code, token: compileToken(set), description }\n}\n\nconst compileCodeSafe = (set: unknown, kind: \"string\" | \"code\"): ((code: number) => boolean) => {\n if (Array.isArray(set) && kind === \"string\") {\n // Predicates nested in arrays also take strings\n const tests = set.map((s) => compile(s, kind).code)\n return (x) => {\n for (let i = 0; i < tests.length; i++) if (tests[i](x)) return true\n return false\n }\n }\n return Result.getOrElse(\n Result.try(() => compileCode(set)),\n (): ((code: number) => boolean) => () => false\n )\n}\n\n/**\n * A matcher that works for every input kind. String predicates receive the\n * token as a string, byte predicates receive numbers.\n */\nexport interface AnyMatcher {\n readonly forString: Matcher\n readonly forCode: Matcher\n readonly description: string\n}\n\n/**\n * A small cache keyed by value, for the parts of a parser that are costly to\n * build and depend only on a string (compiled sets, descriptions). Parsers\n * built inside `Parser.gen` bodies are rebuilt on every run, usually from the\n * same few strings. Dynamic strings could grow it without bound, so it is\n * cleared when full.\n */\nconst cached = <A>(cache: Map<string, A>, key: string, build: (key: string) => A): A => {\n let a = cache.get(key)\n if (a === undefined) {\n if (cache.size >= 1024) cache.clear()\n a = build(key)\n cache.set(key, a)\n }\n return a\n}\n\nconst literalDescriptions = /*#__PURE__*/ new Map<string, string>()\n\n/** Describes a literal for error messages: `\"abc\"`, `b\"abc\"` or `[\"a\", 1]`. */\nexport const describeLiteral = (lit: Input): string =>\n Predicate.isString(lit)\n ? cached(literalDescriptions, lit, describeChar)\n : lit instanceof Uint8Array\n ? describeBytes(lit)\n : `[${lit.map((t) => JSON.stringify(t)).join(\", \")}]`\n\nconst stringMatchers = /*#__PURE__*/ new Map<string, AnyMatcher>()\n\nexport const compileAny = (set: unknown): AnyMatcher =>\n // Matchers for strings are pure functions of the string, so they're shared\n Predicate.isString(set) ? cached(stringMatchers, set, compileAnyImpl) : compileAnyImpl(set)\n\nconst compileAnyImpl = (set: unknown): AnyMatcher => {\n const forCode = compile(set, \"code\")\n const needsString = Predicate.isFunction(set) || Array.isArray(set)\n return {\n forString: needsString ? compile(set, \"string\") : forCode,\n forCode,\n description: forCode.description\n }\n}\n\n/**\n * Whether the string token at `i` is a high surrogate at the very end of a\n * partial input, i.e. the first half of a code point whose second half has\n * not arrived yet.\n */\nexport const splitSurrogate = (state: State<Input>, i: number): boolean => {\n if (!state.partial || i !== state.end - 1) return false\n const c = (state.input as string).charCodeAt(i)\n return c >= 0xd800 && c <= 0xdbff\n}\n\n/** Reads the code point at `i` of a string. */\nconst codePointAt = (s: string, i: number): number => {\n const c = s.charCodeAt(i)\n if (c >= 0xd800 && c <= 0xdbff && i + 1 < s.length) {\n const d = s.charCodeAt(i + 1)\n if (d >= 0xdc00 && d <= 0xdfff) return ((c - 0xd800) << 10) + (d - 0xdc00) + 0x10000\n }\n return c\n}\n\n/**\n * Tests the token at the current position. Returns the token (as the input's\n * token type) and advances, or returns `NoMatch`/`End`.\n */\nexport const NoMatch: unique symbol = /*#__PURE__*/ Symbol(\"NoMatch\")\nexport const End: unique symbol = /*#__PURE__*/ Symbol(\"End\")\n\nexport const nextIf = (state: State<Input>, m: AnyMatcher, negate: boolean): unknown => {\n const pos = state.pos\n if (pos >= state.end) return End\n switch (state.inputKind) {\n case 0: {\n const s = state.input as string\n if (splitSurrogate(state, pos)) return End\n const cp = codePointAt(s, pos)\n if (m.forString.code(cp) === negate) return NoMatch\n const len = cp > 0xffff ? 2 : 1\n state.pos = pos + len\n return len === 1 ? s[pos] : s.slice(pos, pos + 2)\n }\n case 1: {\n const b = (state.input as Uint8Array)[pos]\n if (m.forCode.code(b) === negate) return NoMatch\n state.pos = pos + 1\n return b\n }\n default: {\n const t = (state.input as ReadonlyArray<unknown>)[pos]\n if (m.forCode.token(t) === negate) return NoMatch\n state.pos = pos + 1\n return t\n }\n }\n}\n\n/** How far a {@link scan} got. */\nexport interface Scanned extends Advanced {\n /** Whether the end of input was hit before `max` tokens. */\n readonly hitEnd: boolean\n}\n\n/**\n * Scans forward while tokens satisfy the matcher (xor `negate`), up to `max`\n * tokens. Returns the offset reached, the number of tokens matched, and\n * whether the end of input was hit before `max` tokens.\n */\nexport const scan = (state: State<Input>, m: AnyMatcher, negate: boolean, max: number): Scanned => {\n let i = state.pos\n const end = state.end\n let count = 0\n switch (state.inputKind) {\n case 0: {\n const s = state.input as string\n const test = m.forString.code\n while (count < max) {\n if (i >= end) return { offset: i, count, hitEnd: true }\n const c = s.charCodeAt(i)\n if (c < 0xd800 || c > 0xdbff) {\n if (test(c) === negate) break\n i++\n } else {\n if (splitSurrogate(state, i)) return { offset: i, count, hitEnd: true }\n const cp = codePointAt(s, i)\n if (test(cp) === negate) break\n i += cp > 0xffff ? 2 : 1\n }\n count++\n }\n return { offset: i, count, hitEnd: false }\n }\n case 1: {\n const bytes = state.input as Uint8Array\n const test = m.forCode.code\n while (count < max) {\n if (i >= end) return { offset: i, count, hitEnd: true }\n if (test(bytes[i]) === negate) break\n i++\n count++\n }\n return { offset: i, count, hitEnd: false }\n }\n default: {\n const arr = state.input as ReadonlyArray<unknown>\n const test = m.forCode.token\n while (count < max) {\n if (i >= end) return { offset: i, count, hitEnd: true }\n if (test(arr[i]) === negate) break\n i++\n count++\n }\n return { offset: i, count, hitEnd: false }\n }\n }\n}\n\n/** The offset reached and the number of tokens passed. */\nexport interface Advanced {\n readonly offset: number\n readonly count: number\n}\n\n/** Advances `n` tokens from `start`, returning the offset reached and the count. */\nexport const advance = (state: State<Input>, start: number, n: number): Advanced => {\n if (state.inputKind !== 0) {\n const offset = Math.min(state.end, start + n)\n return { offset, count: offset - start }\n }\n const s = state.input as string\n let i = start\n let count = 0\n while (count < n && i < state.end) {\n if (splitSurrogate(state, i)) break\n const c = s.charCodeAt(i)\n i += c >= 0xd800 && c <= 0xdbff && i + 1 < s.length && (s.charCodeAt(i + 1) & 0xfc00) === 0xdc00 ? 2 : 1\n count++\n }\n return { offset: i, count }\n}\n\n/** Counts tokens between two offsets. */\nexport const countTokens = (state: State<Input>, start: number, end: number): number => {\n if (state.inputKind !== 0) return end - start\n const s = state.input as string\n let count = 0\n for (let i = start; i < end; i++) {\n const c = s.charCodeAt(i)\n if (c >= 0xd800 && c <= 0xdbff && i + 1 < end && (s.charCodeAt(i + 1) & 0xfc00) === 0xdc00) i++\n count++\n }\n return count\n}\n\n/** Finds `needle` within `[from, state.end)`; returns -1 if absent. */\nexport const indexOf = (state: State<Input>, needle: Input, from: number): number => {\n // The whole needle must lie before `state.end`, which may narrow the input\n const last = state.end - needle.length\n if (from > last) return -1\n switch (state.inputKind) {\n case 0: {\n const i = (state.input as string).indexOf(needle as string, from)\n return i <= last ? i : -1\n }\n case 1: {\n const hay = state.input as Uint8Array\n const n = needle as Uint8Array\n if (n.byteLength === 0) return from\n const first = n[0]\n let i = hay.indexOf(first, from)\n while (i !== -1 && i <= last) {\n let j = 1\n while (j < n.length && hay[i + j] === n[j]) j++\n if (j === n.length) return i\n i = hay.indexOf(first, i + 1)\n }\n return -1\n }\n default: {\n const hay = state.input as ReadonlyArray<unknown>\n const n = needle as ReadonlyArray<unknown>\n outer: for (let i = from; i <= last; i++) {\n for (let j = 0; j < n.length; j++) if (hay[i + j] !== n[j]) continue outer\n return i\n }\n return -1\n }\n }\n}\n\n/**\n * Compares the input at the current position with a literal. Returns the\n * number of matching units if the literal matches completely (its length),\n * -1 on mismatch, or -2 when the input ends while matching a prefix.\n */\nexport const matchLiteral = (state: State<Input>, lit: Input, caseless: boolean): number => {\n const r = match(state, lit, caseless)\n // A failed match may have read up to its length past where it fails (see `Syntax`)\n if (r < 0 && state.syntax !== undefined) state.syntax.read(state.pos + Math.min(lit.length, state.end - state.pos))\n return r\n}\n\nconst match = (state: State<Input>, lit: Input, caseless: boolean): number => {\n const pos = state.pos\n const len = lit.length\n const avail = state.end - pos\n const n = Math.min(len, avail)\n switch (state.inputKind) {\n case 0: {\n const s = state.input as string\n const l = lit as string\n if (!caseless) {\n if (avail >= len) return s.startsWith(l, pos) ? len : -1\n return l.startsWith(s.slice(pos)) ? -2 : -1\n }\n for (let i = 0; i < n; i++) {\n if (lowerAscii(s.charCodeAt(pos + i)) !== lowerAscii(l.charCodeAt(i))) return -1\n }\n return n === len ? len : -2\n }\n case 1: {\n const b = state.input as Uint8Array\n const l = lit as Uint8Array\n for (let i = 0; i < n; i++) {\n const x = b[pos + i]\n const y = l[i]\n if (caseless ? lowerAscii(x) !== lowerAscii(y) : x !== y) return -1\n }\n return n === len ? len : -2\n }\n default: {\n const a = state.input as ReadonlyArray<unknown>\n const l = lit as ReadonlyArray<unknown>\n for (let i = 0; i < n; i++) if (a[pos + i] !== l[i]) return -1\n return n === len ? len : -2\n }\n }\n}\n\nconst lowerAscii = (c: number): number => (c >= 65 && c <= 90 ? c + 32 : c)\n"],"mappings":"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"}
1
+ {"version":3,"file":"tokens.js","names":[],"sources":["../../src/internal/tokens.ts"],"sourcesContent":["import * as Predicate from \"effect/Predicate\"\nimport * as Result from \"effect/Result\"\nimport type { Input, State } from \"../Input.js\"\nimport { charOf, firstCodePoint } from \"./text.js\"\n\n/** A compiled token set. */\nexport interface Matcher {\n /** Tests a code point (string input) or a byte (Uint8Array input). */\n readonly code: (code: number) => boolean\n /** Tests an element of an array input. */\n readonly token: (token: unknown) => boolean\n /** Human readable description, used in error messages. */\n readonly description: string\n}\n\n/** @internal */\nexport interface TokenRangeLike {\n readonly _tag: \"TokenRange\"\n readonly from: string | number\n readonly to: string | number\n}\n\nconst isRange = (u: unknown): u is TokenRangeLike => Predicate.isObjectOrArray(u) && Predicate.isTagged(u, \"TokenRange\")\n\nconst toCode = (u: string | number): number => (Predicate.isNumber(u) ? u : firstCodePoint(u))\n\n/** @internal */\nexport const describeChar = (s: string): string => JSON.stringify(s)\n\nconst describeSet = (u: unknown): string => {\n if (Predicate.isString(u)) {\n const chars = Array.from(u)\n return chars.length === 1 ? describeChar(u) : `one of ${JSON.stringify(u)}`\n }\n if (Predicate.isNumber(u)) return `0x${u.toString(16).padStart(2, \"0\")}`\n if (Predicate.isFunction(u)) return u.name ? u.name : \"a matching token\"\n if (u instanceof Uint8Array) return `one of ${describeBytes(u)}`\n if (isRange(u)) return `${describeSet(u.from)}..=${describeSet(u.to)}`\n if (Array.isArray(u)) return u.map(describeSet).join(\" or \")\n return JSON.stringify(u)\n}\n\n/** Renders bytes as a Rust-style byte string literal: b\"GET\\r\\n\". */\nconst describeBytes = (bytes: Uint8Array): string => {\n let out = 'b\"'\n for (const b of bytes) {\n if (b === 0x22) out += '\\\\\"'\n else if (b === 0x5c) out += \"\\\\\\\\\"\n else if (b === 0x0a) out += \"\\\\n\"\n else if (b === 0x0d) out += \"\\\\r\"\n else if (b === 0x09) out += \"\\\\t\"\n else if (b >= 0x20 && b < 0x7f) out += String.fromCharCode(b)\n else out += `\\\\x${b.toString(16).padStart(2, \"0\")}`\n }\n return out + '\"'\n}\n\nconst compileCode = (u: unknown): ((code: number) => boolean) => {\n if (Predicate.isString(u)) {\n const codes = Array.from(u, firstCodePoint)\n if (codes.length === 1) {\n const c = codes[0]\n return (x) => x === c\n }\n return bitmap(codes)\n }\n if (Predicate.isNumber(u)) return (x) => x === u\n if (Predicate.isFunction(u)) {\n // SAFETY: a predicate compiled for codes is a byte, code point or `codePoints` predicate (`compile` wraps string predicates first)\n return u as (code: number) => boolean\n }\n if (u instanceof Uint8Array) return bitmap(Array.from(u))\n if (isRange(u)) {\n const from = toCode(u.from)\n const to = toCode(u.to)\n return (x) => x >= from && x <= to\n }\n if (Array.isArray(u)) {\n const tests = u.map(compileCode)\n if (tests.length === 1) return tests[0]\n return (x) => {\n for (let i = 0; i < tests.length; i++) if (tests[i](x)) return true\n return false\n }\n }\n throw new TypeError(`invalid token set: ${String(u)}`)\n}\n\nconst bitmap = (codes: ReadonlyArray<number>): ((code: number) => boolean) => {\n const ascii = new Uint8Array(256)\n let other: Set<number> | undefined\n for (const c of codes) {\n if (c < 256) ascii[c] = 1\n else (other ??= new Set()).add(c)\n }\n if (other === undefined) return (x) => x < 256 && ascii[x] === 1\n const set = other\n return (x) => (x < 256 ? ascii[x] === 1 : set.has(x))\n}\n\nconst compileToken = (u: unknown): ((token: unknown) => boolean) => {\n if (Predicate.isFunction(u)) {\n // SAFETY: a predicate in an array input's token set takes the array's elements, the tokens tested here\n return u as (token: unknown) => boolean\n }\n if (Array.isArray(u)) {\n const set = new Set(u)\n return (t) => set.has(t)\n }\n return (t) => t === u\n}\n\n/**\n * Marks a predicate over characters that also accepts a code point (a\n * number), so string inputs can call it without allocating a string per\n * character.\n */\nconst CodePointPredicate: unique symbol = /*#__PURE__*/ Symbol.for(\"effect-parse/CodePointPredicate\")\n\n/**\n * The code points accepted by a predicate, as sorted, disjoint, inclusive\n * ranges, when they are known. The compiler turns such predicates into\n * comparisons or tables.\n */\nexport const PredicateRanges: unique symbol = /*#__PURE__*/ Symbol.for(\"effect-parse/PredicateRanges\")\n\n/**\n * Marks `f` as a {@link CodePointPredicate} named `name` (used in error\n * messages), optionally recording the code point ranges it accepts.\n */\nexport const codePointPredicate = <F extends (c: never) => boolean>(\n name: string,\n f: F,\n ranges?: ReadonlyArray<readonly [number, number]>\n): F => {\n Object.defineProperty(f, \"name\", { value: name })\n // SAFETY: `f` is a function object, which takes new properties; the intersection only names the two markers set here\n const marked = f as F & {\n [CodePointPredicate]?: true\n [PredicateRanges]?: ReadonlyArray<readonly [number, number]>\n }\n marked[CodePointPredicate] = true\n if (ranges !== undefined) marked[PredicateRanges] = ranges\n return f\n}\n\n/**\n * Compiles a token set. Predicates for string inputs receive the token as a\n * string, so they are wrapped here; `charOf` avoids `String.fromCodePoint`,\n * which is several times slower, for the Basic Multilingual Plane.\n */\nexport const compile = (set: unknown, kind: \"string\" | \"code\" = \"code\"): Matcher => {\n const description = describeSet(set)\n let code: (code: number) => boolean\n if (Predicate.isFunction(set) && kind === \"string\" && !(CodePointPredicate in set)) {\n // SAFETY: an unmarked predicate in a string token set takes each character as a string (`StringTokenSet`)\n const pred = set as (c: string) => boolean\n code = (x) => pred(charOf(x))\n } else {\n code = compileCodeSafe(set, kind)\n }\n return { code, token: compileToken(set), description }\n}\n\nconst compileCodeSafe = (set: unknown, kind: \"string\" | \"code\"): ((code: number) => boolean) => {\n if (Array.isArray(set) && kind === \"string\") {\n // Predicates nested in arrays also take strings\n const tests = set.map((s) => compile(s, kind).code)\n return (x) => {\n for (let i = 0; i < tests.length; i++) if (tests[i](x)) return true\n return false\n }\n }\n return Result.getOrElse(\n Result.try(() => compileCode(set)),\n (): ((code: number) => boolean) => () => false\n )\n}\n\n/**\n * A matcher that works for every input kind. String predicates receive the\n * token as a string, byte predicates receive numbers.\n */\nexport interface AnyMatcher {\n readonly forString: Matcher\n readonly forCode: Matcher\n readonly description: string\n}\n\n/**\n * A small cache keyed by value, for the parts of a parser that are costly to\n * build and depend only on a string (compiled sets, descriptions). Parsers\n * built inside `Parser.gen` bodies are rebuilt on every run, usually from the\n * same few strings. Dynamic strings could grow it without bound, so it is\n * cleared when full.\n */\nconst cached = <A>(cache: Map<string, A>, key: string, build: (key: string) => A): A => {\n let a = cache.get(key)\n if (a === undefined) {\n if (cache.size >= 1024) cache.clear()\n a = build(key)\n cache.set(key, a)\n }\n return a\n}\n\nconst literalDescriptions = /*#__PURE__*/ new Map<string, string>()\n\n/** Describes a literal for error messages: `\"abc\"`, `b\"abc\"` or `[\"a\", 1]`. */\nexport const describeLiteral = (lit: Input): string =>\n Predicate.isString(lit)\n ? cached(literalDescriptions, lit, describeChar)\n : lit instanceof Uint8Array\n ? describeBytes(lit)\n : `[${lit.map((t) => JSON.stringify(t)).join(\", \")}]`\n\nconst stringMatchers = /*#__PURE__*/ new Map<string, AnyMatcher>()\n\nexport const compileAny = (set: unknown): AnyMatcher =>\n // Matchers for strings are pure functions of the string, so they're shared\n Predicate.isString(set) ? cached(stringMatchers, set, compileAnyImpl) : compileAnyImpl(set)\n\nconst compileAnyImpl = (set: unknown): AnyMatcher => {\n const forCode = compile(set, \"code\")\n const needsString = Predicate.isFunction(set) || Array.isArray(set)\n return {\n forString: needsString ? compile(set, \"string\") : forCode,\n forCode,\n description: forCode.description\n }\n}\n\n/**\n * Whether the string token at `i` is a high surrogate at the very end of a\n * partial input, i.e. the first half of a code point whose second half has\n * not arrived yet.\n */\nexport const splitSurrogate = (state: State<Input>, i: number): boolean => {\n if (!state.partial || i !== state.end - 1) return false\n // SAFETY: called only on string input (the `inputKind === 0` paths of `nextIf`, `scan`, `advance` and `Token.any`)\n const c = (state.input as string).charCodeAt(i)\n return c >= 0xd800 && c <= 0xdbff\n}\n\n/** Reads the code point at `i` of a string. */\nconst codePointAt = (s: string, i: number): number => {\n const c = s.charCodeAt(i)\n if (c >= 0xd800 && c <= 0xdbff && i + 1 < s.length) {\n const d = s.charCodeAt(i + 1)\n if (d >= 0xdc00 && d <= 0xdfff) return ((c - 0xd800) << 10) + (d - 0xdc00) + 0x10000\n }\n return c\n}\n\n/**\n * Tests the token at the current position. Returns the token (as the input's\n * token type) and advances, or returns `NoMatch`/`End`.\n */\nexport const NoMatch: unique symbol = /*#__PURE__*/ Symbol(\"NoMatch\")\nexport const End: unique symbol = /*#__PURE__*/ Symbol(\"End\")\n\nexport const nextIf = (state: State<Input>, m: AnyMatcher, negate: boolean): unknown => {\n const pos = state.pos\n if (pos >= state.end) return End\n switch (state.inputKind) {\n case 0: {\n // SAFETY: `inputKind` 0 is set only for a string input\n const s = state.input as string\n if (splitSurrogate(state, pos)) return End\n const cp = codePointAt(s, pos)\n if (m.forString.code(cp) === negate) return NoMatch\n const len = cp > 0xffff ? 2 : 1\n state.pos = pos + len\n return len === 1 ? s[pos] : s.slice(pos, pos + 2)\n }\n case 1: {\n // SAFETY: `inputKind` 1 is set only for a `Uint8Array` input\n const b = (state.input as Uint8Array)[pos]\n if (m.forCode.code(b) === negate) return NoMatch\n state.pos = pos + 1\n return b\n }\n default: {\n // SAFETY: `inputKind` 2 is set for every input that is neither a string nor a `Uint8Array`, an array\n const t = (state.input as ReadonlyArray<unknown>)[pos]\n if (m.forCode.token(t) === negate) return NoMatch\n state.pos = pos + 1\n return t\n }\n }\n}\n\n/** How far a {@link scan} got. */\nexport interface Scanned extends Advanced {\n /** Whether the end of input was hit before `max` tokens. */\n readonly hitEnd: boolean\n}\n\n/** The one record {@link scan} fills; see there. */\nclass ScanResult implements Scanned {\n offset = 0\n count = 0\n hitEnd = false\n}\n\nconst scanned = /*#__PURE__*/ new ScanResult()\n\n/** Fills {@link scanned} and returns it. */\nconst scannedAt = (offset: number, count: number, hitEnd: boolean): Scanned => {\n scanned.offset = offset\n scanned.count = count\n scanned.hitEnd = hitEnd\n return scanned\n}\n\n/**\n * Scans forward while tokens satisfy the matcher (xor `negate`), up to `max`\n * tokens. Returns the offset reached, the number of tokens matched, and\n * whether the end of input was hit before `max` tokens.\n *\n * The result is one shared record, overwritten by the next scan: read it\n * before running anything else. Allocating one per call cost the\n * interpreter a record per token, since `scan` (shared by every `takeWhile`)\n * is too polymorphic for V8 to inline and remove it.\n */\nexport const scan = (state: State<Input>, m: AnyMatcher, negate: boolean, max: number): Scanned => {\n let i = state.pos\n const end = state.end\n let count = 0\n switch (state.inputKind) {\n case 0: {\n // SAFETY: `inputKind` 0 is set only for a string input\n const s = state.input as string\n const test = m.forString.code\n while (count < max) {\n if (i >= end) return scannedAt(i, count, true)\n const c = s.charCodeAt(i)\n if (c < 0xd800 || c > 0xdbff) {\n if (test(c) === negate) break\n i++\n } else {\n if (splitSurrogate(state, i)) return scannedAt(i, count, true)\n const cp = codePointAt(s, i)\n if (test(cp) === negate) break\n i += cp > 0xffff ? 2 : 1\n }\n count++\n }\n return scannedAt(i, count, false)\n }\n case 1: {\n // SAFETY: `inputKind` 1 is set only for a `Uint8Array` input\n const bytes = state.input as Uint8Array\n const test = m.forCode.code\n while (count < max) {\n if (i >= end) return scannedAt(i, count, true)\n if (test(bytes[i]) === negate) break\n i++\n count++\n }\n return scannedAt(i, count, false)\n }\n default: {\n // SAFETY: `inputKind` 2 is set for every input that is neither a string nor a `Uint8Array`, an array\n const arr = state.input as ReadonlyArray<unknown>\n const test = m.forCode.token\n while (count < max) {\n if (i >= end) return scannedAt(i, count, true)\n if (test(arr[i]) === negate) break\n i++\n count++\n }\n return scannedAt(i, count, false)\n }\n }\n}\n\n/** The offset reached and the number of tokens passed. */\nexport interface Advanced {\n readonly offset: number\n readonly count: number\n}\n\n/** Advances `n` tokens from `start`, returning the offset reached and the count. */\nexport const advance = (state: State<Input>, start: number, n: number): Advanced => {\n if (state.inputKind !== 0) {\n const offset = Math.min(state.end, start + n)\n return { offset, count: offset - start }\n }\n // SAFETY: the other input kinds returned above, and `inputKind` 0 is set only for a string input\n const s = state.input as string\n let i = start\n let count = 0\n while (count < n && i < state.end) {\n if (splitSurrogate(state, i)) break\n const c = s.charCodeAt(i)\n i += c >= 0xd800 && c <= 0xdbff && i + 1 < s.length && (s.charCodeAt(i + 1) & 0xfc00) === 0xdc00 ? 2 : 1\n count++\n }\n return { offset: i, count }\n}\n\n/** Counts tokens between two offsets. */\nexport const countTokens = (state: State<Input>, start: number, end: number): number => {\n if (state.inputKind !== 0) return end - start\n // SAFETY: the other input kinds returned above, and `inputKind` 0 is set only for a string input\n const s = state.input as string\n let count = 0\n for (let i = start; i < end; i++) {\n const c = s.charCodeAt(i)\n if (c >= 0xd800 && c <= 0xdbff && i + 1 < end && (s.charCodeAt(i + 1) & 0xfc00) === 0xdc00) i++\n count++\n }\n return count\n}\n\n/**\n * The first index at or after `from` of any of `needles` within\n * `[from, state.end)`, or -1. The state remembers, under `needles`, where\n * each one next occurs (`[from, at]` at `2 * i`), so successive searches\n * forwards over one input search each needle once per occurrence rather\n * than once per call (as `nextStop` does for `takeTill`).\n */\nexport const indexOfAny = (state: State<Input>, needles: ReadonlyArray<Input>, from: number): number => {\n const searches = (state.searches ??= new Map())\n let memo = searches.get(needles)\n if (memo === undefined) {\n memo = needles.flatMap(() => [-1, -1])\n searches.set(needles, memo)\n }\n let best = -1\n for (let i = 0; i < needles.length; i++) {\n const known = memo[2 * i] ?? -1\n let at = memo[2 * i + 1] ?? -1\n const needle = needles[i] ?? \"\"\n // Searched again when the input's end moved before a remembered occurrence\n if (known < 0 || from < known || (at >= 0 && (at < from || at > state.end - needle.length))) {\n at = indexOf(state, needle, from)\n memo[2 * i] = from\n memo[2 * i + 1] = at\n }\n if (at >= 0 && (best < 0 || at < best)) best = at\n }\n return best\n}\n\n/** Finds `needle` within `[from, state.end)`; returns -1 if absent. */\nexport const indexOf = (state: State<Input>, needle: Input, from: number): number => {\n // The whole needle must lie before `state.end`, which may narrow the input\n const last = state.end - needle.length\n if (from > last) return -1\n switch (state.inputKind) {\n case 0: {\n // SAFETY: `inputKind` 0 is set only for a string input, and the callers' types give the needle the input's kind\n const i = (state.input as string).indexOf(needle as string, from)\n return i <= last ? i : -1\n }\n case 1: {\n // SAFETY: `inputKind` 1 is set only for a `Uint8Array` input\n const hay = state.input as Uint8Array\n // SAFETY: the callers' types give the needle the input's kind (`Text` encodes it for byte input)\n const n = needle as Uint8Array\n if (n.byteLength === 0) return from\n const first = n[0]\n let i = hay.indexOf(first, from)\n while (i !== -1 && i <= last) {\n let j = 1\n while (j < n.length && hay[i + j] === n[j]) j++\n if (j === n.length) return i\n i = hay.indexOf(first, i + 1)\n }\n return -1\n }\n default: {\n // SAFETY: `inputKind` 2 is set for every input that is neither a string nor a `Uint8Array`, an array\n const hay = state.input as ReadonlyArray<unknown>\n // SAFETY: the callers' types give the needle the input's kind, an array of the same element type\n const n = needle as ReadonlyArray<unknown>\n outer: for (let i = from; i <= last; i++) {\n for (let j = 0; j < n.length; j++) if (hay[i + j] !== n[j]) continue outer\n return i\n }\n return -1\n }\n }\n}\n\n/**\n * Compares the input at the current position with a literal. Returns the\n * number of matching units if the literal matches completely (its length),\n * -1 on mismatch, or -2 when the input ends while matching a prefix.\n */\nexport const matchLiteral = (state: State<Input>, lit: Input, caseless: boolean): number => {\n const r = match(state, lit, caseless)\n // A failed match may have read up to its length past where it fails (see `Syntax`)\n if (r < 0 && state.syntax !== undefined) state.syntax.read(state.pos + Math.min(lit.length, state.end - state.pos))\n return r\n}\n\nconst match = (state: State<Input>, lit: Input, caseless: boolean): number => {\n const pos = state.pos\n const len = lit.length\n const avail = state.end - pos\n const n = Math.min(len, avail)\n switch (state.inputKind) {\n case 0: {\n // SAFETY: `inputKind` 0 is set only for a string input\n const s = state.input as string\n // SAFETY: the callers' types give the literal the input's kind (`Token.literal` encodes a string literal for byte input)\n const l = lit as string\n if (!caseless) {\n if (avail >= len) return s.startsWith(l, pos) ? len : -1\n return l.startsWith(s.slice(pos)) ? -2 : -1\n }\n for (let i = 0; i < n; i++) {\n if (lowerAscii(s.charCodeAt(pos + i)) !== lowerAscii(l.charCodeAt(i))) return -1\n }\n return n === len ? len : -2\n }\n case 1: {\n // SAFETY: `inputKind` 1 is set only for a `Uint8Array` input\n const b = state.input as Uint8Array\n // SAFETY: the callers' types give the literal the input's kind (`Token.literal` and `Text` encode string literals for byte input)\n const l = lit as Uint8Array\n for (let i = 0; i < n; i++) {\n const x = b[pos + i]\n const y = l[i]\n if (caseless ? lowerAscii(x) !== lowerAscii(y) : x !== y) return -1\n }\n return n === len ? len : -2\n }\n default: {\n // SAFETY: `inputKind` 2 is set for every input that is neither a string nor a `Uint8Array`, an array\n const a = state.input as ReadonlyArray<unknown>\n // SAFETY: the callers' types give the literal the input's kind, an array of the same element type\n const l = lit as ReadonlyArray<unknown>\n for (let i = 0; i < n; i++) if (a[pos + i] !== l[i]) return -1\n return n === len ? len : -2\n }\n }\n}\n\nconst lowerAscii = (c: number): number => (c >= 65 && c <= 90 ? c + 32 : c)\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://www.schemastore.org/package",
3
3
  "name": "@thomasfosterau/effect-parse",
4
- "version": "0.4.1",
4
+ "version": "0.5.0",
5
5
  "description": "Parser combinators for Effect, ported from Rust's nom and winnow: text, bytes, bits and token streams, streaming input, compiled parsers and Schema integration",
6
6
  "keywords": [
7
7
  "effect",
@@ -102,13 +102,14 @@
102
102
  "@changesets/changelog-github": "^1.0.1",
103
103
  "@changesets/cli": "^3.0.3",
104
104
  "@effect/language-service": "^0.87.5",
105
+ "@effect/platform-node-shared": "4.1.1",
105
106
  "@effect/tsgo": "0.63.0",
106
- "@enfect/oxlint": "^0.9.0",
107
+ "@enfect/oxlint": "^0.10.0",
107
108
  "@types/node": "^26.6.5",
108
109
  "@typescript/native": "npm:typescript@7.0.2",
109
110
  "@vitest/coverage-istanbul": "5.0.5",
110
- "effect": "4.1.0",
111
- "fallow": "3.37.0",
111
+ "effect": "4.1.1",
112
+ "fallow": "3.40.0",
112
113
  "rolldown": "^1.2.14",
113
114
  "typescript": "npm:@typescript/typescript6@6.0.2",
114
115
  "vite": "npm:@voidzero-dev/vite-plus-core@1.4.0",
package/src/Ascii.ts CHANGED
@@ -183,8 +183,13 @@ const alnumSet = [/*#__PURE__*/ range("a", "z"), /*#__PURE__*/ range("A", "Z"),
183
183
  const spaceSet = " \t"
184
184
  const multispaceSet = " \t\r\n"
185
185
 
186
- const cls = (set: unknown, min: 0 | 1, description: string, kind: ErrorKind, hint = true): Parser<string> =>
187
- takeWhileImpl<string>(set, { min }, false, `${kind.toLowerCase()}${min}`, description, kind, hint)
186
+ const cls = (
187
+ set: Token.StringTokenSet,
188
+ min: 0 | 1,
189
+ description: string,
190
+ kind: ErrorKind,
191
+ hint = true
192
+ ): Parser<string> => takeWhileImpl<string>(set, { min }, false, `${kind.toLowerCase()}${min}`, description, kind, hint)
188
193
 
189
194
  // -----------------------------------------------------------------------------
190
195
  // Character classes
@@ -359,6 +364,7 @@ export const tillLineEnding: Parser<string> = /*#__PURE__*/ P.described<string>(
359
364
  const isString = state.inputKind === 0
360
365
  let i = start
361
366
  while (i < state.end) {
367
+ // SAFETY: `Ascii` parsers run on strings or `Uint8Array`s, and `isString` is `inputKind === 0`, set only for a string
362
368
  const c = isString ? (input as string).charCodeAt(i) : (input as Uint8Array)[i]
363
369
  if (c === 10) break
364
370
  if (c === 13) {
@@ -368,6 +374,7 @@ export const tillLineEnding: Parser<string> = /*#__PURE__*/ P.described<string>(
368
374
  if (state.partial) return state.incomplete(1, expectedLineEnding)
369
375
  return state.backtrack("LineEnding", expectedLineEnding, i)
370
376
  }
377
+ // SAFETY: `Ascii` parsers run on strings or `Uint8Array`s, and `isString` is `inputKind === 0`, set only for a string
371
378
  const d = isString ? (input as string).charCodeAt(i + 1) : (input as Uint8Array)[i + 1]
372
379
  if (d === 10) break
373
380
  return state.backtrack("LineEnding", expectedLineEnding, i)
@@ -376,6 +383,7 @@ export const tillLineEnding: Parser<string> = /*#__PURE__*/ P.described<string>(
376
383
  }
377
384
  if (i >= state.end && state.partial) return state.incomplete(1, expectedLineEnding)
378
385
  state.pos = i
386
+ // SAFETY: on string input, the input type of a `Parser<string>`, the slice is a string (`bytes` retypes it for bytes)
379
387
  return state.slice(start, i) as string
380
388
  },
381
389
  "tillLineEnding",
@@ -471,7 +479,7 @@ const unsignedFloat = /*#__PURE__*/ P.alt(
471
479
  const floatText = /*#__PURE__*/ numbers.floatText(
472
480
  /*#__PURE__*/ P.taken(
473
481
  /*#__PURE__*/ P.alt(/*#__PURE__*/ literalImpl("nan", true), /*#__PURE__*/ P.seq(sign, unsignedFloat))
474
- ).pipe(/*#__PURE__*/ P.expected("number")) as Parser<string>
482
+ ).pipe(/*#__PURE__*/ P.expected("number"))
475
483
  )
476
484
 
477
485
  /** @internal */
@@ -501,6 +509,17 @@ export const float: Parser<number> = /*#__PURE__*/ floatText.pipe(
501
509
  // Literals
502
510
  // -----------------------------------------------------------------------------
503
511
 
512
+ /**
513
+ * The overloads of {@link caseless}.
514
+ *
515
+ * @since 0.5.0
516
+ * @category literals
517
+ */
518
+ export interface CaselessFn {
519
+ (literal: string): Parser<string>
520
+ (literal: Uint8Array): Parser<Uint8Array, never, never, Uint8Array>
521
+ }
522
+
504
523
  /**
505
524
  * Matches a literal ignoring ASCII case (winnow's `Caseless`, nom's
506
525
  * `tag_no_case`). Returns the input as written.
@@ -508,10 +527,7 @@ export const float: Parser<number> = /*#__PURE__*/ floatText.pipe(
508
527
  * @since 0.1.0
509
528
  * @category literals
510
529
  */
511
- export const caseless: {
512
- (literal: string): Parser<string>
513
- (literal: Uint8Array): Parser<Uint8Array, never, never, Uint8Array>
514
- } = (lit: string | Uint8Array): any => literalImpl(lit, true)
530
+ export const caseless: CaselessFn = (lit: string | Uint8Array): any => literalImpl(lit, true)
515
531
 
516
532
  // -----------------------------------------------------------------------------
517
533
  // Escapes
@@ -522,6 +538,7 @@ const controlCode = (c: string | number): number => (Predicate.isNumber(c) ? c :
522
538
  const atControl = (state: State<Input>, control: number): boolean => {
523
539
  if (state.pos >= state.end) return false
524
540
  const input = state.input
541
+ // SAFETY: escapes are read from strings or `Uint8Array`s, and `inputKind` 0 is set only for a string
525
542
  const c = state.inputKind === 0 ? (input as string).charCodeAt(state.pos) : (input as Uint8Array)[state.pos]
526
543
  return c === control
527
544
  }
@@ -559,6 +576,7 @@ export const takeEscaped = <A, E, R, I extends Input, B, E2, R2, I2 extends Inpu
559
576
  return true
560
577
  },
561
578
  escapable,
579
+ // SAFETY: the parser runs on input of type `I & I2`, and `State.slice` returns that input's own slice type
562
580
  (state, start) => state.slice(start, state.pos) as Slice<I & I2>,
563
581
  ctrl,
564
582
  undefined
@@ -593,9 +611,11 @@ export const takeEscapedImpl = <A, E, R, I extends Input, B, E2, R2, I2 extends
593
611
  const start = state.pos
594
612
  let resumed = false
595
613
  if (state.resume !== undefined) {
614
+ // SAFETY: under its own `key`, this parser saves only a resume offset (`suspendAt`) or a `Done`
596
615
  const checkpoint = Resume.take(state, key, start) as number | Resume.Done | undefined
597
616
  if (checkpoint instanceof Resume.Done) {
598
617
  state.pos = checkpoint.pos
618
+ // SAFETY: a `Done` saved under this parser's `key` holds the `S` it returned
599
619
  return checkpoint.value as S
600
620
  }
601
621
  if (checkpoint !== undefined) {
@@ -701,9 +721,11 @@ export const escapedImpl = <E, R, I extends Input, E2, R2, I2 extends Input>(
701
721
  let out = ""
702
722
  let resumed = false
703
723
  if (state.resume !== undefined) {
724
+ // SAFETY: under its own `key`, this parser saves only an `EscapedCheckpoint` (`suspendAt`) or a `Done`
704
725
  const checkpoint = Resume.take(state, key, start) as EscapedCheckpoint | Resume.Done | undefined
705
726
  if (checkpoint instanceof Resume.Done) {
706
727
  state.pos = checkpoint.pos
728
+ // SAFETY: a `Done` saved under this parser's `key` holds the string it returned
707
729
  return checkpoint.value as string
708
730
  }
709
731
  if (checkpoint !== undefined) {
@@ -754,6 +776,14 @@ type Bytes<P> =
754
776
  ? Parser<A extends string ? Uint8Array : A, E, R, Uint8Array>
755
777
  : never
756
778
 
779
+ /**
780
+ * Gives a value the type of another view of the same parsers (see
781
+ * {@link bytes}).
782
+ */
783
+ const retype = <T>(value: unknown): T =>
784
+ // SAFETY: callers pass the byte views' parsers, which are the string parsers themselves (below)
785
+ value as T
786
+
757
787
  /**
758
788
  * The parsers of this module, typed for `Uint8Array` input. Slices are
759
789
  * returned as `Uint8Array`s.
@@ -803,7 +833,7 @@ export const bytes: {
803
833
  const lit = (s: string) => Token.literal(new TextEncoder().encode(s))
804
834
  const crlfB = lit("\r\n")
805
835
  const newlineB = lit("\n")
806
- return {
836
+ const views = {
807
837
  alpha0,
808
838
  alpha1,
809
839
  digit0,
@@ -829,5 +859,8 @@ export const bytes: {
829
859
  decBigInt,
830
860
  hexUint,
831
861
  float
832
- } as any
862
+ }
863
+ // SAFETY: the string parsers run on byte input unchanged (their slices of a `Uint8Array` are `Uint8Array`s),
864
+ // so only their declared input and slice types differ from the byte views'
865
+ return retype<typeof bytes>(views)
833
866
  })()