@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.
- package/README.md +37 -13
- package/dist/Ascii.d.ts +11 -4
- package/dist/Ascii.d.ts.map +1 -1
- package/dist/Ascii.js +7 -1
- package/dist/Ascii.js.map +1 -1
- package/dist/Binary.d.ts.map +1 -1
- package/dist/Binary.js +64 -35
- package/dist/Binary.js.map +1 -1
- package/dist/Bits.d.ts.map +1 -1
- package/dist/Bits.js +7 -4
- package/dist/Bits.js.map +1 -1
- package/dist/Compiler.d.ts +74 -2
- package/dist/Compiler.d.ts.map +1 -1
- package/dist/Compiler.js +78 -1
- package/dist/Compiler.js.map +1 -1
- package/dist/Expression.d.ts.map +1 -1
- package/dist/Expression.js +86 -74
- package/dist/Expression.js.map +1 -1
- package/dist/Input.d.ts +37 -4
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +42 -0
- package/dist/Input.js.map +1 -1
- package/dist/Nom.d.ts +5 -15
- package/dist/Nom.d.ts.map +1 -1
- package/dist/Nom.js.map +1 -1
- package/dist/ParseError.d.ts.map +1 -1
- package/dist/ParseError.js.map +1 -1
- package/dist/Parser.d.ts +366 -26
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +390 -19
- package/dist/Parser.js.map +1 -1
- package/dist/ParserSchema.js +1 -1
- package/dist/ParserStream.d.ts +3 -2
- package/dist/ParserStream.d.ts.map +1 -1
- package/dist/ParserStream.js +13 -9
- package/dist/ParserStream.js.map +1 -1
- package/dist/Syntax.d.ts +23 -5
- package/dist/Syntax.d.ts.map +1 -1
- package/dist/Syntax.js.map +1 -1
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +9 -9
- package/dist/Text.js.map +1 -1
- package/dist/Token.d.ts +55 -10
- package/dist/Token.d.ts.map +1 -1
- package/dist/Token.js +59 -21
- package/dist/Token.js.map +1 -1
- package/dist/internal/compiler/closure.d.ts.map +1 -1
- package/dist/internal/compiler/closure.js +257 -97
- package/dist/internal/compiler/closure.js.map +1 -1
- package/dist/internal/compiler/entries.d.ts +3 -1
- package/dist/internal/compiler/entries.d.ts.map +1 -1
- package/dist/internal/compiler/entries.js +3 -2
- package/dist/internal/compiler/entries.js.map +1 -1
- package/dist/internal/compiler/first.d.ts.map +1 -1
- package/dist/internal/compiler/first.js +7 -1
- package/dist/internal/compiler/first.js.map +1 -1
- package/dist/internal/compiler/graph.d.ts +17 -0
- package/dist/internal/compiler/graph.d.ts.map +1 -0
- package/dist/internal/compiler/graph.js +56 -0
- package/dist/internal/compiler/graph.js.map +1 -0
- package/dist/internal/compiler/jit.d.ts +5 -0
- package/dist/internal/compiler/jit.d.ts.map +1 -1
- package/dist/internal/compiler/jit.js +185 -96
- package/dist/internal/compiler/jit.js.map +1 -1
- package/dist/internal/compiler/registry.d.ts +10 -2
- package/dist/internal/compiler/registry.d.ts.map +1 -1
- package/dist/internal/compiler/registry.js.map +1 -1
- package/dist/internal/compiler/search.d.ts +32 -0
- package/dist/internal/compiler/search.d.ts.map +1 -0
- package/dist/internal/compiler/search.js +68 -0
- package/dist/internal/compiler/search.js.map +1 -0
- package/dist/internal/compiler/sets.d.ts.map +1 -1
- package/dist/internal/compiler/sets.js +1 -1
- package/dist/internal/compiler/sets.js.map +1 -1
- package/dist/internal/compiler/wasm.d.ts +8 -0
- package/dist/internal/compiler/wasm.d.ts.map +1 -0
- package/dist/internal/compiler/wasm.js +2769 -0
- package/dist/internal/compiler/wasm.js.map +1 -0
- package/dist/internal/compiler/wasmAsm.d.ts +199 -0
- package/dist/internal/compiler/wasmAsm.d.ts.map +1 -0
- package/dist/internal/compiler/wasmAsm.js +427 -0
- package/dist/internal/compiler/wasmAsm.js.map +1 -0
- package/dist/internal/entries.d.ts +3 -1
- package/dist/internal/entries.d.ts.map +1 -1
- package/dist/internal/entries.js.map +1 -1
- package/dist/internal/node.d.ts +58 -2
- package/dist/internal/node.d.ts.map +1 -1
- package/dist/internal/node.js +13 -3
- package/dist/internal/node.js.map +1 -1
- package/dist/internal/numbers.d.ts.map +1 -1
- package/dist/internal/numbers.js.map +1 -1
- package/dist/internal/run.d.ts +12 -0
- package/dist/internal/run.d.ts.map +1 -1
- package/dist/internal/run.js +51 -11
- package/dist/internal/run.js.map +1 -1
- package/dist/internal/stack.d.ts +6 -0
- package/dist/internal/stack.d.ts.map +1 -1
- package/dist/internal/stack.js +8 -2
- package/dist/internal/stack.js.map +1 -1
- package/dist/internal/syntax.d.ts +4 -4
- package/dist/internal/syntax.d.ts.map +1 -1
- package/dist/internal/syntax.js +18 -10
- package/dist/internal/syntax.js.map +1 -1
- package/dist/internal/text.d.ts +32 -0
- package/dist/internal/text.d.ts.map +1 -1
- package/dist/internal/text.js +68 -14
- package/dist/internal/text.js.map +1 -1
- package/dist/internal/tokens.d.ts +13 -0
- package/dist/internal/tokens.d.ts.map +1 -1
- package/dist/internal/tokens.js +59 -39
- package/dist/internal/tokens.js.map +1 -1
- package/package.json +5 -4
- package/src/Ascii.ts +42 -9
- package/src/Binary.ts +151 -71
- package/src/Bits.ts +12 -6
- package/src/Compiler.ts +101 -10
- package/src/Expression.ts +94 -81
- package/src/Input.ts +65 -6
- package/src/Nom.ts +15 -5
- package/src/ParseError.ts +3 -0
- package/src/Parser.ts +678 -127
- package/src/ParserStream.ts +37 -18
- package/src/Syntax.ts +60 -36
- package/src/Text.ts +16 -15
- package/src/Token.ts +138 -29
- package/src/internal/compiler/closure.ts +362 -135
- package/src/internal/compiler/entries.ts +4 -2
- package/src/internal/compiler/first.ts +10 -0
- package/src/internal/compiler/graph.ts +68 -0
- package/src/internal/compiler/jit.ts +284 -154
- package/src/internal/compiler/registry.ts +10 -2
- package/src/internal/compiler/search.ts +68 -0
- package/src/internal/compiler/sets.ts +7 -3
- package/src/internal/compiler/wasm.ts +3203 -0
- package/src/internal/compiler/wasmAsm.ts +484 -0
- package/src/internal/entries.ts +8 -2
- package/src/internal/node.ts +54 -4
- package/src/internal/numbers.ts +3 -1
- package/src/internal/run.ts +71 -12
- package/src/internal/stack.ts +8 -1
- package/src/internal/syntax.ts +39 -18
- package/src/internal/text.ts +97 -9
- package/src/internal/tokens.ts +96 -14
package/dist/ParseError.js.map
CHANGED
|
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+EA,MAAa,SAAS;;;;;;;AAQtB,IAAa,aAAb,eACwB,mBAAK,YAAY,YAAY,EAAA,CAuBrD;;;;CAIE,CAAU,UAAyB;;;;;;;CAQnC,IAAI,WAAuB;EACzB,OAAO,WAAW,KAAK,OAAO,KAAK,QAAQ,KAAK,QAAQ;CAC1D;;;;;;CAOA,IAAa,UAAkB;EAC7B,OAAO,OAAO,IAAI;CACpB;;;;CAKA,WAA4B;EAC1B,OAAO,eAAe,KAAK;CAC7B;AACF;;;;;AAMA,MAAa,gBAAgB,MAAyC,UAAU,gBAAgB,CAAC,KAAA,8BAAe;;;;;;;AAQhH,MAAa,eACX,OACA,SACA,MACA,aAEA,IAAI,WAAc;CAChB;CACA,QAAQ,QAAQ;CAChB,MAAM,QAAQ;CACd;CACA,UAAU,QAAQ;CAClB,SAAS,QAAQ;CAIjB,OAAO,QAAQ,WAAY,QAAQ,QAAc,KAAA;CACjD,aAAa,QAAQ;CACrB,UAAU,iBAAiB,aAAa,WAAW,KAAA;AACrD,CAAC;;;;;;;AAQH,MAAa,YAAe,SAC1B,KAAK,UAAU,KAAA,IAAY,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,KAAK;;;;;;;;;;AAsBnE,MAAa,cAAc,OAAc,QAAgB,aAAyC;CAChG,IAAI,aAAa,KAAA,KAAa,iBAAiB,YAAY;EACzD,IAAI,OAAO;EACX,IAAI,SAAS;EACb,KAAK,KAAK,UAAU,OAAO,GAAG,KAAK,IAAI,QAAQ,MAAM,MAAM,IAAI,OAAO;GACpE,IAAI,OAAO,IAAI;IACb;IACA,SAAS;GACX,OACE;EAEJ,CAAC;EACD,OAAO;GAAE;GAAM;EAAO;CACxB;CACA,IAAI,CAAC,UAAU,SAAS,KAAK,GAAG,OAAO;EAAE,MAAM;EAAG,QAAQ,SAAS;CAAE;CACrE,IAAI,OAAO;CACX,IAAI,YAAY;CAChB,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,IAAI,MAAM,QAAQ,KAC9C,IAAI,MAAM,WAAW,CAAC,MAAM,IAAI;EAC9B;EACA,YAAY,IAAI;CAClB;CAEF,OAAO;EAAE;EAAM,QAAQ,eAAe,OAAO,WAAW,KAAK,IAAI,QAAQ,MAAM,MAAM,CAAC,IAAI;CAAE;AAC9F;AAEA,MAAM,kBAAkB,GAAW,OAAe,QAAwB;CACxE,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,KAAK;EAChC,MAAM,IAAI,EAAE,WAAW,CAAC;EACxB,IAAI,KAAK,SAAU,KAAK,SAAU,IAAI,IAAI,KAAK;GAC7C,MAAM,IAAI,EAAE,WAAW,IAAI,CAAC;GAC5B,IAAI,KAAK,SAAU,KAAK,OAAQ;EAClC;EACA;CACF;CACA,OAAO;AACT;;;;;;;AAQA,MAAa,kBAAkB,aAA4C;CACzE,IAAI,IAAI,qBAAqB,QAAQ,GAAG,OAAO;CAC/C,IAAI,SAAS,WAAW,GAAG,OAAO,SAAS;CAC3C,OAAO,GAAG,SAAS,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,MAAM,SAAS,SAAS,SAAS;AAC9E;AAEA,MAAM,YAAY,UAChB,MAAM,KAAK,QAAQ,MAAM,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG,CAAC,CAAC,KAAK,GAAG;AAE3E,MAAM,iBAAiB,OAAc,QAAgB,aAAgD;CACnG,IAAI,UAAU,MAAM,QAAQ,OAAO;CACnC,IAAI,aAAa,KAAA,KAAa,iBAAiB,YAAY;EACzD,MAAM,KAAK,SAAS,OAAO,OAAO,QAAQ,MAAM,MAAM;EACtD,IAAI,MAAM,GAAG,OAAO,KAAK,UAAU,OAAO,cAAc,EAAE,CAAC;EAC3D,MAAM,MAAM,MAAM,SAAS,QAAQ,KAAK,IAAI,MAAM,QAAQ,SAAS,KAAK,IAAI,SAAS,MAAM,CAAC,CAAC,CAAC;EAC9F,OAAO,OAAO,KAAK,YACf,cAAc,SAAS,KAAK,YAAY,SAAS,MAAM,SAAS,MAAM,CAAC,MACvE,WAAW,SAAS,KAAK,GAAG,SAAS,GAAG;CAC9C;CACA,IAAI,UAAU,SAAS,KAAK,GAAG;EAC7B,MAAM,KAAK,MAAM,YAAY,MAAM,KAAK;EACxC,OAAO,KAAK,UAAU,OAAO,cAAc,EAAE,CAAC;CAChD;CACA,IAAI,iBAAiB,YACnB,OAAO,KAAK,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG;CAExD,OAAO,aAAa,MAAM,OAAO;AACnC;;AAGA,MAAa,gBAAgB,MAAuB;CAClD,IAAI,UAAU,SAAS,CAAC,GAAG,OAAO,KAAK,UAAU,CAAC;CAClD,IAAI,UAAU,gBAAgB,CAAC,GAI7B,OAAO,OAAO,UACZ,OAAO,UAAU,KAAK,UAAU,CAAC,CAAC,SAC3B,MAAM,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,OAAO,UAAU,SAAS,KAAK,CAAC,CAC1E;CAEF,OAAO,OAAO,CAAC;AACjB;AAEA,MAAM,gBAAgB,UAAuC;CAC3D,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,IAAI,UAAU,SAAS,KAAK,GAAG,OAAO;CAEtC,IAAI,UAAU,gBAAgB,KAAK,KAAK,aAAa,SAAS,UAAU,SAAS,MAAM,OAAO,GAC5F,OAAO,MAAM;CAEf,OAAO,aAAa,KAAK;AAC3B;AAEA,MAAM,iBAAiB,OAAc,QAAgB,aAAuD;CAC1G,IAAI,aAAa,KAAA,KAAa,iBAAiB,YAAY;EAEzD,IAAI,YAAY;EAChB,IAAI,MAAM,MAAM;EAChB,IAAI,SAAS;EACb,KAAK,KAAK,UAAU,OAAO,GAAG,MAAM,SAAS,IAAI,GAAG,MAAM;GACxD,IAAI,KAAK,UAAU,OAAO,IAAI;IAC5B,MAAM;IACN,OAAO;GACT;GACA,IAAI,IAAI,QAAQ;IACd,IAAI,OAAO,IAAI;KACb,YAAY,IAAI;KAChB,SAAS;IACX,OACE;GAEJ;EACF,CAAC;EACD,IAAI,OAAO,KAAK,YAAY,UAAU,OAAO,WAAW,GAAG;EAC3D,IAAI,KAAK,SAAS,IAAI,GAAG,OAAO,KAAK,MAAM,GAAG,EAAE;EAChD,MAAM,SAAS,OAAO,WAAW,OAAO,QAAQ,QAAQ,CAAC,CAAC,IAAI;EAC9D,MAAM,MAAM,IAAI,OAAO,OAAO,MAAM;EACpC,OAAO,CAAC,GAAG,OAAO,KAAK,QAAQ,GAAG,IAAI,KAAK,IAAI,OAAO,SAAS,CAAC,EAAE,EAAE;CACtE;CACA,IAAI,UAAU,SAAS,KAAK,GAAG;EAC7B,MAAM,EAAE,QAAQ,SAAS,WAAW,OAAO,MAAM;EACjD,IAAI,QAAQ;EACZ,OAAO,QAAQ,KAAK,MAAM,WAAW,QAAQ,CAAC,MAAM,IAAI;EACxD,IAAI,MAAM;EACV,OAAO,MAAM,MAAM,UAAU,MAAM,WAAW,GAAG,MAAM,IAAI;EAC3D,IAAI,OAAO,MAAM,MAAM,OAAO,GAAG;EACjC,IAAI,KAAK,SAAS,IAAI,GAAG,OAAO,KAAK,MAAM,GAAG,EAAE;EAChD,MAAM,SAAS,OAAO,IAAI;EAC1B,MAAM,MAAM,IAAI,OAAO,OAAO,MAAM;EACpC,OAAO,CAAC,GAAG,OAAO,KAAK,QAAQ,GAAG,IAAI,KAAK,IAAI,OAAO,SAAS,CAAC,EAAE,EAAE;CACtE;CACA,IAAI,iBAAiB,YAAY;EAC/B,MAAM,QAAQ,KAAK,IAAI,GAAG,SAAS,CAAC;EACpC,MAAM,MAAM,KAAK,IAAI,MAAM,QAAQ,SAAS,CAAC;EAC7C,MAAM,QAAuB,CAAC;EAC9B,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,KAAK,MAAM,KAAK,MAAM,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC;EACnF,MAAM,SAAS,SAAS,SAAS;EACjC,OAAO,CAAC,GAAG,MAAM,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE,KAAK,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,OAAO,CAAC,EAAE,KAAK,IAAI,OAAO,KAAK,EAAE,EAAE;CACnH;CACA,OAAO,CAAC;AACV;AAEA,MAAM,UAAU,UAAuC;CACrD,MAAM,EAAE,UAAU,OAAO,WAAW;CACpC,MAAM,QAAuB,CAAC;CAC9B,IAAI,UAAU,SAAS,KAAK,GAAG;EAC7B,MAAM,EAAE,QAAQ,SAAS,WAAW,OAAO,MAAM;EACjD,MAAM,KAAK,uBAAuB,KAAK,WAAW,OAAO,EAAE;CAC7D,OAAO,IAAI,aAAa,KAAA,GAAW;EACjC,MAAM,EAAE,QAAQ,SAAS,WAAW,OAAO,QAAQ,QAAQ;EAC3D,MAAM,KAAK,uBAAuB,KAAK,WAAW,OAAO,SAAS,OAAO,GAAG;CAC9E,OACE,MAAM,KAAK,yBAAyB,OAAO,EAAE;CAE/C,MAAM,KAAK,GAAG,cAAc,OAAO,QAAQ,QAAQ,CAAC;CACpD,KAAK,IAAI,IAAI,MAAM,QAAQ,SAAS,GAAG,KAAK,GAAG,KAC7C,MAAM,KAAK,iBAAiB,MAAM,QAAQ,IAAI;CAEhD,MAAM,QAAQ,aAAa,MAAM,KAAK;CACtC,IAAI,UAAU,KAAA,GAAW,MAAM,KAAK,KAAK;CACzC,IAAI,MAAM,gBAAgB,KAAA,GAAW,MAAM,KAAK,MAAM,WAAW;CACjE,IAAI,MAAM,SAAS,cACjB,MAAM,KAAK,sCAAsC;MAC5C,IAAI,IAAI,wBAAwB,MAAM,QAAQ,GACnD,MAAM,KAAK,YAAY,eAAe,MAAM,QAAQ,EAAE,UAAU,cAAc,OAAO,QAAQ,QAAQ,GAAG;MACnG,IAAI,UAAU,KAAA,KAAa,MAAM,gBAAgB,KAAA,GACtD,MAAM,KAAK,cAAc,cAAc,OAAO,QAAQ,QAAQ,EAAE,IAAI,MAAM,KAAK,EAAE;CAEnF,OAAO,MAAM,KAAK,IAAI;AACxB"}
|
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
|
-
*
|
|
1468
|
+
* The overloads of {@link parseSync}.
|
|
1157
1469
|
*
|
|
1158
|
-
* @since 0.
|
|
1470
|
+
* @since 0.5.0
|
|
1159
1471
|
* @category running
|
|
1160
1472
|
*/
|
|
1161
|
-
export
|
|
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
|