@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
@@ -1 +1 @@
1
- {"version":3,"file":"ParseError.js","names":[],"sources":["../src/ParseError.ts"],"sourcesContent":["/**\n * The error type produced when running a parser.\n *\n * `ParseError` merges winnow's `ContextError`/`ParseError` and nom's\n * `VerboseError`. It records where parsing failed, what was expected there,\n * the context labels that were active, and an optional typed `cause`\n * produced by `Parser.fail`, `Parser.tryMap` and friends. Its `message`\n * shows the failing position in the input:\n *\n * ```text\n * Parse error at line 1, column 4:\n * 1 | [1,,2]\n * | ^\n * expected digit\n * ```\n *\n * `ParseError` is a `Data.TaggedError`, so it can be yielded directly inside\n * `Effect.gen`.\n *\n * @since 0.1.0\n */\nimport * as Arr from \"effect/Array\"\nimport * as Predicate from \"effect/Predicate\"\nimport * as Data from \"effect/Data\"\nimport * as Option from \"effect/Option\"\nimport * as Result from \"effect/Result\"\nimport type { Encoding } from \"./Encoding.js\"\nimport type { ErrMode, Failure, Input } from \"./Input.js\"\nimport * as text from \"./internal/text.js\"\n\n/**\n * The kind of parser that produced an error, in the spirit of nom's\n * `ErrorKind`.\n *\n * `\"TooDeep\"` is not produced by a parser: the runners report it when\n * deeply nested input exhausts the call stack (see `Parser.suspend`).\n *\n * @since 0.1.0\n * @category models\n */\nexport type ErrorKind =\n | \"Alpha\"\n | \"AlphaNumeric\"\n | \"Alt\"\n | \"Assert\"\n | \"Bits\"\n | \"Complete\"\n | \"CrLf\"\n | \"Digit\"\n | \"Dispatch\"\n | \"Eof\"\n | \"Escaped\"\n | \"Fail\"\n | \"Float\"\n | \"HexDigit\"\n | \"Incomplete\"\n | \"LineEnding\"\n | \"Literal\"\n | \"Many\"\n | \"MultiSpace\"\n | \"NoneOf\"\n | \"Not\"\n | \"OctDigit\"\n | \"OneOf\"\n | \"Permutation\"\n | \"Separated\"\n | \"Slice\"\n | \"Space\"\n | \"Take\"\n | \"TakeUntil\"\n | \"TakeWhile\"\n | \"Token\"\n | \"TooDeep\"\n | \"Verify\"\n\n/**\n * @since 0.1.0\n * @category type ids\n */\nexport const TypeId = \"~effect-parse/ParseError\" as const\n\n/**\n * An error produced by running a parser.\n *\n * @since 0.1.0\n * @category models\n */\nexport class ParseError<out E = never>\n extends /*#__PURE__*/ Data.TaggedError(\"ParseError\")<{\n /** The input that was being parsed. */\n readonly input: Input\n /** The offset of the failure in the input. */\n readonly offset: number\n /** The kind of parser that failed. */\n readonly kind: ErrorKind\n /** How the error propagated before parsing stopped. */\n readonly mode: ErrMode\n /** Descriptions of what was expected at `offset`. */\n readonly expected: ReadonlyArray<string>\n /** Context labels (`Parser.context`), innermost first. */\n readonly context: ReadonlyArray<string>\n /** The user supplied cause, if any. */\n readonly cause: E | undefined\n /** An optional free-form description. */\n readonly description: string | undefined\n /**\n * For byte inputs parsed by `Text` parsers, the text encoding. Errors\n * then show the input as text, with line and column numbers.\n */\n readonly encoding?: Encoding<Uint8Array> | undefined\n }>\n{\n /**\n * @since 0.1.0\n */\n readonly [TypeId]: typeof TypeId = TypeId\n\n /**\n * The 1-based line and column of the failure (for strings and encoded\n * text; for other inputs the line is 1 and the column is `offset + 1`).\n *\n * @since 0.1.0\n */\n get position(): LineColumn {\n return lineColumn(this.input, this.offset, this.encoding)\n }\n\n /**\n * The rendered, human-readable error message.\n *\n * @since 0.1.0\n */\n override get message(): string {\n return render(this)\n }\n\n /**\n * @since 0.1.0\n */\n override toString(): string {\n return `ParseError: ${this.message}`\n }\n}\n\n/**\n * @since 0.1.0\n * @category guards\n */\nexport const isParseError = (u: unknown): u is ParseError<unknown> => Predicate.isObjectOrArray(u) && TypeId in u\n\n/**\n * Builds a `ParseError` from the failure details recorded while parsing.\n *\n * @since 0.1.0\n * @category constructors\n */\nexport const fromFailure = <E = never>(\n input: Input,\n failure: Failure,\n mode: ErrMode,\n encoding?: Encoding<any>\n): ParseError<E> =>\n new ParseError<E>({\n input,\n offset: failure.offset,\n kind: failure.kind,\n mode,\n expected: failure.expected,\n context: failure.context,\n cause: failure.hasCause ? (failure.cause as E) : undefined,\n description: failure.message,\n encoding: input instanceof Uint8Array ? encoding : undefined\n })\n\n/**\n * The user supplied cause of an error, if any.\n *\n * @since 0.1.0\n * @category getters\n */\nexport const getCause = <E>(self: ParseError<E>): Option.Option<E> =>\n self.cause === undefined ? Option.none() : Option.some(self.cause)\n\n/**\n * A 1-based line/column position.\n *\n * @since 0.1.0\n * @category models\n */\nexport interface LineColumn {\n readonly line: number\n readonly column: number\n}\n\n/**\n * Computes the 1-based line and column (in code points) of an offset. Lines\n * are separated by `\\n`. Byte inputs are read as text when an `encoding`\n * is given. For other inputs the line is always 1 and the column is\n * `offset + 1`.\n *\n * @since 0.1.0\n * @category utils\n */\nexport const lineColumn = (input: Input, offset: number, encoding?: Encoding<any>): LineColumn => {\n if (encoding !== undefined && input instanceof Uint8Array) {\n let line = 1\n let column = 1\n text.walk(encoding, input, 0, Math.min(offset, input.length), (cp) => {\n if (cp === 10) {\n line++\n column = 1\n } else {\n column++\n }\n })\n return { line, column }\n }\n if (!Predicate.isString(input)) return { line: 1, column: offset + 1 }\n let line = 1\n let lineStart = 0\n for (let i = 0; i < offset && i < input.length; i++) {\n if (input.charCodeAt(i) === 10) {\n line++\n lineStart = i + 1\n }\n }\n return { line, column: codePointCount(input, lineStart, Math.min(offset, input.length)) + 1 }\n}\n\nconst codePointCount = (s: string, start: number, end: number): number => {\n let n = 0\n for (let i = start; i < end; i++) {\n const c = s.charCodeAt(i)\n if (c >= 0xd800 && c <= 0xdbff && i + 1 < end) {\n const d = s.charCodeAt(i + 1)\n if (d >= 0xdc00 && d <= 0xdfff) i++\n }\n n++\n }\n return n\n}\n\n/**\n * Formats a list of expectations: `a`, `a or b`, `a, b or c`.\n *\n * @since 0.1.0\n * @category utils\n */\nexport const formatExpected = (expected: ReadonlyArray<string>): string => {\n if (Arr.isReadonlyArrayEmpty(expected)) return \"\"\n if (expected.length === 1) return expected[0]\n return `${expected.slice(0, -1).join(\", \")} or ${expected[expected.length - 1]}`\n}\n\nconst hexBytes = (bytes: Uint8Array): string =>\n Array.from(bytes, (b) => `0x${b.toString(16).padStart(2, \"0\")}`).join(\" \")\n\nconst describeFound = (input: Input, offset: number, encoding: Encoding<any> | undefined): string => {\n if (offset >= input.length) return \"end of input\"\n if (encoding !== undefined && input instanceof Uint8Array) {\n const cp = encoding.decode(input, offset, input.length)\n if (cp >= 0) return JSON.stringify(String.fromCodePoint(cp))\n const bad = input.subarray(offset, Math.min(input.length, offset + Math.max(encoding.unit, 1)))\n return cp === text.Truncated\n ? `incomplete ${encoding.name} sequence ${hexBytes(input.subarray(offset))}`\n : `invalid ${encoding.name} ${hexBytes(bad)}`\n }\n if (Predicate.isString(input)) {\n const cp = input.codePointAt(offset) ?? Number.NaN\n return JSON.stringify(String.fromCodePoint(cp))\n }\n if (input instanceof Uint8Array) {\n return `0x${input[offset].toString(16).padStart(2, \"0\")}`\n }\n return inspectToken(input[offset])\n}\n\n/** @internal */\nexport const inspectToken = (u: unknown): string => {\n if (Predicate.isString(u)) return JSON.stringify(u)\n if (Predicate.isObjectOrArray(u)) {\n // `JSON.stringify` throws on cycles and `BigInt`s. Fall back to what\n // `String` gives an array (its elements joined) or an object's tag\n // (`[object Map]`), never a user `toString` that might throw in turn.\n return Result.getOrElse(\n Result.try(() => JSON.stringify(u)),\n () => (Array.isArray(u) ? u.join(\",\") : Object.prototype.toString.call(u))\n )\n }\n return String(u)\n}\n\nconst causeMessage = (cause: unknown): string | undefined => {\n if (cause === undefined) return undefined\n if (Predicate.isString(cause)) return cause\n // An `Error`'s message, or any other object's string `message`\n if (Predicate.isObjectOrArray(cause) && \"message\" in cause && Predicate.isString(cause.message)) {\n return cause.message\n }\n return inspectToken(cause)\n}\n\nconst renderSnippet = (input: Input, offset: number, encoding: Encoding<any> | undefined): Array<string> => {\n if (encoding !== undefined && input instanceof Uint8Array) {\n // Find the line containing `offset`, then decode it\n let lineStart = 0\n let end = input.length\n let column = 1\n text.walk(encoding, input, 0, input.length, (cp, i, w) => {\n if (i >= offset && cp === 10) {\n end = i\n return false\n }\n if (i < offset) {\n if (cp === 10) {\n lineStart = i + w\n column = 1\n } else {\n column++\n }\n }\n })\n let line = text.lenientText(encoding, input, lineStart, end)\n if (line.endsWith(\"\\r\")) line = line.slice(0, -1)\n const gutter = String(lineColumn(input, offset, encoding).line)\n const pad = \" \".repeat(gutter.length)\n return [`${gutter} | ${line}`, `${pad} | ${\" \".repeat(column - 1)}^`]\n }\n if (Predicate.isString(input)) {\n const { column, line } = lineColumn(input, offset)\n let start = offset\n while (start > 0 && input.charCodeAt(start - 1) !== 10) start--\n let end = offset\n while (end < input.length && input.charCodeAt(end) !== 10) end++\n let text = input.slice(start, end)\n if (text.endsWith(\"\\r\")) text = text.slice(0, -1)\n const gutter = String(line)\n const pad = \" \".repeat(gutter.length)\n return [`${gutter} | ${text}`, `${pad} | ${\" \".repeat(column - 1)}^`]\n }\n if (input instanceof Uint8Array) {\n const start = Math.max(0, offset - 8)\n const end = Math.min(input.length, offset + 8)\n const bytes: Array<string> = []\n for (let i = start; i < end; i++) bytes.push(input[i].toString(16).padStart(2, \"0\"))\n const caret = (offset - start) * 3\n return [`${start.toString(16).padStart(8, \"0\")} | ${bytes.join(\" \")}`, `${\" \".repeat(8)} | ${\" \".repeat(caret)}^`]\n }\n return []\n}\n\nconst render = (error: ParseError<unknown>): string => {\n const { encoding, input, offset } = error\n const lines: Array<string> = []\n if (Predicate.isString(input)) {\n const { column, line } = lineColumn(input, offset)\n lines.push(`Parse error at line ${line}, column ${column}:`)\n } else if (encoding !== undefined) {\n const { column, line } = lineColumn(input, offset, encoding)\n lines.push(`Parse error at line ${line}, column ${column} (byte ${offset}):`)\n } else {\n lines.push(`Parse error at offset ${offset}:`)\n }\n lines.push(...renderSnippet(input, offset, encoding))\n for (let i = error.context.length - 1; i >= 0; i--) {\n lines.push(`while parsing ${error.context[i]}`)\n }\n const cause = causeMessage(error.cause)\n if (cause !== undefined) lines.push(cause)\n if (error.description !== undefined) lines.push(error.description)\n if (error.mode === \"Incomplete\") {\n lines.push(\"unexpected end of input (incomplete)\")\n } else if (Arr.isReadonlyArrayNonEmpty(error.expected)) {\n lines.push(`expected ${formatExpected(error.expected)}, found ${describeFound(input, offset, encoding)}`)\n } else if (cause === undefined && error.description === undefined) {\n lines.push(`unexpected ${describeFound(input, offset, encoding)} (${error.kind})`)\n }\n return lines.join(\"\\n\")\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ParseError.js","names":[],"sources":["../src/ParseError.ts"],"sourcesContent":["/**\n * The error type produced when running a parser.\n *\n * `ParseError` merges winnow's `ContextError`/`ParseError` and nom's\n * `VerboseError`. It records where parsing failed, what was expected there,\n * the context labels that were active, and an optional typed `cause`\n * produced by `Parser.fail`, `Parser.tryMap` and friends. Its `message`\n * shows the failing position in the input:\n *\n * ```text\n * Parse error at line 1, column 4:\n * 1 | [1,,2]\n * | ^\n * expected digit\n * ```\n *\n * `ParseError` is a `Data.TaggedError`, so it can be yielded directly inside\n * `Effect.gen`.\n *\n * @since 0.1.0\n */\nimport * as Arr from \"effect/Array\"\nimport * as Predicate from \"effect/Predicate\"\nimport * as Data from \"effect/Data\"\nimport * as Option from \"effect/Option\"\nimport * as Result from \"effect/Result\"\nimport type { Encoding } from \"./Encoding.js\"\nimport type { ErrMode, Failure, Input } from \"./Input.js\"\nimport * as text from \"./internal/text.js\"\n\n/**\n * The kind of parser that produced an error, in the spirit of nom's\n * `ErrorKind`.\n *\n * `\"TooDeep\"` is not produced by a parser: the runners report it when\n * deeply nested input exhausts the call stack (see `Parser.suspend`).\n *\n * @since 0.1.0\n * @category models\n */\nexport type ErrorKind =\n | \"Alpha\"\n | \"AlphaNumeric\"\n | \"Alt\"\n | \"Assert\"\n | \"Bits\"\n | \"Complete\"\n | \"CrLf\"\n | \"Digit\"\n | \"Dispatch\"\n | \"Eof\"\n | \"Escaped\"\n | \"Fail\"\n | \"Float\"\n | \"HexDigit\"\n | \"Incomplete\"\n | \"LineEnding\"\n | \"Literal\"\n | \"Many\"\n | \"MultiSpace\"\n | \"NoneOf\"\n | \"Not\"\n | \"OctDigit\"\n | \"OneOf\"\n | \"Permutation\"\n | \"Separated\"\n | \"Slice\"\n | \"Space\"\n | \"Take\"\n | \"TakeUntil\"\n | \"TakeWhile\"\n | \"Token\"\n | \"TooDeep\"\n | \"Verify\"\n\n/**\n * @since 0.1.0\n * @category type ids\n */\nexport const TypeId = \"~effect-parse/ParseError\" as const\n\n/**\n * An error produced by running a parser.\n *\n * @since 0.1.0\n * @category models\n */\nexport class ParseError<out E = never>\n extends /*#__PURE__*/ Data.TaggedError(\"ParseError\")<{\n /** The input that was being parsed. */\n readonly input: Input\n /** The offset of the failure in the input. */\n readonly offset: number\n /** The kind of parser that failed. */\n readonly kind: ErrorKind\n /** How the error propagated before parsing stopped. */\n readonly mode: ErrMode\n /** Descriptions of what was expected at `offset`. */\n readonly expected: ReadonlyArray<string>\n /** Context labels (`Parser.context`), innermost first. */\n readonly context: ReadonlyArray<string>\n /** The user supplied cause, if any. */\n readonly cause: E | undefined\n /** An optional free-form description. */\n readonly description: string | undefined\n /**\n * For byte inputs parsed by `Text` parsers, the text encoding. Errors\n * then show the input as text, with line and column numbers.\n */\n readonly encoding?: Encoding<Uint8Array> | undefined\n }>\n{\n /**\n * @since 0.1.0\n */\n readonly [TypeId]: typeof TypeId = TypeId\n\n /**\n * The 1-based line and column of the failure (for strings and encoded\n * text; for other inputs the line is 1 and the column is `offset + 1`).\n *\n * @since 0.1.0\n */\n get position(): LineColumn {\n return lineColumn(this.input, this.offset, this.encoding)\n }\n\n /**\n * The rendered, human-readable error message.\n *\n * @since 0.1.0\n */\n override get message(): string {\n return render(this)\n }\n\n /**\n * @since 0.1.0\n */\n override toString(): string {\n return `ParseError: ${this.message}`\n }\n}\n\n/**\n * @since 0.1.0\n * @category guards\n */\nexport const isParseError = (u: unknown): u is ParseError<unknown> => Predicate.isObjectOrArray(u) && TypeId in u\n\n/**\n * Builds a `ParseError` from the failure details recorded while parsing.\n *\n * @since 0.1.0\n * @category constructors\n */\nexport const fromFailure = <E = never>(\n input: Input,\n failure: Failure,\n mode: ErrMode,\n encoding?: Encoding<any>\n): ParseError<E> =>\n new ParseError<E>({\n input,\n offset: failure.offset,\n kind: failure.kind,\n mode,\n expected: failure.expected,\n context: failure.context,\n // SAFETY: `E` is the user error type of the parser whose run recorded\n // `failure`; a failure with `hasCause` carries a cause raised by that\n // parser's `fail` / `mapError`\n cause: failure.hasCause ? (failure.cause as E) : undefined,\n description: failure.message,\n encoding: input instanceof Uint8Array ? encoding : undefined\n })\n\n/**\n * The user supplied cause of an error, if any.\n *\n * @since 0.1.0\n * @category getters\n */\nexport const getCause = <E>(self: ParseError<E>): Option.Option<E> =>\n self.cause === undefined ? Option.none() : Option.some(self.cause)\n\n/**\n * A 1-based line/column position.\n *\n * @since 0.1.0\n * @category models\n */\nexport interface LineColumn {\n readonly line: number\n readonly column: number\n}\n\n/**\n * Computes the 1-based line and column (in code points) of an offset. Lines\n * are separated by `\\n`. Byte inputs are read as text when an `encoding`\n * is given. For other inputs the line is always 1 and the column is\n * `offset + 1`.\n *\n * @since 0.1.0\n * @category utils\n */\nexport const lineColumn = (input: Input, offset: number, encoding?: Encoding<any>): LineColumn => {\n if (encoding !== undefined && input instanceof Uint8Array) {\n let line = 1\n let column = 1\n text.walk(encoding, input, 0, Math.min(offset, input.length), (cp) => {\n if (cp === 10) {\n line++\n column = 1\n } else {\n column++\n }\n })\n return { line, column }\n }\n if (!Predicate.isString(input)) return { line: 1, column: offset + 1 }\n let line = 1\n let lineStart = 0\n for (let i = 0; i < offset && i < input.length; i++) {\n if (input.charCodeAt(i) === 10) {\n line++\n lineStart = i + 1\n }\n }\n return { line, column: codePointCount(input, lineStart, Math.min(offset, input.length)) + 1 }\n}\n\nconst codePointCount = (s: string, start: number, end: number): number => {\n let n = 0\n for (let i = start; i < end; i++) {\n const c = s.charCodeAt(i)\n if (c >= 0xd800 && c <= 0xdbff && i + 1 < end) {\n const d = s.charCodeAt(i + 1)\n if (d >= 0xdc00 && d <= 0xdfff) i++\n }\n n++\n }\n return n\n}\n\n/**\n * Formats a list of expectations: `a`, `a or b`, `a, b or c`.\n *\n * @since 0.1.0\n * @category utils\n */\nexport const formatExpected = (expected: ReadonlyArray<string>): string => {\n if (Arr.isReadonlyArrayEmpty(expected)) return \"\"\n if (expected.length === 1) return expected[0]\n return `${expected.slice(0, -1).join(\", \")} or ${expected[expected.length - 1]}`\n}\n\nconst hexBytes = (bytes: Uint8Array): string =>\n Array.from(bytes, (b) => `0x${b.toString(16).padStart(2, \"0\")}`).join(\" \")\n\nconst describeFound = (input: Input, offset: number, encoding: Encoding<any> | undefined): string => {\n if (offset >= input.length) return \"end of input\"\n if (encoding !== undefined && input instanceof Uint8Array) {\n const cp = encoding.decode(input, offset, input.length)\n if (cp >= 0) return JSON.stringify(String.fromCodePoint(cp))\n const bad = input.subarray(offset, Math.min(input.length, offset + Math.max(encoding.unit, 1)))\n return cp === text.Truncated\n ? `incomplete ${encoding.name} sequence ${hexBytes(input.subarray(offset))}`\n : `invalid ${encoding.name} ${hexBytes(bad)}`\n }\n if (Predicate.isString(input)) {\n const cp = input.codePointAt(offset) ?? Number.NaN\n return JSON.stringify(String.fromCodePoint(cp))\n }\n if (input instanceof Uint8Array) {\n return `0x${input[offset].toString(16).padStart(2, \"0\")}`\n }\n return inspectToken(input[offset])\n}\n\n/** @internal */\nexport const inspectToken = (u: unknown): string => {\n if (Predicate.isString(u)) return JSON.stringify(u)\n if (Predicate.isObjectOrArray(u)) {\n // `JSON.stringify` throws on cycles and `BigInt`s. Fall back to what\n // `String` gives an array (its elements joined) or an object's tag\n // (`[object Map]`), never a user `toString` that might throw in turn.\n return Result.getOrElse(\n Result.try(() => JSON.stringify(u)),\n () => (Array.isArray(u) ? u.join(\",\") : Object.prototype.toString.call(u))\n )\n }\n return String(u)\n}\n\nconst causeMessage = (cause: unknown): string | undefined => {\n if (cause === undefined) return undefined\n if (Predicate.isString(cause)) return cause\n // An `Error`'s message, or any other object's string `message`\n if (Predicate.isObjectOrArray(cause) && \"message\" in cause && Predicate.isString(cause.message)) {\n return cause.message\n }\n return inspectToken(cause)\n}\n\nconst renderSnippet = (input: Input, offset: number, encoding: Encoding<any> | undefined): Array<string> => {\n if (encoding !== undefined && input instanceof Uint8Array) {\n // Find the line containing `offset`, then decode it\n let lineStart = 0\n let end = input.length\n let column = 1\n text.walk(encoding, input, 0, input.length, (cp, i, w) => {\n if (i >= offset && cp === 10) {\n end = i\n return false\n }\n if (i < offset) {\n if (cp === 10) {\n lineStart = i + w\n column = 1\n } else {\n column++\n }\n }\n })\n let line = text.lenientText(encoding, input, lineStart, end)\n if (line.endsWith(\"\\r\")) line = line.slice(0, -1)\n const gutter = String(lineColumn(input, offset, encoding).line)\n const pad = \" \".repeat(gutter.length)\n return [`${gutter} | ${line}`, `${pad} | ${\" \".repeat(column - 1)}^`]\n }\n if (Predicate.isString(input)) {\n const { column, line } = lineColumn(input, offset)\n let start = offset\n while (start > 0 && input.charCodeAt(start - 1) !== 10) start--\n let end = offset\n while (end < input.length && input.charCodeAt(end) !== 10) end++\n let text = input.slice(start, end)\n if (text.endsWith(\"\\r\")) text = text.slice(0, -1)\n const gutter = String(line)\n const pad = \" \".repeat(gutter.length)\n return [`${gutter} | ${text}`, `${pad} | ${\" \".repeat(column - 1)}^`]\n }\n if (input instanceof Uint8Array) {\n const start = Math.max(0, offset - 8)\n const end = Math.min(input.length, offset + 8)\n const bytes: Array<string> = []\n for (let i = start; i < end; i++) bytes.push(input[i].toString(16).padStart(2, \"0\"))\n const caret = (offset - start) * 3\n return [`${start.toString(16).padStart(8, \"0\")} | ${bytes.join(\" \")}`, `${\" \".repeat(8)} | ${\" \".repeat(caret)}^`]\n }\n return []\n}\n\nconst render = (error: ParseError<unknown>): string => {\n const { encoding, input, offset } = error\n const lines: Array<string> = []\n if (Predicate.isString(input)) {\n const { column, line } = lineColumn(input, offset)\n lines.push(`Parse error at line ${line}, column ${column}:`)\n } else if (encoding !== undefined) {\n const { column, line } = lineColumn(input, offset, encoding)\n lines.push(`Parse error at line ${line}, column ${column} (byte ${offset}):`)\n } else {\n lines.push(`Parse error at offset ${offset}:`)\n }\n lines.push(...renderSnippet(input, offset, encoding))\n for (let i = error.context.length - 1; i >= 0; i--) {\n lines.push(`while parsing ${error.context[i]}`)\n }\n const cause = causeMessage(error.cause)\n if (cause !== undefined) lines.push(cause)\n if (error.description !== undefined) lines.push(error.description)\n if (error.mode === \"Incomplete\") {\n lines.push(\"unexpected end of input (incomplete)\")\n } else if (Arr.isReadonlyArrayNonEmpty(error.expected)) {\n lines.push(`expected ${formatExpected(error.expected)}, found ${describeFound(input, offset, encoding)}`)\n } else if (cause === undefined && error.description === undefined) {\n lines.push(`unexpected ${describeFound(input, offset, encoding)} (${error.kind})`)\n }\n return lines.join(\"\\n\")\n}\n"],"mappings":"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"}
package/dist/Parser.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import * as Result from "effect/Result";
2
- import { Fail, Input, Slice, Source, State, TraceEvent } from "./Input.js";
2
+ import { ErrMode, Fail, Input, Slice, Source, State, TraceEvent } from "./Input.js";
3
3
  import * as Option from "effect/Option";
4
4
  import * as Context from "effect/Context";
5
5
  import * as Effect from "effect/Effect";
6
6
  import { Pipeable } from "effect/Pipeable";
7
7
  import * as ParseError from "./ParseError.js";
8
8
  import { ErrorKind } from "./ParseError.js";
9
- import { Node } from "./internal/node.js";
9
+ import { Defer as Defer$1, Node } from "./internal/node.js";
10
10
  import { Contravariant, Covariant, Simplify } from "effect/Types";
11
11
  /**
12
12
  * @since 0.1.0
@@ -90,6 +90,13 @@ export declare namespace Parser {
90
90
  * @since 0.1.0
91
91
  */
92
92
  type InputOf<P> = [P] extends [never] ? Input : [P] extends [Parser<infer _A, infer _E, infer _R, infer I>] ? I : never;
93
+ /**
94
+ * The steps {@link combinator}'s `build` receives: one per parser, in
95
+ * order, each returning its parser's output or `Fail`.
96
+ *
97
+ * @since 0.5.0
98
+ */
99
+ type Steps<Ps extends ReadonlyArray<Any>> = { readonly [K in keyof Ps]: (state: State<InputOf<Ps[number]>>) => Success<Ps[K]> | Fail; };
93
100
  }
94
101
  /**
95
102
  * A repetition range, in the spirit of winnow's `impl Into<Range>`:
@@ -171,6 +178,51 @@ export declare const make: <A, E = never, R = never, I extends Input = string>(s
171
178
  * @internal
172
179
  */
173
180
  export declare const described: <A, E = never, R = never, I extends Input = string>(step: (state: State<I>) => A | Fail, name: string | undefined, node: Node) => Parser<A, E, R, I>;
181
+ /**
182
+ * Creates a combinator over `parsers` that compiles: `build` makes the
183
+ * combinator's step from the parsers' steps. Write combinators with it
184
+ * rather than with {@link make} when they run other parsers: a `make`
185
+ * parser is opaque to the compilers, so in a compiled grammar it runs
186
+ * interpreted, and so does every parser it runs. Interpreted, `build`
187
+ * receives the parsers' own steps; compiled (see the `Compiler` module), it
188
+ * receives their compiled steps, so the parsers inside compile with the
189
+ * grammar.
190
+ *
191
+ * Each step runs its parser on the state it is given, as `Parser.run` does,
192
+ * and returns the parser's output or `Fail`. The steps must run on the
193
+ * combinator's own state (they are compiled for its input kind): a
194
+ * combinator that runs a parser on another input, as {@link mapParser}
195
+ * does, is written with `make`. `build` may be called more than once (once
196
+ * interpreted, and once for each compiled build), so state its step shares
197
+ * between calls belongs inside `build`.
198
+ *
199
+ * @example
200
+ * ```ts
201
+ * import { Ascii, Input, Parser, Token } from "@thomasfosterau/effect-parse"
202
+ *
203
+ * // One or more `item`s separated by `sep`, returning their count
204
+ * const count = <A, B>(item: Parser.Parser<A>, sep: Parser.Parser<B>) =>
205
+ * Parser.combinator([item, sep], ([itemStep, sepStep]) => (state) => {
206
+ * if (itemStep(state) === Input.Fail) return Input.Fail
207
+ * let n = 1
208
+ * while (true) {
209
+ * const start = state.pos
210
+ * if (sepStep(state) === Input.Fail || itemStep(state) === Input.Fail) {
211
+ * if (state.mode !== "Backtrack") return Input.Fail
212
+ * state.rewind(start)
213
+ * return n
214
+ * }
215
+ * n++
216
+ * }
217
+ * })
218
+ *
219
+ * Parser.parse(count(Ascii.digit1, Token.literal(",")), "1,22,333") // Result.succeed(3)
220
+ * ```
221
+ *
222
+ * @since 0.5.0
223
+ * @category constructors
224
+ */
225
+ export declare const combinator: <const Ps extends ReadonlyArray<Parser.Any>, A, E = never>(parsers: Ps, build: (steps: Parser.Steps<Ps>) => (state: State<Parser.InputOf<Ps[number]>>) => A | Fail, name?: string) => Parser<A, E | Parser.Error<Ps[number]>, Parser.Services<Ps[number]>, Parser.InputOf<Ps[number]>>;
174
226
  /**
175
227
  * Gives a parser a name, used by `toString`.
176
228
  *
@@ -218,6 +270,34 @@ export declare const void_: Parser<void, never, never, Input>;
218
270
  * @category constructors
219
271
  */
220
272
  export declare const fail: <E>(error: E) => Parser<never, E, never, Input>;
273
+ /**
274
+ * A parser that fails (backtracks) with the given user error, reporting it
275
+ * at `offset` rather than where the parser runs. Use it for a check that
276
+ * can only run once a whole construct has parsed but should point at the
277
+ * part at fault: return it from a {@link flatMap} continuation, with an
278
+ * offset taken from {@link location} or {@link withSpan}. Like any failure,
279
+ * one at a later offset is preferred over the failures of other
280
+ * alternatives (the furthest failure wins). The offset is clamped to the
281
+ * input.
282
+ *
283
+ * @example
284
+ * ```ts
285
+ * import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
286
+ *
287
+ * const tag = (open: string) => Parser.delimited(Token.literal(open), Ascii.alpha1, Token.literal(">"))
288
+ * const element = Parser.seq(tag("<"), Parser.location, tag("</")).pipe(
289
+ * Parser.flatMap(([start, at, end]) =>
290
+ * start === end ? Parser.succeed(start) : Parser.failAt(at, `expected </${start}>`)
291
+ * )
292
+ * )
293
+ * // The error points at the end tag (offset 3), not at the start of the element
294
+ * Parser.parse(element, "<a></b>")
295
+ * ```
296
+ *
297
+ * @since 0.5.0
298
+ * @category constructors
299
+ */
300
+ export declare const failAt: <E>(offset: number, error: E) => Parser<never, E, never, Input>;
221
301
  /**
222
302
  * A parser that always fails (backtracks) without a cause. This is winnow's
223
303
  * `fail` and nom's `fail()`.
@@ -398,6 +478,40 @@ export declare const tryMap: {
398
478
  <A, B, E2>(f: (a: A) => Result.Result<B, E2>): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<B, E | E2, R, I>;
399
479
  <A, E, R, I extends Input, B, E2>(self: Parser<A, E, R, I>, f: (a: A) => Result.Result<B, E2>): Parser<B, E | E2, R, I>;
400
480
  };
481
+ /**
482
+ * Transforms the output of a parser with a function that returns
483
+ * `Input.Fail` to reject it: the allocation-free form of {@link tryMap} and
484
+ * {@link filterMap}, for checks that run on nearly every token. Compiled
485
+ * code compares the result with the sentinel instead of allocating and
486
+ * unwrapping a `Result` or an `Option` on every success.
487
+ *
488
+ * On failure the parser backtracks to where it started. With `orFailWith`,
489
+ * the user error it builds (only on failure) becomes the `cause` of the
490
+ * `ParseError`, as with `tryMap`; without, the failure has no cause, as
491
+ * with `filterMap`.
492
+ *
493
+ * @example
494
+ * ```ts
495
+ * import { Ascii, Input, Parser } from "@thomasfosterau/effect-parse"
496
+ *
497
+ * const byte = Ascii.decUint.pipe(
498
+ * Parser.mapOrFail(
499
+ * (n) => (n < 256 ? n : Input.Fail),
500
+ * (n) => `${n} is not a byte`
501
+ * )
502
+ * )
503
+ * Parser.parse(byte, "300") // fails with the cause "300 is not a byte"
504
+ * ```
505
+ *
506
+ * @since 0.5.0
507
+ * @category mapping
508
+ */
509
+ export declare const mapOrFail: {
510
+ <A, B>(f: (a: A) => B | Fail): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<Exclude<B, Fail>, E, R, I>;
511
+ <A, B, E2>(f: (a: A) => B | Fail, orFailWith: (a: A) => E2): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<Exclude<B, Fail>, E | E2, R, I>;
512
+ <A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, f: (a: A) => B | Fail): Parser<Exclude<B, Fail>, E, R, I>;
513
+ <A, E, R, I extends Input, B, E2>(self: Parser<A, E, R, I>, f: (a: A) => B | Fail, orFailWith: (a: A) => E2): Parser<Exclude<B, Fail>, E | E2, R, I>;
514
+ };
401
515
  /**
402
516
  * Like {@link tryMap}, but the function may throw. Thrown values become the
403
517
  * `cause` of the error.
@@ -479,6 +593,28 @@ export declare const span: <A, E, R, I extends Input>(self: Parser<A, E, R, I>)
479
593
  * @category consumed input
480
594
  */
481
595
  export declare const withSpan: <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<[output: A, span: Span], E, R, I>;
596
+ /**
597
+ * Transforms the output of a parser together with the offsets it consumed,
598
+ * `[start, end)`: the allocation-free spelling of
599
+ * `map(withSpan(p), ([a, span]) => f(a, span.start, span.end))`, which
600
+ * builds a tuple and a span object on every success. Compiled code passes
601
+ * the offsets to `f` directly.
602
+ *
603
+ * @example
604
+ * ```ts
605
+ * import { Ascii, Parser } from "@thomasfosterau/effect-parse"
606
+ *
607
+ * const name = Ascii.alpha1.pipe(Parser.mapSpan((text, start, end) => ({ text, start, end })))
608
+ * Parser.parse(name, "abc") // Result.succeed({ text: "abc", start: 0, end: 3 })
609
+ * ```
610
+ *
611
+ * @since 0.5.0
612
+ * @category consumed input
613
+ */
614
+ export declare const mapSpan: {
615
+ <A, B>(f: (a: A, start: number, end: number) => B): <E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<B, E, R, I>;
616
+ <A, E, R, I extends Input, B>(self: Parser<A, E, R, I>, f: (a: A, start: number, end: number) => B): Parser<B, E, R, I>;
617
+ };
482
618
  /**
483
619
  * Commits to the current branch: recoverable failures of the parser become
484
620
  * unrecoverable, so enclosing `alt`, `opt`, `repeat`, ... do not try
@@ -537,6 +673,146 @@ export declare const expected: {
537
673
  (description: string): <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>;
538
674
  <A, E, R, I extends Input>(self: Parser<A, E, R, I>, description: string): Parser<A, E, R, I>;
539
675
  };
676
+ /**
677
+ * Runs a parser without letting it add to the expectations of later errors
678
+ * (chumsky's `quiet`). Use it on skippers, such as whitespace and comments,
679
+ * that may appear between any two tokens: they stop by failing, and without
680
+ * `quiet` what they would have accepted (`" "`, `"(:"`, ...) is listed in
681
+ * every error raised after them.
682
+ *
683
+ * When the parser succeeds, the hints and the furthest failure it recorded
684
+ * are forgotten, as after a lookahead that succeeded. When it fails
685
+ * recoverably without consuming input, its failure expects nothing, so an
686
+ * enclosing `alt` or `opt` reports only the other alternatives. A failure
687
+ * after consuming input (an unterminated comment) or an unrecoverable one
688
+ * is kept as it is. `Parser.expected` cannot do this: it relabels a failure,
689
+ * and a skipper that matches zero or more times never fails.
690
+ *
691
+ * @example
692
+ * ```ts
693
+ * import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
694
+ *
695
+ * const comment = Parser.delimited(Token.literal("(:"), Token.takeTill(":"), Token.literal(":)"))
696
+ * const skip = Parser.quiet(Parser.repeat(Parser.alt(Ascii.multispace1, comment)))
697
+ * const number = Parser.preceded(skip, Ascii.digit1)
698
+ * // Fails expecting only a digit: without `quiet`, also whitespace and "(:"
699
+ * Parser.parse(number, " (: one :) x")
700
+ * ```
701
+ *
702
+ * @since 0.5.0
703
+ * @category error management
704
+ */
705
+ export declare const quiet: <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>;
706
+ /**
707
+ * What a fast path (see {@link withFastPath}) returns to leave the input at
708
+ * the current offset to its grammar.
709
+ *
710
+ * @since 0.5.0
711
+ * @category fast paths
712
+ */
713
+ export declare const Defer: typeof Defer$1;
714
+ /**
715
+ * The type of {@link Defer}.
716
+ *
717
+ * @since 0.5.0
718
+ * @category fast paths
719
+ */
720
+ export type Defer = typeof Defer$1;
721
+ /**
722
+ * Puts a hand-written fast path in front of a grammar, which stays the
723
+ * specification: `fast` runs on the state, at the offset where the grammar
724
+ * would, and either returns the value the grammar would return, with
725
+ * `state.pos` where the grammar would stop, or returns {@link Defer}, and
726
+ * the grammar runs from that offset instead. Use it where a scanner written
727
+ * by hand (`indexOf`, a lookup table, interned names) beats compiled code on
728
+ * the tokens that dominate an input, and let the grammar handle everything
729
+ * else.
730
+ *
731
+ * The fast path runs in compiled code only (see the `Compiler` module).
732
+ * Interpreted runs, and so every error, every `Syntax` tree and every trace,
733
+ * come from the grammar alone, so they are exactly the grammar's. It must
734
+ * defer wherever it would not return exactly what the grammar returns, and
735
+ * on partial input wherever the grammar might report `Incomplete`; check it
736
+ * against the grammar with {@link verifyFastPath}.
737
+ *
738
+ * @example
739
+ * ```ts
740
+ * import { Compiler, Parser, Token } from "@thomasfosterau/effect-parse"
741
+ *
742
+ * const text = Token.takeTill("<", { min: 1 })
743
+ * // The same run, found with `indexOf`; anything else (an empty run, the end of a partial input) defers
744
+ * const fastText = Compiler.jit(
745
+ * Parser.withFastPath(text, (state) => {
746
+ * const end = state.input.indexOf("<", state.pos)
747
+ * if (end <= state.pos || end > state.end) return Parser.Defer
748
+ * const value = state.input.slice(state.pos, end)
749
+ * state.pos = end
750
+ * return value
751
+ * })
752
+ * )
753
+ * ```
754
+ *
755
+ * @since 0.5.0
756
+ * @category fast paths
757
+ */
758
+ export declare const withFastPath: {
759
+ <A, I extends Input>(fast: (state: State<I>) => A | Defer): <E, R>(grammar: Parser<A, E, R, I>) => Parser<A, E, R, I>;
760
+ <A, E, R, I extends Input>(grammar: Parser<A, E, R, I>, fast: (state: State<I>) => A | Defer): Parser<A, E, R, I>;
761
+ };
762
+ /**
763
+ * A place where a fast path disagrees with its grammar (see
764
+ * {@link verifyFastPath}).
765
+ *
766
+ * @since 0.5.0
767
+ * @category fast paths
768
+ */
769
+ export interface FastPathMismatch<A, I extends Input> {
770
+ readonly input: I;
771
+ readonly offset: number;
772
+ readonly partial: boolean;
773
+ /** What the fast path returned, and where it stopped. */
774
+ readonly fast: {
775
+ readonly value: A;
776
+ readonly end: number;
777
+ };
778
+ /** What the grammar returned, and where it stopped, or how it failed. */
779
+ readonly grammar: {
780
+ readonly value: A;
781
+ readonly end: number;
782
+ } | {
783
+ readonly failed: ErrMode;
784
+ };
785
+ }
786
+ /**
787
+ * Checks a fast path against its grammar (see {@link withFastPath}): on
788
+ * every input, at every offset, on complete and on partial input, wherever
789
+ * `fast` returns a value, the grammar (run interpreted) must return an
790
+ * equal value (by `Equal.equals`, or `options.equivalence`) and stop at the
791
+ * same offset. Returns every place where it doesn't, so a test asserts that
792
+ * the result is empty; generated inputs, mutated and truncated, find the
793
+ * most. Grammars that use services are not supported.
794
+ *
795
+ * @example
796
+ * ```ts
797
+ * import { Input, Parser, Token } from "@thomasfosterau/effect-parse"
798
+ *
799
+ * const text = Token.takeTill("<", { min: 1 })
800
+ * const fast = (state: Input.State<string>) => {
801
+ * const end = state.input.indexOf("<", state.pos)
802
+ * if (end <= state.pos || end > state.end) return Parser.Defer
803
+ * const value = state.input.slice(state.pos, end)
804
+ * state.pos = end
805
+ * return value
806
+ * }
807
+ * Parser.verifyFastPath(text, fast, ["a<b", "<", "abc"]) // []
808
+ * ```
809
+ *
810
+ * @since 0.5.0
811
+ * @category fast paths
812
+ */
813
+ export declare const verifyFastPath: <A, E, I extends Input>(grammar: Parser<A, E, never, I>, fast: (state: State<I>) => A | Defer, inputs: Iterable<I>, options?: {
814
+ readonly equivalence?: ((a: A, b: A) => boolean) | undefined;
815
+ }) => ReadonlyArray<FastPathMismatch<A, I>>;
540
816
  /**
541
817
  * Transforms the user error (cause) of a parser's failures.
542
818
  *
@@ -633,6 +909,28 @@ export declare const allConsuming: <A, E, R, I extends Input>(self: Parser<A, E,
633
909
  * @category sequencing
634
910
  */
635
911
  export declare const seq: <const Ps extends ReadonlyArray<Parser.Any>>(...parsers: Ps) => Parser<{ -readonly [K in keyof Ps]: Parser.Success<Ps[K]>; }, Parser.Error<Ps[number]>, Parser.Services<Ps[number]>, Parser.InputOf<Ps[number]>>;
912
+ /**
913
+ * Runs parsers in sequence and combines their outputs with `f`, which
914
+ * receives one argument per parser: the allocation-free spelling of
915
+ * `map(seq(...parsers), ([a, b, ...]) => f(a, b, ...))`, which builds a
916
+ * tuple on every success. Compiled code calls `f` with the values directly.
917
+ * {@link zipWith} is the two-parser, pipeable form.
918
+ *
919
+ * @example
920
+ * ```ts
921
+ * import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
922
+ *
923
+ * const point = Parser.seqWith(
924
+ * [Ascii.decInt, Token.literal(","), Ascii.decInt],
925
+ * (x, _, y) => ({ x, y })
926
+ * )
927
+ * Parser.parse(point, "3,-4") // Result.succeed({ x: 3, y: -4 })
928
+ * ```
929
+ *
930
+ * @since 0.5.0
931
+ * @category sequencing
932
+ */
933
+ export declare const seqWith: <const Ps extends ReadonlyArray<Parser.Any>, B>(parsers: Ps, f: (...values: { -readonly [K in keyof Ps]: Parser.Success<Ps[K]>; }) => B) => Parser<B, Parser.Error<Ps[number]>, Parser.Services<Ps[number]>, Parser.InputOf<Ps[number]>>;
636
934
  /**
637
935
  * Runs a record of parsers in sequence (in key order), collecting their
638
936
  * outputs in a record. This is the Effect counterpart to winnow's
@@ -806,6 +1104,16 @@ declare const let_: {
806
1104
  * @category choice
807
1105
  */
808
1106
  export declare const alt: <const Ps extends ReadonlyArray<Parser.Any>>(...parsers: Ps) => Parser<Parser.Success<Ps[number]>, Parser.Error<Ps[number]>, Parser.Services<Ps[number]>, Parser.InputOf<Ps[number]>>;
1107
+ /**
1108
+ * The overloads of {@link dispatch}.
1109
+ *
1110
+ * @since 0.5.0
1111
+ * @category choice
1112
+ */
1113
+ export interface DispatchFn {
1114
+ <K, E, R, I extends Input, P extends Parser.Any>(selector: Parser<K, E, R, I>, cases: (key: K) => P | undefined): Parser<Parser.Success<P>, E | Parser.Error<P>, R | Parser.Services<P>, I & Parser.InputOf<P>>;
1115
+ <K extends PropertyKey, E, R, I extends Input, const Cases extends { readonly [key in K]?: Parser.Any; }, Otherwise extends Parser.Any = never>(selector: Parser<K, E, R, I>, cases: Cases, otherwise?: Otherwise): Parser<Parser.Success<NonNullable<Cases[keyof Cases]> | Otherwise>, E | Parser.Error<NonNullable<Cases[keyof Cases]> | Otherwise>, R | Parser.Services<NonNullable<Cases[keyof Cases]> | Otherwise>, I & Parser.InputOf<NonNullable<Cases[keyof Cases]> | Otherwise>>;
1116
+ }
809
1117
  /**
810
1118
  * Selects the parser to run next based on the output of `selector`, like a
811
1119
  * `match` over the input (winnow's `dispatch!`). If no case matches, the
@@ -840,10 +1148,7 @@ export declare const alt: <const Ps extends ReadonlyArray<Parser.Any>>(...parser
840
1148
  * @since 0.1.0
841
1149
  * @category choice
842
1150
  */
843
- export declare const dispatch: {
844
- <K, E, R, I extends Input, P extends Parser.Any>(selector: Parser<K, E, R, I>, cases: (key: K) => P | undefined): Parser<Parser.Success<P>, E | Parser.Error<P>, R | Parser.Services<P>, I & Parser.InputOf<P>>;
845
- <K extends PropertyKey, E, R, I extends Input, const Cases extends { readonly [key in K]?: Parser.Any; }, Otherwise extends Parser.Any = never>(selector: Parser<K, E, R, I>, cases: Cases, otherwise?: Otherwise): Parser<Parser.Success<NonNullable<Cases[keyof Cases]> | Otherwise>, E | Parser.Error<NonNullable<Cases[keyof Cases]> | Otherwise>, R | Parser.Services<NonNullable<Cases[keyof Cases]> | Otherwise>, I & Parser.InputOf<NonNullable<Cases[keyof Cases]> | Otherwise>>;
846
- };
1151
+ export declare const dispatch: DispatchFn;
847
1152
  /**
848
1153
  * Applies every parser exactly once, in whatever order they match, and
849
1154
  * returns their outputs in the order the parsers were given (winnow's and
@@ -1132,6 +1437,16 @@ export interface ParseOptions {
1132
1437
  export interface ParseOptionsWithContext<R> extends ParseOptions {
1133
1438
  readonly context: Context.Context<R>;
1134
1439
  }
1440
+ /**
1441
+ * The overloads of {@link parse}.
1442
+ *
1443
+ * @since 0.5.0
1444
+ * @category running
1445
+ */
1446
+ export interface ParseFn {
1447
+ <A, E, I extends Input>(self: Parser<A, E, never, I>, input: NoInfer<Source<I>>, options?: ParseOptions): Result.Result<A, ParseError.ParseError<E>>;
1448
+ <A, E, R, I extends Input>(self: Parser<A, E, R, I>, input: NoInfer<Source<I>>, options: ParseOptionsWithContext<R>): Result.Result<A, ParseError.ParseError<E>>;
1449
+ }
1135
1450
  /**
1136
1451
  * Runs a parser against a complete input, requiring the whole input to be
1137
1452
  * consumed (winnow's `Parser::parse`).
@@ -1148,20 +1463,34 @@ export interface ParseOptionsWithContext<R> extends ParseOptions {
1148
1463
  * @since 0.1.0
1149
1464
  * @category running
1150
1465
  */
1151
- export declare const parse: {
1152
- <A, E, I extends Input>(self: Parser<A, E, never, I>, input: NoInfer<Source<I>>, options?: ParseOptions): Result.Result<A, ParseError.ParseError<E>>;
1153
- <A, E, R, I extends Input>(self: Parser<A, E, R, I>, input: NoInfer<Source<I>>, options: ParseOptionsWithContext<R>): Result.Result<A, ParseError.ParseError<E>>;
1154
- };
1466
+ export declare const parse: ParseFn;
1155
1467
  /**
1156
- * Like {@link parse}, but throws the `ParseError` on failure.
1468
+ * The overloads of {@link parseSync}.
1157
1469
  *
1158
- * @since 0.1.0
1470
+ * @since 0.5.0
1159
1471
  * @category running
1160
1472
  */
1161
- export declare const parseSync: {
1473
+ export interface ParseSyncFn {
1162
1474
  <A, E, I extends Input>(self: Parser<A, E, never, I>, input: NoInfer<Source<I>>, options?: ParseOptions): A;
1163
1475
  <A, E, R, I extends Input>(self: Parser<A, E, R, I>, input: NoInfer<Source<I>>, options: ParseOptionsWithContext<R>): A;
1164
- };
1476
+ }
1477
+ /**
1478
+ * Like {@link parse}, but throws the `ParseError` on failure.
1479
+ *
1480
+ * @since 0.1.0
1481
+ * @category running
1482
+ */
1483
+ export declare const parseSync: ParseSyncFn;
1484
+ /**
1485
+ * The overloads of {@link parsePeek}.
1486
+ *
1487
+ * @since 0.5.0
1488
+ * @category running
1489
+ */
1490
+ export interface ParsePeekFn {
1491
+ <A, E, I extends Input>(self: Parser<A, E, never, I>, input: NoInfer<Source<I>>, options?: ParseOptions): Result.Result<[remaining: Slice<I>, output: A], ParseError.ParseError<E>>;
1492
+ <A, E, R, I extends Input>(self: Parser<A, E, R, I>, input: NoInfer<Source<I>>, options: ParseOptionsWithContext<R>): Result.Result<[remaining: Slice<I>, output: A], ParseError.ParseError<E>>;
1493
+ }
1165
1494
  /**
1166
1495
  * Runs a parser against the start of an input, returning the remaining
1167
1496
  * input along with the output, nom-style (winnow's `parse_peek`, nom's
@@ -1174,10 +1503,7 @@ export declare const parseSync: {
1174
1503
  * @since 0.1.0
1175
1504
  * @category running
1176
1505
  */
1177
- export declare const parsePeek: {
1178
- <A, E, I extends Input>(self: Parser<A, E, never, I>, input: NoInfer<Source<I>>, options?: ParseOptions): Result.Result<[remaining: Slice<I>, output: A], ParseError.ParseError<E>>;
1179
- <A, E, R, I extends Input>(self: Parser<A, E, R, I>, input: NoInfer<Source<I>>, options: ParseOptionsWithContext<R>): Result.Result<[remaining: Slice<I>, output: A], ParseError.ParseError<E>>;
1180
- };
1506
+ export declare const parsePeek: ParsePeekFn;
1181
1507
  /**
1182
1508
  * The outcome of parsing a partial (streaming) input.
1183
1509
  *
@@ -1195,6 +1521,16 @@ export type PartialResult<A> = {
1195
1521
  readonly _tag: "Incomplete";
1196
1522
  readonly needed: Option.Option<number>;
1197
1523
  };
1524
+ /**
1525
+ * The overloads of {@link parsePartial}.
1526
+ *
1527
+ * @since 0.5.0
1528
+ * @category running
1529
+ */
1530
+ export interface ParsePartialFn {
1531
+ <A, E, I extends Input>(self: Parser<A, E, never, I>, input: NoInfer<Source<I>>, options?: ParseOptions): Result.Result<PartialResult<A>, ParseError.ParseError<E>>;
1532
+ <A, E, R, I extends Input>(self: Parser<A, E, R, I>, input: NoInfer<Source<I>>, options: ParseOptionsWithContext<R>): Result.Result<PartialResult<A>, ParseError.ParseError<E>>;
1533
+ }
1198
1534
  /**
1199
1535
  * Runs a parser against a *partial* input, i.e. a chunk of a stream that may
1200
1536
  * be followed by more data (winnow's `Partial`, nom's `streaming` parsers).
@@ -1224,10 +1560,7 @@ export type PartialResult<A> = {
1224
1560
  * @since 0.1.0
1225
1561
  * @category running
1226
1562
  */
1227
- export declare const parsePartial: {
1228
- <A, E, I extends Input>(self: Parser<A, E, never, I>, input: NoInfer<Source<I>>, options?: ParseOptions): Result.Result<PartialResult<A>, ParseError.ParseError<E>>;
1229
- <A, E, R, I extends Input>(self: Parser<A, E, R, I>, input: NoInfer<Source<I>>, options: ParseOptionsWithContext<R>): Result.Result<PartialResult<A>, ParseError.ParseError<E>>;
1230
- };
1563
+ export declare const parsePartial: ParsePartialFn;
1231
1564
  /**
1232
1565
  * Runs a parser against a complete input as an `Effect`. Services required
1233
1566
  * by the parser are taken from the Effect's context.
@@ -1330,6 +1663,16 @@ export interface RecoverableResult<A, E> {
1330
1663
  /** Every error encountered: recovered ones, then the fatal one (if any). */
1331
1664
  readonly errors: ReadonlyArray<ParseError.ParseError<E>>;
1332
1665
  }
1666
+ /**
1667
+ * The overloads of {@link parseRecoverable}.
1668
+ *
1669
+ * @since 0.5.0
1670
+ * @category running
1671
+ */
1672
+ export interface ParseRecoverableFn {
1673
+ <A, E, I extends Input>(self: Parser<A, E, never, I>, input: NoInfer<Source<I>>, options?: ParseOptions): RecoverableResult<A, E>;
1674
+ <A, E, R, I extends Input>(self: Parser<A, E, R, I>, input: NoInfer<Source<I>>, options: ParseOptionsWithContext<R>): RecoverableResult<A, E>;
1675
+ }
1333
1676
  /**
1334
1677
  * Runs a parser with error recovery enabled (winnow's `Recoverable`
1335
1678
  * stream). Failures handled by {@link resumeAfter} and {@link retryAfter}
@@ -1338,9 +1681,6 @@ export interface RecoverableResult<A, E> {
1338
1681
  * @since 0.1.0
1339
1682
  * @category running
1340
1683
  */
1341
- export declare const parseRecoverable: {
1342
- <A, E, I extends Input>(self: Parser<A, E, never, I>, input: NoInfer<Source<I>>, options?: ParseOptions): RecoverableResult<A, E>;
1343
- <A, E, R, I extends Input>(self: Parser<A, E, R, I>, input: NoInfer<Source<I>>, options: ParseOptionsWithContext<R>): RecoverableResult<A, E>;
1344
- };
1684
+ export declare const parseRecoverable: ParseRecoverableFn;
1345
1685
  export { type ErrorKind, let_ as let, void_ as void };
1346
1686
  //# sourceMappingURL=Parser.d.ts.map