@thomasfosterau/effect-parse 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +202 -0
- package/README.md +56 -14
- package/dist/Ascii.d.ts +11 -4
- package/dist/Ascii.d.ts.map +1 -1
- package/dist/Ascii.js +12 -4
- package/dist/Ascii.js.map +1 -1
- package/dist/Binary.d.ts +5 -2
- package/dist/Binary.d.ts.map +1 -1
- package/dist/Binary.js +83 -37
- package/dist/Binary.js.map +1 -1
- package/dist/Bits.d.ts.map +1 -1
- package/dist/Bits.js +11 -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 +56 -5
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +70 -1
- 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 +69 -11
- package/dist/ParseError.d.ts.map +1 -1
- package/dist/ParseError.js +129 -28
- package/dist/ParseError.js.map +1 -1
- package/dist/Parser.d.ts +375 -29
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +394 -37
- package/dist/Parser.js.map +1 -1
- package/dist/ParserSchema.d.ts.map +1 -1
- package/dist/ParserSchema.js +2 -3
- package/dist/ParserSchema.js.map +1 -1
- package/dist/ParserStream.d.ts +122 -14
- package/dist/ParserStream.d.ts.map +1 -1
- package/dist/ParserStream.js +293 -62
- 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 +1 -1
- package/dist/Syntax.js.map +1 -1
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +21 -15
- package/dist/Text.js.map +1 -1
- package/dist/Token.d.ts +65 -11
- package/dist/Token.d.ts.map +1 -1
- package/dist/Token.js +73 -26
- package/dist/Token.js.map +1 -1
- package/dist/internal/compiler/closure.d.ts +1 -1
- package/dist/internal/compiler/closure.d.ts.map +1 -1
- package/dist/internal/compiler/closure.js +263 -113
- 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 +9 -2
- package/dist/internal/compiler/first.js.map +1 -1
- package/dist/internal/compiler/graph.d.ts +39 -0
- package/dist/internal/compiler/graph.d.ts.map +1 -0
- package/dist/internal/compiler/graph.js +78 -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 +208 -106
- package/dist/internal/compiler/jit.js.map +1 -1
- package/dist/internal/compiler/registry.d.ts +11 -3
- 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 +2840 -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 +77 -3
- package/dist/internal/node.d.ts.map +1 -1
- package/dist/internal/node.js +54 -10
- 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 +14 -0
- package/dist/internal/run.d.ts.map +1 -1
- package/dist/internal/run.js +53 -11
- package/dist/internal/run.js.map +1 -1
- package/dist/internal/stack.d.ts +14 -0
- package/dist/internal/stack.d.ts.map +1 -1
- package/dist/internal/stack.js +24 -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 +20 -0
- package/dist/internal/tokens.d.ts.map +1 -1
- package/dist/internal/tokens.js +72 -39
- package/dist/internal/tokens.js.map +1 -1
- package/dist/internal/tuple.d.ts +6 -0
- package/dist/internal/tuple.d.ts.map +1 -0
- package/dist/internal/tuple.js +170 -0
- package/dist/internal/tuple.js.map +1 -0
- package/package.json +18 -10
- package/src/Ascii.ts +47 -12
- package/src/Binary.ts +174 -73
- package/src/Bits.ts +16 -6
- package/src/Compiler.ts +101 -10
- package/src/Expression.ts +94 -81
- package/src/Input.ts +99 -7
- package/src/Nom.ts +15 -5
- package/src/ParseError.ts +209 -52
- package/src/Parser.ts +684 -143
- package/src/ParserSchema.ts +1 -2
- package/src/ParserStream.ts +361 -68
- package/src/Syntax.ts +60 -36
- package/src/Text.ts +32 -27
- package/src/Token.ts +152 -34
- package/src/internal/compiler/closure.ts +371 -153
- package/src/internal/compiler/entries.ts +4 -2
- package/src/internal/compiler/first.ts +16 -0
- package/src/internal/compiler/graph.ts +96 -0
- package/src/internal/compiler/jit.ts +319 -169
- 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 +3276 -0
- package/src/internal/compiler/wasmAsm.ts +484 -0
- package/src/internal/entries.ts +8 -2
- package/src/internal/node.ts +103 -7
- package/src/internal/numbers.ts +3 -1
- package/src/internal/run.ts +73 -12
- package/src/internal/stack.ts +25 -1
- package/src/internal/syntax.ts +39 -18
- package/src/internal/text.ts +97 -9
- package/src/internal/tokens.ts +106 -14
- package/src/internal/tuple.ts +141 -0
package/dist/Bits.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Bits.js","names":[],"sources":["../src/Bits.ts"],"sourcesContent":["/**\n * Bit-level parsing (winnow's `binary::bits`, nom's `bits` module).\n *\n * Bit parsers run inside {@link bits}, which switches a byte parser into\n * bit mode. Bits are read most-significant first. When `bits` finishes, any\n * remaining bits of a partly consumed byte are skipped.\n *\n * Inside `bits`, offsets count bits, so the general combinators (`alt`,\n * `repeat`, `opt`, ...) backtrack at bit granularity.\n *\n * @example\n * ```ts\n * import { Binary, Bits, Parser } from \"@thomasfosterau/effect-parse\"\n *\n * // An IPv4 header starts with a 4-bit version and a 4-bit header length\n * const versionAndLength = Bits.bits(Parser.seq(Bits.take(4), Bits.take(4)))\n *\n * Parser.parse(versionAndLength, new Uint8Array([0x45])) // Result.succeed([4, 5])\n * ```\n *\n * @since 0.1.0\n */\nimport type { State } from \"./Input.js\"\nimport { Fail, Failure } from \"./Input.js\"\nimport type { Parser } from \"./Parser.js\"\nimport { make } from \"./Parser.js\"\n\ndeclare const BitInputBrand: unique symbol\n\n/**\n * The input type of bit-level parsers. A `Parser<A, E, R, BitInput>` can\n * only be run inside {@link bits}.\n *\n * @since 0.1.0\n * @category models\n */\nexport interface BitInput extends ReadonlyArray<never> {\n readonly [BitInputBrand]: true\n}\n\nconst scale = (f: Failure, factor: number): Failure =>\n new Failure(\n factor < 1 ? Math.floor(f.offset * factor) : f.offset * factor,\n f.kind,\n f.expected,\n f.context,\n f.hasCause,\n f.cause,\n f.message,\n factor < 1 ? Math.ceil(f.needed * factor) : f.needed * factor\n )\n\n/**\n * Runs `step` with offsets measured in different units (bits vs bytes),\n * converting failure offsets back to the outer units afterwards.\n */\nconst inUnits = <A>(state: State<any>, factor: number, step: (state: State<any>) => A | Fail): A | Fail => {\n const end = state.end\n const deepest = state.deepest\n state.deepest = undefined\n state.pos = factor > 1 ? state.pos * factor : Math.ceil(state.pos * factor)\n state.end = end * factor\n const a = step(state)\n state.end = end\n const inner = state.deepest\n state.deepest = deepest\n if (a === Fail) {\n state.pos = factor > 1 ? Math.floor(state.pos / factor) : state.pos / factor\n const f = state.failure\n state.failure = scale(f, 1 / factor)\n // A committed failure keeps only the failures recorded after the commit\n // (see `Parser.cut`), so none from before these units\n if (state.mode === \"Cut\") state.deepest = undefined\n if (inner !== undefined) {\n const d = inner === f ? state.failure : scale(inner, 1 / factor)\n if (state.deepest === undefined || d.offset >= state.deepest.offset) state.deepest = d\n }\n return Fail\n }\n state.pos = factor > 1 ? Math.ceil(state.pos / factor) : state.pos / factor\n if (inner !== undefined) {\n const d = scale(inner, 1 / factor)\n if (deepest === undefined || d.offset >= deepest.offset) state.deepest = d\n }\n return a\n}\n\n/**\n * Runs a bit-level parser on byte input (winnow's and nom's `bits`). After\n * success, the input advances to the next byte boundary.\n *\n * @since 0.1.0\n * @category combinators\n */\nexport const bits = <A, E, R>(self: Parser<A, E, R, BitInput>): Parser<A, E, R, Uint8Array> => {\n const step = self.step
|
|
1
|
+
{"version":3,"file":"Bits.js","names":[],"sources":["../src/Bits.ts"],"sourcesContent":["/**\n * Bit-level parsing (winnow's `binary::bits`, nom's `bits` module).\n *\n * Bit parsers run inside {@link bits}, which switches a byte parser into\n * bit mode. Bits are read most-significant first. When `bits` finishes, any\n * remaining bits of a partly consumed byte are skipped.\n *\n * Inside `bits`, offsets count bits, so the general combinators (`alt`,\n * `repeat`, `opt`, ...) backtrack at bit granularity.\n *\n * @example\n * ```ts\n * import { Binary, Bits, Parser } from \"@thomasfosterau/effect-parse\"\n *\n * // An IPv4 header starts with a 4-bit version and a 4-bit header length\n * const versionAndLength = Bits.bits(Parser.seq(Bits.take(4), Bits.take(4)))\n *\n * Parser.parse(versionAndLength, new Uint8Array([0x45])) // Result.succeed([4, 5])\n * ```\n *\n * @since 0.1.0\n */\nimport type { State } from \"./Input.js\"\nimport { Fail, Failure } from \"./Input.js\"\nimport type { Parser } from \"./Parser.js\"\nimport { make } from \"./Parser.js\"\nimport { checkCount } from \"./internal/node.js\"\n\ndeclare const BitInputBrand: unique symbol\n\n/**\n * The input type of bit-level parsers. A `Parser<A, E, R, BitInput>` can\n * only be run inside {@link bits}.\n *\n * @since 0.1.0\n * @category models\n */\nexport interface BitInput extends ReadonlyArray<never> {\n readonly [BitInputBrand]: true\n}\n\nconst scale = (f: Failure, factor: number): Failure =>\n new Failure(\n factor < 1 ? Math.floor(f.offset * factor) : f.offset * factor,\n f.kind,\n f.expected,\n f.context,\n f.hasCause,\n f.cause,\n f.message,\n factor < 1 ? Math.ceil(f.needed * factor) : f.needed * factor\n )\n\n/**\n * Runs `step` with offsets measured in different units (bits vs bytes),\n * converting failure offsets back to the outer units afterwards.\n */\nconst inUnits = <A>(state: State<any>, factor: number, step: (state: State<any>) => A | Fail): A | Fail => {\n const end = state.end\n const deepest = state.deepest\n state.deepest = undefined\n state.pos = factor > 1 ? state.pos * factor : Math.ceil(state.pos * factor)\n state.end = end * factor\n const a = step(state)\n state.end = end\n const inner = state.deepest\n state.deepest = deepest\n if (a === Fail) {\n state.pos = factor > 1 ? Math.floor(state.pos / factor) : state.pos / factor\n const f = state.failure\n state.failure = scale(f, 1 / factor)\n // A committed failure keeps only the failures recorded after the commit\n // (see `Parser.cut`), so none from before these units\n if (state.mode === \"Cut\") state.deepest = undefined\n if (inner !== undefined) {\n const d = inner === f ? state.failure : scale(inner, 1 / factor)\n if (state.deepest === undefined || d.offset >= state.deepest.offset) state.deepest = d\n }\n return Fail\n }\n state.pos = factor > 1 ? Math.ceil(state.pos / factor) : state.pos / factor\n if (inner !== undefined) {\n const d = scale(inner, 1 / factor)\n if (deepest === undefined || d.offset >= deepest.offset) state.deepest = d\n }\n return a\n}\n\n/**\n * Runs a bit-level parser on byte input (winnow's and nom's `bits`). After\n * success, the input advances to the next byte boundary.\n *\n * @since 0.1.0\n * @category combinators\n */\nexport const bits = <A, E, R>(self: Parser<A, E, R, BitInput>): Parser<A, E, R, Uint8Array> => {\n const step = self.step\n return make((state) => inUnits(state, 8, step), \"bits\")\n}\n\n/**\n * Runs a byte-level parser from within a bit-level parser (winnow's and\n * nom's `bytes`). The partly consumed byte, if any, is skipped first.\n *\n * @since 0.1.0\n * @category combinators\n */\nexport const bytes = <A, E, R>(self: Parser<A, E, R, Uint8Array>): Parser<A, E, R, BitInput> => {\n const step = self.step\n return make((state: State<any>) => inUnits(state, 1 / 8, step), \"bytes\")\n}\n\nconst readBits = (state: State<any>, count: number): number => {\n // SAFETY: bit-level parsers run inside `bits`, on the `Uint8Array` it was given (`BitInput` only re-indexes it in bits)\n const input = state.input as Uint8Array\n let pos = state.pos\n let value = 0\n let left = count\n // As many bits as the current byte holds at once, not one at a time\n while (left > 0) {\n const avail = 8 - (pos & 7)\n const n = left < avail ? left : avail\n // Multiplying, not shifting: the value can have up to 53 bits\n value = value * (1 << n) + ((input[pos >>> 3] >>> (avail - n)) & ((1 << n) - 1))\n pos += n\n left -= n\n }\n state.pos = pos\n return value\n}\n\n/**\n * Takes `count` bits (at most 53) as an unsigned number (winnow's and nom's\n * bit-level `take`).\n *\n * @since 0.1.0\n * @category parsers\n */\nexport const take = (count: number): Parser<number, never, never, BitInput> => {\n checkCount(count)\n if (count > 53) throw new RangeError(\"Bits.take: use Bits.takeBig for more than 53 bits\")\n const expected = [`${count} bits`]\n return make((state: State<any>) => {\n const avail = state.end - state.pos\n if (avail < count) return state.eoi(\"Bits\", expected, count - avail)\n return readBits(state, count)\n }, \"take\")\n}\n\n/**\n * Takes `count` bits as an unsigned `bigint`.\n *\n * @since 0.1.0\n * @category parsers\n */\nexport const takeBig = (count: number): Parser<bigint, never, never, BitInput> => {\n checkCount(count)\n const expected = [`${count} bits`]\n return make((state: State<any>) => {\n const avail = state.end - state.pos\n if (avail < count) return state.eoi(\"Bits\", expected, count - avail)\n let value = 0n\n let remaining = count\n while (remaining > 0) {\n const n = Math.min(remaining, 32)\n value = (value << BigInt(n)) | BigInt(readBits(state, n))\n remaining -= n\n }\n return value\n }, \"takeBig\")\n}\n\n/**\n * Matches `count` bits equal to `pattern` (winnow's `pattern`, nom's bit\n * `tag`).\n *\n * @since 0.1.0\n * @category parsers\n */\nexport const pattern = (pattern: number, count: number): Parser<number, never, never, BitInput> => {\n checkCount(count)\n const expected = [`bit pattern ${pattern.toString(2).padStart(count, \"0\")}`]\n return make((state: State<any>) => {\n const start = state.pos\n const avail = state.end - start\n if (avail < count) return state.eoi(\"Bits\", expected, count - avail)\n const value = readBits(state, count)\n if (value !== pattern) {\n state.rewind(start)\n return state.backtrack(\"Bits\", expected)\n }\n return value\n }, \"pattern\")\n}\n\n/**\n * Takes one bit as a boolean (winnow's and nom's `bool`).\n *\n * @since 0.1.0\n * @category parsers\n */\nexport const bool: Parser<boolean, never, never, BitInput> = /*#__PURE__*/ make((state: State<any>) => {\n if (state.pos >= state.end) return state.eoi(\"Bits\", [\"1 bit\"], 1)\n return readBits(state, 1) === 1\n}, \"bool\")\n"],"mappings":"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"}
|
package/dist/Compiler.d.ts
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
|
-
import { Input } from "./Input.js";
|
|
2
|
-
import { Parser } from "./Parser.js";
|
|
1
|
+
import { Fail, Input, State } from "./Input.js";
|
|
2
|
+
import { Parser, RunOptions } from "./Parser.js";
|
|
3
|
+
/**
|
|
4
|
+
* Compiles a parser with the WebAssembly compiler. Returns the same parser.
|
|
5
|
+
*
|
|
6
|
+
* The input is copied into WebAssembly memory and scanned there, by code
|
|
7
|
+
* generated from the grammar; a JavaScript function generated with
|
|
8
|
+
* `new Function` then builds the value from what the scan recorded, with
|
|
9
|
+
* the same callbacks and the same objects as the JIT. Parts of the grammar
|
|
10
|
+
* with no WebAssembly form (such as `Parser.make`, `flatMap`, or `filter`
|
|
11
|
+
* on a value) run their JIT-compiled code from inside the scan.
|
|
12
|
+
*
|
|
13
|
+
* It uses the JIT (see {@link jit}) for array input, for the streaming build
|
|
14
|
+
* of `Parser.parsePartial` and `ParserStream`, and where `WebAssembly` or
|
|
15
|
+
* `new Function` is unavailable: a Content Security Policy needs both
|
|
16
|
+
* `'wasm-unsafe-eval'` and `'unsafe-eval'` for it. Short strings with the
|
|
17
|
+
* same characters may be returned as one string, which no program can tell
|
|
18
|
+
* apart from two.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { Ascii, Compiler, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
23
|
+
*
|
|
24
|
+
* const list = Compiler.wasm(Parser.separated(Ascii.decInt, Token.literal(",")))
|
|
25
|
+
* Parser.parse(list, "1,2,3") // Result.succeed([1, 2, 3])
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @since 0.5.0
|
|
29
|
+
* @category compilation
|
|
30
|
+
*/
|
|
31
|
+
export declare const wasm: <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>;
|
|
3
32
|
/**
|
|
4
33
|
* Compiles a parser with the JIT: generated code where `new Function` is
|
|
5
34
|
* allowed, otherwise specialized closures (see {@link closure}). Returns the
|
|
@@ -34,4 +63,47 @@ export declare const jit: <A, E, R, I extends Input>(self: Parser<A, E, R, I>) =
|
|
|
34
63
|
* @category compilation
|
|
35
64
|
*/
|
|
36
65
|
export declare const closure: <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>;
|
|
66
|
+
/**
|
|
67
|
+
* Prepares a parser for running many times on states you own, as
|
|
68
|
+
* `Parser.run` does: for drivers that make one small run per token, such as
|
|
69
|
+
* a lexer over a buffer. `Parser.run` looks the parser's compiled form up
|
|
70
|
+
* on every run, which costs about a quarter of a small token's time; the
|
|
71
|
+
* function returned here looks it up once (again only when the input kind
|
|
72
|
+
* changes, or between complete and partial states) and calls the compiled
|
|
73
|
+
* code directly.
|
|
74
|
+
*
|
|
75
|
+
* It returns exactly what `Parser.run(self, state, options)` returns, and
|
|
76
|
+
* leaves the state as it would: the output with the cursor where the
|
|
77
|
+
* parser stopped, or `Fail` with the interpreter's failure (or, with
|
|
78
|
+
* `diagnostics: false`, only the mode). Compile the parser first with
|
|
79
|
+
* {@link jit} or {@link closure}; a parser that isn't compiled runs
|
|
80
|
+
* interpreted. The compiled form is looked up on the first run, so compile
|
|
81
|
+
* the parser before using the runner: compiling it again later doesn't
|
|
82
|
+
* reach a runner that has already run.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* import { Ascii, Compiler, Input, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
87
|
+
*
|
|
88
|
+
* const token = Compiler.jit(Parser.preceded(Ascii.space0, Parser.alt(Ascii.alpha1, Token.oneOf("+-"))))
|
|
89
|
+
* const next = Compiler.runner(token)
|
|
90
|
+
*
|
|
91
|
+
* const tokens = (text: string): Array<string> => {
|
|
92
|
+
* const state = new Input.State(text)
|
|
93
|
+
* const out: Array<string> = []
|
|
94
|
+
* while (state.pos < state.end) {
|
|
95
|
+
* const t = next(state.reset(state.pos))
|
|
96
|
+
* if (t === Input.Fail) break
|
|
97
|
+
* out.push(t)
|
|
98
|
+
* }
|
|
99
|
+
* return out
|
|
100
|
+
* }
|
|
101
|
+
*
|
|
102
|
+
* tokens("a + b") // ["a", "+", "b"]
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @since 0.5.0
|
|
106
|
+
* @category running
|
|
107
|
+
*/
|
|
108
|
+
export declare const runner: <A, E, R, I extends Input>(self: Parser<A, E, R, I>, options?: RunOptions) => ((state: State<I>) => A | Fail);
|
|
37
109
|
//# sourceMappingURL=Compiler.d.ts.map
|
package/dist/Compiler.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Compiler.d.ts","names":[],"sources":["../src/Compiler.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Compiler.d.ts","names":[],"sources":["../src/Compiler.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAgGa,OAAQ,GAAG,GAAG,GAAG,UAAU,OAAO,MAAM,OAAO,GAAG,GAAG,GAAG,OAAK,OAAO,GAAG,GAAG,GAAG;;;;;;;;;;;;;;;;;qBAqB7E,MAAO,GAAG,GAAG,GAAG,UAAU,OAAO,MAAM,OAAO,GAAG,GAAG,GAAG,OAAK,OAAO,GAAG,GAAG,GAAG;;;;;;;;;;;;;;;;;qBAqB5E,UAAW,GAAG,GAAG,GAAG,UAAU,OAAO,MAAM,OAAO,GAAG,GAAG,GAAG,OAAK,OAAO,GAAG,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA+ChF,SAAU,GAAG,GAAG,GAAG,UAAU,OACxC,MAAM,OAAO,GAAG,GAAG,GAAG,IACtB,UAAU,iBACP,OAAO,MAAM,OAAO,IAAI"}
|
package/dist/Compiler.js
CHANGED
|
@@ -1,8 +1,42 @@
|
|
|
1
1
|
import { backend } from "./internal/compiler/closure.js";
|
|
2
2
|
import { backend as backend$1 } from "./internal/compiler/jit.js";
|
|
3
3
|
import { register } from "./internal/compiler/registry.js";
|
|
4
|
+
import { backend as backend$2 } from "./internal/compiler/wasm.js";
|
|
5
|
+
import { prepare } from "./internal/run.js";
|
|
4
6
|
// src/Compiler.ts
|
|
5
7
|
/**
|
|
8
|
+
* Compiles a parser with the WebAssembly compiler. Returns the same parser.
|
|
9
|
+
*
|
|
10
|
+
* The input is copied into WebAssembly memory and scanned there, by code
|
|
11
|
+
* generated from the grammar; a JavaScript function generated with
|
|
12
|
+
* `new Function` then builds the value from what the scan recorded, with
|
|
13
|
+
* the same callbacks and the same objects as the JIT. Parts of the grammar
|
|
14
|
+
* with no WebAssembly form (such as `Parser.make`, `flatMap`, or `filter`
|
|
15
|
+
* on a value) run their JIT-compiled code from inside the scan.
|
|
16
|
+
*
|
|
17
|
+
* It uses the JIT (see {@link jit}) for array input, for the streaming build
|
|
18
|
+
* of `Parser.parsePartial` and `ParserStream`, and where `WebAssembly` or
|
|
19
|
+
* `new Function` is unavailable: a Content Security Policy needs both
|
|
20
|
+
* `'wasm-unsafe-eval'` and `'unsafe-eval'` for it. Short strings with the
|
|
21
|
+
* same characters may be returned as one string, which no program can tell
|
|
22
|
+
* apart from two.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { Ascii, Compiler, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
27
|
+
*
|
|
28
|
+
* const list = Compiler.wasm(Parser.separated(Ascii.decInt, Token.literal(",")))
|
|
29
|
+
* Parser.parse(list, "1,2,3") // Result.succeed([1, 2, 3])
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @since 0.5.0
|
|
33
|
+
* @category compilation
|
|
34
|
+
*/
|
|
35
|
+
const wasm = (self) => {
|
|
36
|
+
register(self, backend$2);
|
|
37
|
+
return self;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
6
40
|
* Compiles a parser with the JIT: generated code where `new Function` is
|
|
7
41
|
* allowed, otherwise specialized closures (see {@link closure}). Returns the
|
|
8
42
|
* same parser.
|
|
@@ -42,6 +76,49 @@ const closure = (self) => {
|
|
|
42
76
|
register(self, backend);
|
|
43
77
|
return self;
|
|
44
78
|
};
|
|
45
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Prepares a parser for running many times on states you own, as
|
|
81
|
+
* `Parser.run` does: for drivers that make one small run per token, such as
|
|
82
|
+
* a lexer over a buffer. `Parser.run` looks the parser's compiled form up
|
|
83
|
+
* on every run, which costs about a quarter of a small token's time; the
|
|
84
|
+
* function returned here looks it up once (again only when the input kind
|
|
85
|
+
* changes, or between complete and partial states) and calls the compiled
|
|
86
|
+
* code directly.
|
|
87
|
+
*
|
|
88
|
+
* It returns exactly what `Parser.run(self, state, options)` returns, and
|
|
89
|
+
* leaves the state as it would: the output with the cursor where the
|
|
90
|
+
* parser stopped, or `Fail` with the interpreter's failure (or, with
|
|
91
|
+
* `diagnostics: false`, only the mode). Compile the parser first with
|
|
92
|
+
* {@link jit} or {@link closure}; a parser that isn't compiled runs
|
|
93
|
+
* interpreted. The compiled form is looked up on the first run, so compile
|
|
94
|
+
* the parser before using the runner: compiling it again later doesn't
|
|
95
|
+
* reach a runner that has already run.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* import { Ascii, Compiler, Input, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
100
|
+
*
|
|
101
|
+
* const token = Compiler.jit(Parser.preceded(Ascii.space0, Parser.alt(Ascii.alpha1, Token.oneOf("+-"))))
|
|
102
|
+
* const next = Compiler.runner(token)
|
|
103
|
+
*
|
|
104
|
+
* const tokens = (text: string): Array<string> => {
|
|
105
|
+
* const state = new Input.State(text)
|
|
106
|
+
* const out: Array<string> = []
|
|
107
|
+
* while (state.pos < state.end) {
|
|
108
|
+
* const t = next(state.reset(state.pos))
|
|
109
|
+
* if (t === Input.Fail) break
|
|
110
|
+
* out.push(t)
|
|
111
|
+
* }
|
|
112
|
+
* return out
|
|
113
|
+
* }
|
|
114
|
+
*
|
|
115
|
+
* tokens("a + b") // ["a", "+", "b"]
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* @since 0.5.0
|
|
119
|
+
* @category running
|
|
120
|
+
*/
|
|
121
|
+
const runner = (self, options) => prepare(self, self.step, options?.diagnostics !== false);
|
|
122
|
+
export { closure, jit, runner, wasm };
|
|
46
123
|
|
|
47
124
|
//# sourceMappingURL=Compiler.js.map
|
package/dist/Compiler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Compiler.js","names":["jitBackend","closureBackend"],"sources":["../src/Compiler.ts"],"sourcesContent":["/**\n * Compiles parsers into fused, specialized code. Grammars are written as\n * usual; compiling the root of a grammar only makes `Parser.parse`,\n * `Parser.parseSync`, `Parser.parsePeek`, `Parser.parsePartial` and\n * `Parser.parseEffect` faster, from any `offset`.\n *\n * There are
|
|
1
|
+
{"version":3,"file":"Compiler.js","names":["wasmBackend","jitBackend","closureBackend"],"sources":["../src/Compiler.ts"],"sourcesContent":["/**\n * Compiles parsers into fused, specialized code. Grammars are written as\n * usual; compiling the root of a grammar only makes `Parser.parse`,\n * `Parser.parseSync`, `Parser.parsePeek`, `Parser.parsePartial` and\n * `Parser.parseEffect` faster, from any `offset`.\n *\n * There are three compilers, one function each, so a program bundles only\n * the ones it uses, and a program that compiles nothing bundles none:\n *\n * - {@link wasm} scans the input in WebAssembly and builds the value with\n * generated JavaScript. It is the fastest on strings and bytes, and uses\n * the JIT for array input and streaming, and where WebAssembly or\n * `new Function` is unavailable.\n * - {@link jit} generates code with `new Function` where it is allowed, and\n * otherwise uses the closure compiler.\n * - {@link closure} builds specialized closures only. It never generates\n * code, and a bundle that uses only it contains no `new Function`, so it\n * is the choice under a Content Security Policy, where even probing for\n * `new Function` is reported as a violation.\n *\n * ```ts\n * import { Ascii, Compiler, Parser, Token } from \"@thomasfosterau/effect-parse\"\n *\n * export const list = Compiler.jit(\n * Parser.separated(Ascii.decInt, Token.literal(\",\"))\n * )\n * Parser.parse(list, \"1,2,3\") // Result.succeed([1, 2, 3]), compiled\n * ```\n *\n * Both return the same parser, so they also work in a pipe:\n * `p.pipe(Compiler.closure)`. The code is built lazily on the first run, for\n * each kind of input (string, bytes or array), and cached with the parser.\n * Compiling a parser again, with either function, replaces its compiled\n * form.\n *\n * **Results and errors are unchanged.** Compiled code records no\n * diagnostics. When it fails, the parser runs again, interpreted, from the\n * same offset, so every `ParseError` (offset, expected, context, cause and\n * message) is exactly the one the interpreter reports. Running out of\n * partial input is not a failure that needs it: compiled code reports\n * `Incomplete` where the interpreter does, with the same `needed`.\n *\n * **Callbacks should be pure.** On an input that fails, the callbacks given\n * to `map`, `filter`, `tryMap`, `tap`, `fold`, ... may run twice, once\n * compiled and once interpreted. Callbacks whose results are discarded\n * (a `map` inside `taken` or `preceded`, for example) may not run at all,\n * nor those of a branch that is certain to fail, and token-set predicates\n * may be called once per character code and cached.\n *\n * `Parser.parsePartial`, `ParserStream.parseAll` and\n * `ParserStream.parseMany` run a build that handles partial input;\n * `parseMany` runs it once per value and parses a value again, interpreted,\n * only when it fails. `Parser.parseRecoverable`, `Syntax`\n * parses and runs with the `trace` option are always interpreted. Parsers that\n * can't be described, such as `Parser.make` and `Parser.gen`, run\n * interpreted inside compiled code; the parsers given to a\n * `Parser.combinator` compile, and its step is built from theirs.\n *\n * @since 0.2.0\n */\nimport type { Fail, Input, State } from \"./Input.js\"\nimport type { Parser, RunOptions } from \"./Parser.js\"\nimport { backend as closureBackend } from \"./internal/compiler/closure.js\"\nimport { backend as jitBackend } from \"./internal/compiler/jit.js\"\nimport { register } from \"./internal/compiler/registry.js\"\nimport { backend as wasmBackend } from \"./internal/compiler/wasm.js\"\nimport { prepare } from \"./internal/run.js\"\n\n/**\n * Compiles a parser with the WebAssembly compiler. Returns the same parser.\n *\n * The input is copied into WebAssembly memory and scanned there, by code\n * generated from the grammar; a JavaScript function generated with\n * `new Function` then builds the value from what the scan recorded, with\n * the same callbacks and the same objects as the JIT. Parts of the grammar\n * with no WebAssembly form (such as `Parser.make`, `flatMap`, or `filter`\n * on a value) run their JIT-compiled code from inside the scan.\n *\n * It uses the JIT (see {@link jit}) for array input, for the streaming build\n * of `Parser.parsePartial` and `ParserStream`, and where `WebAssembly` or\n * `new Function` is unavailable: a Content Security Policy needs both\n * `'wasm-unsafe-eval'` and `'unsafe-eval'` for it. Short strings with the\n * same characters may be returned as one string, which no program can tell\n * apart from two.\n *\n * @example\n * ```ts\n * import { Ascii, Compiler, Parser, Token } from \"@thomasfosterau/effect-parse\"\n *\n * const list = Compiler.wasm(Parser.separated(Ascii.decInt, Token.literal(\",\")))\n * Parser.parse(list, \"1,2,3\") // Result.succeed([1, 2, 3])\n * ```\n *\n * @since 0.5.0\n * @category compilation\n */\nexport const wasm = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> => {\n register(self, wasmBackend)\n return self\n}\n\n/**\n * Compiles a parser with the JIT: generated code where `new Function` is\n * allowed, otherwise specialized closures (see {@link closure}). Returns the\n * same parser.\n *\n * @example\n * ```ts\n * import { Ascii, Compiler, Parser, Token } from \"@thomasfosterau/effect-parse\"\n *\n * const list = Compiler.jit(Parser.separated(Ascii.decInt, Token.literal(\",\")))\n * Parser.parse(list, \"1,2,3\") // Result.succeed([1, 2, 3])\n * ```\n *\n * @since 0.2.0\n * @category compilation\n */\nexport const jit = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> => {\n register(self, jitBackend)\n return self\n}\n\n/**\n * Compiles a parser into specialized closures. Returns the same parser.\n * Nothing is generated, so it works under a Content Security Policy, and a\n * bundle that compiles only with `closure` contains no `new Function`.\n *\n * @example\n * ```ts\n * import { Ascii, Compiler, Parser, Token } from \"@thomasfosterau/effect-parse\"\n *\n * const list = Compiler.closure(Parser.separated(Ascii.decInt, Token.literal(\",\")))\n * Parser.parse(list, \"1,2,3\") // Result.succeed([1, 2, 3])\n * ```\n *\n * @since 0.2.0\n * @category compilation\n */\nexport const closure = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> => {\n register(self, closureBackend)\n return self\n}\n\n/**\n * Prepares a parser for running many times on states you own, as\n * `Parser.run` does: for drivers that make one small run per token, such as\n * a lexer over a buffer. `Parser.run` looks the parser's compiled form up\n * on every run, which costs about a quarter of a small token's time; the\n * function returned here looks it up once (again only when the input kind\n * changes, or between complete and partial states) and calls the compiled\n * code directly.\n *\n * It returns exactly what `Parser.run(self, state, options)` returns, and\n * leaves the state as it would: the output with the cursor where the\n * parser stopped, or `Fail` with the interpreter's failure (or, with\n * `diagnostics: false`, only the mode). Compile the parser first with\n * {@link jit} or {@link closure}; a parser that isn't compiled runs\n * interpreted. The compiled form is looked up on the first run, so compile\n * the parser before using the runner: compiling it again later doesn't\n * reach a runner that has already run.\n *\n * @example\n * ```ts\n * import { Ascii, Compiler, Input, Parser, Token } from \"@thomasfosterau/effect-parse\"\n *\n * const token = Compiler.jit(Parser.preceded(Ascii.space0, Parser.alt(Ascii.alpha1, Token.oneOf(\"+-\"))))\n * const next = Compiler.runner(token)\n *\n * const tokens = (text: string): Array<string> => {\n * const state = new Input.State(text)\n * const out: Array<string> = []\n * while (state.pos < state.end) {\n * const t = next(state.reset(state.pos))\n * if (t === Input.Fail) break\n * out.push(t)\n * }\n * return out\n * }\n *\n * tokens(\"a + b\") // [\"a\", \"+\", \"b\"]\n * ```\n *\n * @since 0.5.0\n * @category running\n */\nexport const runner = <A, E, R, I extends Input>(\n self: Parser<A, E, R, I>,\n options?: RunOptions\n): ((state: State<I>) => A | Fail) => prepare(self, self.step, options?.diagnostics !== false)\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgGA,MAAa,QAAkC,SAAiD;CAC9F,SAAS,MAAMA,SAAW;CAC1B,OAAO;AACT;;;;;;;;;;;;;;;;;AAkBA,MAAa,OAAiC,SAAiD;CAC7F,SAAS,MAAMC,SAAU;CACzB,OAAO;AACT;;;;;;;;;;;;;;;;;AAkBA,MAAa,WAAqC,SAAiD;CACjG,SAAS,MAAMC,OAAc;CAC7B,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,MAAa,UACX,MACA,YACoC,QAAQ,MAAM,KAAK,MAAM,SAAS,gBAAgB,KAAK"}
|
package/dist/Expression.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Expression.d.ts","names":[],"sources":["../src/Expression.ts"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"Expression.d.ts","names":[],"sources":["../src/Expression.ts"],"mappings":";;;;;;;;YAoDY,SAAS,GAAG,WAAW,WAAW,UAAU,kBACpD,OAAO,GAAG,GAAG,GAAG,KAChB,QAAQ,GAAG,GAAG,GAAG,KACjB,MAAM,GAAG,GAAG,GAAG;UAET,aAAa,GAAG,GAAG,UAAU;WAC5B,QAAQ,gBAAgB,GAAG,GAAG;WAC9B;;;;;;iBAOM,OAAO,GAAG,WAAW,WAAW,UAAU,wBAAwB,aAAa,GAAG,GAAG;WAC3F;WACA,OAAO,SAAS,SAAS,MAAM;;;;;;iBAOzB,QAAQ,GAAG,WAAW,WAAW,UAAU,wBAAwB,aAAa,GAAG,GAAG;WAC5F;WACA,OAAO,SAAS,GAAG,YAAY;;;;;;iBAOzB,MAAM,GAAG,WAAW,WAAW,UAAU,wBAAwB,aAAa,GAAG,GAAG;WAC1F;WACA;WACA,OAAO,MAAM,GAAG,SAAS,OAAO,MAAM;;;;;;;;qBASpC,SAAU,GAAG,GAAG,GAAG,UAAU,OAAO,GAC/C,QAAQ,OAAO,GAAG,GAAG,GAAG,IACxB,oBACA,OAAO,IAAI,GAAG,SAAS,MAAM,MAC5B,OAAO,GAAG,GAAG,GAAG;;;;;;;qBAQN,UAAW,GAAG,GAAG,GAAG,UAAU,OAAO,GAChD,QAAQ,OAAO,GAAG,GAAG,GAAG,IACxB,oBACA,OAAO,SAAS,GAAG,IAAI,MAAM,MAC5B,QAAQ,GAAG,GAAG,GAAG;;;;;;;qBAQP,YAAa,GAAG,GAAG,GAAG,UAAU,OAAO,GAClD,QAAQ,OAAO,GAAG,GAAG,GAAG,IACxB,oBACA,OAAO,MAAM,GAAG,IAAI,GAAG,OAAO,MAAM,MACnC,MAAM,GAAG,GAAG,GAAG;;;;;;;qBAQL,aAAc,GAAG,GAAG,GAAG,UAAU,OAAO,GACnD,QAAQ,OAAO,GAAG,GAAG,GAAG,IACxB,oBACA,OAAO,MAAM,GAAG,IAAI,GAAG,OAAO,MAAM,MACnC,MAAM,GAAG,GAAG,GAAG;KAEb,QAAQ,MAAM,WAAW,mBAAmB,SAAS,UAAU,MAAM;KACrE,WAAW,MAAM,WAAW,mBAAmB,UAAU,SAAS,MAAM;KACxE,QAAQ,OAAO,sBAAsB,SAAS,aAAa,mBAAmB,UAAU,UAAU,MAAM;;;;;;;;;;;;;;qBAehG,OAAQ,GAAG,GAAG,GAAG,UAAU,aAAa,YAAY,cAAc,SAAS,oBAAoB;WACjG,SAAS,OAAO,GAAG,GAAG,GAAG;WACzB,WAAW;MAClB,OAAO,GAAG,IAAI,QAAQ,cAAc,IAAI,WAAW,cAAc,IAAI,QAAQ"}
|
package/dist/Expression.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as Predicate from "effect/Predicate";
|
|
2
2
|
import { Fail } from "./Input.js";
|
|
3
|
-
import {
|
|
3
|
+
import { combinator } from "./Parser.js";
|
|
4
4
|
import { TiedFailures } from "./internal/ties.js";
|
|
5
5
|
// src/Expression.ts
|
|
6
6
|
/**
|
|
@@ -103,91 +103,103 @@ const infixRight = (parser, precedence, fold) => ({
|
|
|
103
103
|
* @category constructors
|
|
104
104
|
*/
|
|
105
105
|
const make = (options) => {
|
|
106
|
-
const operand = options.operand.step;
|
|
107
106
|
const prefixes = options.operators.filter((o) => Predicate.isTagged(o, "Prefix"));
|
|
108
107
|
const postfixes = options.operators.filter((o) => Predicate.isTagged(o, "Postfix"));
|
|
109
108
|
const infixes = options.operators.filter((o) => Predicate.isTagged(o, "Infix"));
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
109
|
+
const operators = [
|
|
110
|
+
...prefixes,
|
|
111
|
+
...postfixes,
|
|
112
|
+
...infixes
|
|
113
|
+
];
|
|
114
|
+
const parsers = [options.operand, ...operators.map((o) => o.parser)];
|
|
115
|
+
const build = (steps) => {
|
|
116
|
+
const operand = steps[0];
|
|
117
|
+
const prefixSteps = steps.slice(1, 1 + prefixes.length);
|
|
118
|
+
const postfixSteps = steps.slice(1 + prefixes.length, 1 + prefixes.length + postfixes.length);
|
|
119
|
+
const infixSteps = steps.slice(1 + prefixes.length + postfixes.length);
|
|
120
|
+
let matched;
|
|
121
|
+
const failures = new TiedFailures();
|
|
122
|
+
const tryOps = (state, ops, mustConsume) => {
|
|
123
|
+
const start = state.pos;
|
|
124
|
+
for (let i = 0; i < ops.length; i++) {
|
|
125
|
+
const out = ops[i](state);
|
|
126
|
+
if (out !== Fail) {
|
|
127
|
+
if (mustConsume && state.pos === start) {
|
|
128
|
+
state.failMessage("Cut", "Assert", "prefix and postfix operators must always consume");
|
|
129
|
+
return -2;
|
|
130
|
+
}
|
|
131
|
+
matched = out;
|
|
132
|
+
return i;
|
|
120
133
|
}
|
|
121
|
-
|
|
122
|
-
|
|
134
|
+
if (state.mode !== "Backtrack") return -2;
|
|
135
|
+
state.rewind(start);
|
|
136
|
+
failures.add(state);
|
|
123
137
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
failures.add(state);
|
|
152
|
-
failures.fail(state);
|
|
138
|
+
return -1;
|
|
139
|
+
};
|
|
140
|
+
const expr = (state, minPower) => {
|
|
141
|
+
let lhs;
|
|
142
|
+
failures.clear();
|
|
143
|
+
const p = tryOps(state, prefixSteps, true);
|
|
144
|
+
if (p === -2) return Fail;
|
|
145
|
+
if (p >= 0) {
|
|
146
|
+
const op = prefixes[p];
|
|
147
|
+
const opOut = matched;
|
|
148
|
+
const operandValue = expr(state, op.precedence * 2);
|
|
149
|
+
if (operandValue === Fail) return Fail;
|
|
150
|
+
lhs = op.fold(opOut, operandValue);
|
|
151
|
+
} else {
|
|
152
|
+
const prefixFailure = failures.failure;
|
|
153
|
+
const prefixTie1 = failures.tie1;
|
|
154
|
+
const prefixTie2 = failures.tie2;
|
|
155
|
+
lhs = operand(state);
|
|
156
|
+
if (lhs === Fail) {
|
|
157
|
+
if (prefixFailure !== void 0 && state.mode === "Backtrack") {
|
|
158
|
+
failures.failure = prefixFailure;
|
|
159
|
+
failures.tie1 = prefixTie1;
|
|
160
|
+
failures.tie2 = prefixTie2;
|
|
161
|
+
failures.add(state);
|
|
162
|
+
failures.fail(state);
|
|
163
|
+
}
|
|
164
|
+
return Fail;
|
|
153
165
|
}
|
|
154
|
-
return Fail;
|
|
155
166
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
167
|
+
while (true) {
|
|
168
|
+
const start = state.pos;
|
|
169
|
+
failures.clear();
|
|
170
|
+
const q = tryOps(state, postfixSteps, true);
|
|
171
|
+
if (q === -2) return Fail;
|
|
172
|
+
if (q >= 0) {
|
|
173
|
+
const op = postfixes[q];
|
|
174
|
+
if (op.precedence * 2 < minPower) {
|
|
175
|
+
state.rewind(start);
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
lhs = op.fold(lhs, matched);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const i = tryOps(state, infixSteps, false);
|
|
182
|
+
if (i === -2) return Fail;
|
|
183
|
+
if (i < 0) {
|
|
184
|
+
failures.hint(state);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
const op = infixes[i];
|
|
188
|
+
const leftPower = op.precedence * 2;
|
|
189
|
+
if (leftPower < minPower) {
|
|
165
190
|
state.rewind(start);
|
|
166
191
|
break;
|
|
167
192
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (i === -2) return Fail;
|
|
173
|
-
if (i < 0) {
|
|
174
|
-
failures.hint(state);
|
|
175
|
-
break;
|
|
176
|
-
}
|
|
177
|
-
const op = infixes[i];
|
|
178
|
-
const leftPower = op.precedence * 2;
|
|
179
|
-
if (leftPower < minPower) {
|
|
180
|
-
state.rewind(start);
|
|
181
|
-
break;
|
|
193
|
+
const opOut = matched;
|
|
194
|
+
const rhs = expr(state, op.associativity === "left" ? leftPower + 1 : leftPower);
|
|
195
|
+
if (rhs === Fail) return Fail;
|
|
196
|
+
lhs = op.fold(lhs, opOut, rhs);
|
|
182
197
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
lhs = op.fold(lhs, opOut, rhs);
|
|
187
|
-
}
|
|
188
|
-
return lhs;
|
|
198
|
+
return lhs;
|
|
199
|
+
};
|
|
200
|
+
return (state) => expr(state, 0);
|
|
189
201
|
};
|
|
190
|
-
return
|
|
202
|
+
return combinator(parsers, build, "expression");
|
|
191
203
|
};
|
|
192
204
|
export { infixLeft, infixRight, make, postfix, prefix };
|
|
193
205
|
|
package/dist/Expression.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Expression.js","names":["makeParser"],"sources":["../src/Expression.ts"],"sourcesContent":["/**\n * Operator-precedence expression parsing with a Pratt parser (from\n * `nom-language`'s `precedence`, and winnow's expression parser).\n *\n * Describe the operand parser and a table of prefix, postfix and infix\n * operators with their precedence (higher binds tighter) and associativity.\n * Each operator carries a function that folds its operands into a result.\n *\n * @example\n * ```ts\n * import { Ascii, Expression, Parser, Token } from \"@thomasfosterau/effect-parse\"\n *\n * const op = (s: string) => Parser.delimited(Ascii.space0, Token.literal(s), Ascii.space0)\n *\n * const arithmetic: Parser.Parser<number, string> = Expression.make({\n * operand: Parser.alt(\n * Ascii.decInt,\n * Parser.delimited(op(\"(\"), Parser.suspend(() => arithmetic), op(\")\"))\n * ),\n * operators: [\n * Expression.prefix(op(\"-\"), 4, (_, x) => -x),\n * Expression.postfix(op(\"!\"), 5, (x) => factorial(x)),\n * Expression.infixRight(op(\"^\"), 3, (l, _, r) => l ** r),\n * Expression.infixLeft(op(\"*\"), 2, (l, _, r) => l * r),\n * Expression.infixLeft(op(\"/\"), 2, (l, _, r) => l / r),\n * Expression.infixLeft(op(\"+\"), 1, (l, _, r) => l + r),\n * Expression.infixLeft(op(\"-\"), 1, (l, _, r) => l - r)\n * ]\n * })\n *\n * declare const factorial: (n: number) => number\n * Parser.parse(arithmetic, \"1 + 2 * 3 ^ 2\") // Result.succeed(19)\n * ```\n *\n * @since 0.1.0\n */\nimport * as Predicate from \"effect/Predicate\"\nimport type { Input, State } from \"./Input.js\"\nimport { Fail } from \"./Input.js\"\nimport type { Parser } from \"./Parser.js\"\nimport { make as makeParser } from \"./Parser.js\"\nimport { TiedFailures } from \"./internal/ties.js\"\n\n/**\n * An operator in an expression grammar.\n *\n * @since 0.1.0\n * @category models\n */\nexport type Operator<A, E = never, R = never, I extends Input = string> =\n | Prefix<A, E, R, I>\n | Postfix<A, E, R, I>\n | Infix<A, E, R, I>\n\ninterface OperatorBase<E, R, I extends Input> {\n readonly parser: Parser<unknown, E, R, I>\n readonly precedence: number\n}\n\n/**\n * @since 0.1.0\n * @category models\n */\nexport interface Prefix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {\n readonly _tag: \"Prefix\"\n readonly fold: (op: any, operand: A) => A\n}\n\n/**\n * @since 0.1.0\n * @category models\n */\nexport interface Postfix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {\n readonly _tag: \"Postfix\"\n readonly fold: (operand: A, op: any) => A\n}\n\n/**\n * @since 0.1.0\n * @category models\n */\nexport interface Infix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {\n readonly _tag: \"Infix\"\n readonly associativity: \"left\" | \"right\"\n readonly fold: (left: A, op: any, right: A) => A\n}\n\n/**\n * A prefix operator, e.g. unary minus.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const prefix = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (op: O, operand: A) => A\n): Prefix<A, E, R, I> => ({ _tag: \"Prefix\", parser, precedence, fold })\n\n/**\n * A postfix operator, e.g. factorial or a function call suffix.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const postfix = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (operand: A, op: O) => A\n): Postfix<A, E, R, I> => ({ _tag: \"Postfix\", parser, precedence, fold })\n\n/**\n * A left-associative infix operator: `a - b - c` is `(a - b) - c`.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const infixLeft = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (left: A, op: O, right: A) => A\n): Infix<A, E, R, I> => ({ _tag: \"Infix\", associativity: \"left\", parser, precedence, fold })\n\n/**\n * A right-associative infix operator: `a ^ b ^ c` is `a ^ (b ^ c)`.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const infixRight = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (left: A, op: O, right: A) => A\n): Infix<A, E, R, I> => ({ _tag: \"Infix\", associativity: \"right\", parser, precedence, fold })\n\ntype OpError<Op> = Op extends OperatorBase<infer E, infer _R, infer _I> ? E : never\ntype OpServices<Op> = Op extends OperatorBase<infer _E, infer R, infer _I> ? R : never\ntype OpInput<Op> = [Op] extends [never] ? Input : [Op] extends [OperatorBase<infer _E, infer _R, infer I>] ? I : never\n\n/**\n * Builds an expression parser from an operand parser and an operator table.\n *\n * Precedences are compared numerically: higher binds tighter. A prefix\n * operator applies to everything that binds tighter than it, so with `-`\n * at precedence 4 and `^` at 3, `-2 ^ 2` parses as `(-2) ^ 2`.\n *\n * When several operators of the same kind match, the first one in the\n * table wins, so list longer operators (`<=`) before their prefixes (`<`).\n *\n * @since 0.1.0\n * @category constructors\n */\nexport const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<Operator<A, any, any, any>>>(options: {\n readonly operand: Parser<A, E, R, I>\n readonly operators: Ops\n}): Parser<A, E | OpError<Ops[number]>, R | OpServices<Ops[number]>, I & OpInput<Ops[number]>> => {\n const operand = options.operand.step\n const prefixes = options.operators.filter((o): o is Prefix<A, any, any, any> => Predicate.isTagged(o, \"Prefix\"))\n const postfixes = options.operators.filter((o): o is Postfix<A, any, any, any> => Predicate.isTagged(o, \"Postfix\"))\n const infixes = options.operators.filter((o): o is Infix<A, any, any, any> => Predicate.isTagged(o, \"Infix\"))\n\n // Attempts each operator in turn. Returns the index of the first match\n // (with its output in `matched`), -1 if none matched, or -2 on a fatal\n // failure. Failed attempts are folded into `failures`, merged only when\n // read (#44): a round in which an operator matches discards them unmerged.\n // Like `matched`, it is shared by nested expressions, which clear it.\n let matched: unknown\n const failures = new TiedFailures()\n const tryOps = (state: State<any>, ops: ReadonlyArray<OperatorBase<any, any, any>>, mustConsume: boolean): number => {\n const start = state.pos\n for (let i = 0; i < ops.length; i++) {\n const out = ops[i].parser.step(state)\n if (out !== Fail) {\n // A prefix or postfix operator matching nothing would apply forever\n if (mustConsume && state.pos === start) {\n state.failMessage(\"Cut\", \"Assert\", \"prefix and postfix operators must always consume\")\n return -2\n }\n matched = out\n return i\n }\n if (state.mode !== \"Backtrack\") return -2\n state.rewind(start)\n failures.add(state)\n }\n return -1\n }\n\n const expr = (state: State<any>, minPower: number): A | Fail => {\n let lhs: A | Fail\n failures.clear()\n const p = tryOps(state, prefixes, true)\n if (p === -2) return Fail\n if (p >= 0) {\n const op = prefixes[p]\n const opOut = matched\n const operandValue = expr(state, op.precedence * 2)\n if (operandValue === Fail) return Fail\n lhs = op.fold(opOut, operandValue)\n } else {\n const prefixFailure = failures.failure\n const prefixTie1 = failures.tie1\n const prefixTie2 = failures.tie2\n lhs = operand(state)\n if (lhs === Fail) {\n if (prefixFailure !== undefined && state.mode === \"Backtrack\") {\n // The operand may have parsed nested expressions, which reuse `failures`\n failures.failure = prefixFailure\n failures.tie1 = prefixTie1\n failures.tie2 = prefixTie2\n failures.add(state)\n failures.fail(state)\n }\n return Fail\n }\n }\n\n while (true) {\n const start = state.pos\n failures.clear()\n const q = tryOps(state, postfixes, true)\n if (q === -2) return Fail\n if (q >= 0) {\n const op = postfixes[q]\n if (op.precedence * 2 < minPower) {\n state.rewind(start)\n break\n }\n lhs = op.fold(lhs, matched)\n continue\n }\n // The infix attempts are folded on top of the postfix ones\n const i = tryOps(state, infixes, false)\n if (i === -2) return Fail\n if (i < 0) {\n failures.hint(state)\n break\n }\n const op = infixes[i]\n const leftPower = op.precedence * 2\n if (leftPower < minPower) {\n state.rewind(start)\n break\n }\n const opOut = matched\n const rhs = expr(state, op.associativity === \"left\" ? leftPower + 1 : leftPower)\n if (rhs === Fail) return Fail\n lhs = op.fold(lhs, opOut, rhs)\n }\n return lhs\n }\n\n return makeParser((state: State<any>) => expr(state, 0), \"expression\")\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Expression.js","names":[],"sources":["../src/Expression.ts"],"sourcesContent":["/**\n * Operator-precedence expression parsing with a Pratt parser (from\n * `nom-language`'s `precedence`, and winnow's expression parser).\n *\n * Describe the operand parser and a table of prefix, postfix and infix\n * operators with their precedence (higher binds tighter) and associativity.\n * Each operator carries a function that folds its operands into a result.\n *\n * @example\n * ```ts\n * import { Ascii, Expression, Parser, Token } from \"@thomasfosterau/effect-parse\"\n *\n * const op = (s: string) => Parser.delimited(Ascii.space0, Token.literal(s), Ascii.space0)\n *\n * const arithmetic: Parser.Parser<number, string> = Expression.make({\n * operand: Parser.alt(\n * Ascii.decInt,\n * Parser.delimited(op(\"(\"), Parser.suspend(() => arithmetic), op(\")\"))\n * ),\n * operators: [\n * Expression.prefix(op(\"-\"), 4, (_, x) => -x),\n * Expression.postfix(op(\"!\"), 5, (x) => factorial(x)),\n * Expression.infixRight(op(\"^\"), 3, (l, _, r) => l ** r),\n * Expression.infixLeft(op(\"*\"), 2, (l, _, r) => l * r),\n * Expression.infixLeft(op(\"/\"), 2, (l, _, r) => l / r),\n * Expression.infixLeft(op(\"+\"), 1, (l, _, r) => l + r),\n * Expression.infixLeft(op(\"-\"), 1, (l, _, r) => l - r)\n * ]\n * })\n *\n * declare const factorial: (n: number) => number\n * Parser.parse(arithmetic, \"1 + 2 * 3 ^ 2\") // Result.succeed(19)\n * ```\n *\n * @since 0.1.0\n */\nimport * as Predicate from \"effect/Predicate\"\nimport type { Input, State } from \"./Input.js\"\nimport { Fail } from \"./Input.js\"\nimport type { Parser } from \"./Parser.js\"\nimport { combinator } from \"./Parser.js\"\n\n/** A parser's step, interpreted or compiled. */\ntype Step = (state: State<any>) => unknown\nimport { TiedFailures } from \"./internal/ties.js\"\n\n/**\n * An operator in an expression grammar.\n *\n * @since 0.1.0\n * @category models\n */\nexport type Operator<A, E = never, R = never, I extends Input = string> =\n | Prefix<A, E, R, I>\n | Postfix<A, E, R, I>\n | Infix<A, E, R, I>\n\ninterface OperatorBase<E, R, I extends Input> {\n readonly parser: Parser<unknown, E, R, I>\n readonly precedence: number\n}\n\n/**\n * @since 0.1.0\n * @category models\n */\nexport interface Prefix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {\n readonly _tag: \"Prefix\"\n readonly fold: (op: any, operand: A) => A\n}\n\n/**\n * @since 0.1.0\n * @category models\n */\nexport interface Postfix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {\n readonly _tag: \"Postfix\"\n readonly fold: (operand: A, op: any) => A\n}\n\n/**\n * @since 0.1.0\n * @category models\n */\nexport interface Infix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {\n readonly _tag: \"Infix\"\n readonly associativity: \"left\" | \"right\"\n readonly fold: (left: A, op: any, right: A) => A\n}\n\n/**\n * A prefix operator, e.g. unary minus.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const prefix = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (op: O, operand: A) => A\n): Prefix<A, E, R, I> => ({ _tag: \"Prefix\", parser, precedence, fold })\n\n/**\n * A postfix operator, e.g. factorial or a function call suffix.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const postfix = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (operand: A, op: O) => A\n): Postfix<A, E, R, I> => ({ _tag: \"Postfix\", parser, precedence, fold })\n\n/**\n * A left-associative infix operator: `a - b - c` is `(a - b) - c`.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const infixLeft = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (left: A, op: O, right: A) => A\n): Infix<A, E, R, I> => ({ _tag: \"Infix\", associativity: \"left\", parser, precedence, fold })\n\n/**\n * A right-associative infix operator: `a ^ b ^ c` is `a ^ (b ^ c)`.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const infixRight = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (left: A, op: O, right: A) => A\n): Infix<A, E, R, I> => ({ _tag: \"Infix\", associativity: \"right\", parser, precedence, fold })\n\ntype OpError<Op> = Op extends OperatorBase<infer E, infer _R, infer _I> ? E : never\ntype OpServices<Op> = Op extends OperatorBase<infer _E, infer R, infer _I> ? R : never\ntype OpInput<Op> = [Op] extends [never] ? Input : [Op] extends [OperatorBase<infer _E, infer _R, infer I>] ? I : never\n\n/**\n * Builds an expression parser from an operand parser and an operator table.\n *\n * Precedences are compared numerically: higher binds tighter. A prefix\n * operator applies to everything that binds tighter than it, so with `-`\n * at precedence 4 and `^` at 3, `-2 ^ 2` parses as `(-2) ^ 2`.\n *\n * When several operators of the same kind match, the first one in the\n * table wins, so list longer operators (`<=`) before their prefixes (`<`).\n *\n * @since 0.1.0\n * @category constructors\n */\nexport const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<Operator<A, any, any, any>>>(options: {\n readonly operand: Parser<A, E, R, I>\n readonly operators: Ops\n}): Parser<A, E | OpError<Ops[number]>, R | OpServices<Ops[number]>, I & OpInput<Ops[number]>> => {\n const prefixes = options.operators.filter((o): o is Prefix<A, any, any, any> => Predicate.isTagged(o, \"Prefix\"))\n const postfixes = options.operators.filter((o): o is Postfix<A, any, any, any> => Predicate.isTagged(o, \"Postfix\"))\n const infixes = options.operators.filter((o): o is Infix<A, any, any, any> => Predicate.isTagged(o, \"Infix\"))\n const operators = [...prefixes, ...postfixes, ...infixes]\n const parsers = [options.operand, ...operators.map((o) => o.parser)]\n // Builds the step from the operand's and the operators' steps, in that\n // order: their own steps when interpreted, compiled ones when compiled\n const build = (steps: ReadonlyArray<Step>) => {\n const operand = steps[0]\n const prefixSteps = steps.slice(1, 1 + prefixes.length)\n const postfixSteps = steps.slice(1 + prefixes.length, 1 + prefixes.length + postfixes.length)\n const infixSteps = steps.slice(1 + prefixes.length + postfixes.length)\n\n // Attempts each operator in turn. Returns the index of the first match\n // (with its output in `matched`), -1 if none matched, or -2 on a fatal\n // failure. Failed attempts are folded into `failures`, merged only when\n // read (#44): a round in which an operator matches discards them unmerged.\n // Like `matched`, it is shared by nested expressions, which clear it.\n let matched: unknown\n const failures = new TiedFailures()\n const tryOps = (state: State<any>, ops: ReadonlyArray<Step>, mustConsume: boolean): number => {\n const start = state.pos\n for (let i = 0; i < ops.length; i++) {\n const out = ops[i](state)\n if (out !== Fail) {\n // A prefix or postfix operator matching nothing would apply forever\n if (mustConsume && state.pos === start) {\n state.failMessage(\"Cut\", \"Assert\", \"prefix and postfix operators must always consume\")\n return -2\n }\n matched = out\n return i\n }\n if (state.mode !== \"Backtrack\") return -2\n state.rewind(start)\n failures.add(state)\n }\n return -1\n }\n\n const expr = (state: State<any>, minPower: number): A | Fail => {\n let lhs: A | Fail\n failures.clear()\n const p = tryOps(state, prefixSteps, true)\n if (p === -2) return Fail\n if (p >= 0) {\n const op = prefixes[p]\n const opOut = matched\n const operandValue = expr(state, op.precedence * 2)\n if (operandValue === Fail) return Fail\n lhs = op.fold(opOut, operandValue)\n } else {\n const prefixFailure = failures.failure\n const prefixTie1 = failures.tie1\n const prefixTie2 = failures.tie2\n // SAFETY: the operand's step, interpreted or compiled, returns its output (an `A`) or `Fail`\n lhs = operand(state) as A | Fail\n if (lhs === Fail) {\n if (prefixFailure !== undefined && state.mode === \"Backtrack\") {\n // The operand may have parsed nested expressions, which reuse `failures`\n failures.failure = prefixFailure\n failures.tie1 = prefixTie1\n failures.tie2 = prefixTie2\n failures.add(state)\n failures.fail(state)\n }\n return Fail\n }\n }\n\n while (true) {\n const start = state.pos\n failures.clear()\n const q = tryOps(state, postfixSteps, true)\n if (q === -2) return Fail\n if (q >= 0) {\n const op = postfixes[q]\n if (op.precedence * 2 < minPower) {\n state.rewind(start)\n break\n }\n lhs = op.fold(lhs, matched)\n continue\n }\n // The infix attempts are folded on top of the postfix ones\n const i = tryOps(state, infixSteps, false)\n if (i === -2) return Fail\n if (i < 0) {\n failures.hint(state)\n break\n }\n const op = infixes[i]\n const leftPower = op.precedence * 2\n if (leftPower < minPower) {\n state.rewind(start)\n break\n }\n const opOut = matched\n const rhs = expr(state, op.associativity === \"left\" ? leftPower + 1 : leftPower)\n if (rhs === Fail) return Fail\n lhs = op.fold(lhs, opOut, rhs)\n }\n return lhs\n }\n return (state: State<any>) => expr(state, 0)\n }\n return combinator(parsers, build, \"expression\")\n}\n"],"mappings":"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"}
|
package/dist/Input.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AsciiRun } from "./internal/text.js";
|
|
1
2
|
import * as Context from "effect/Context";
|
|
2
3
|
import { ErrorKind } from "./ParseError.js";
|
|
3
4
|
import { Builder } from "./internal/syntax.js";
|
|
@@ -35,6 +36,16 @@ export type BinaryInput = ArrayBufferLike | ArrayBufferView;
|
|
|
35
36
|
* @category models
|
|
36
37
|
*/
|
|
37
38
|
export type Source<I> = I | ([I] extends [Uint8Array] ? BinaryInput : never);
|
|
39
|
+
/**
|
|
40
|
+
* The overloads of {@link fromSource}.
|
|
41
|
+
*
|
|
42
|
+
* @since 0.5.0
|
|
43
|
+
* @category constructors
|
|
44
|
+
*/
|
|
45
|
+
export interface FromSourceFn {
|
|
46
|
+
(source: BinaryInput): Uint8Array;
|
|
47
|
+
<I extends Input>(source: Source<I>): I;
|
|
48
|
+
}
|
|
38
49
|
/**
|
|
39
50
|
* Converts a {@link Source} to the input parsers read: binary data becomes a
|
|
40
51
|
* `Uint8Array` view of the same memory, everything else is returned as is.
|
|
@@ -49,10 +60,7 @@ export type Source<I> = I | ([I] extends [Uint8Array] ? BinaryInput : never);
|
|
|
49
60
|
* @since 0.1.0
|
|
50
61
|
* @category constructors
|
|
51
62
|
*/
|
|
52
|
-
export declare const fromSource:
|
|
53
|
-
(source: BinaryInput): Uint8Array;
|
|
54
|
-
<I extends Input>(source: Source<I>): I;
|
|
55
|
-
};
|
|
63
|
+
export declare const fromSource: FromSourceFn;
|
|
56
64
|
/**
|
|
57
65
|
* The type of a single token of an input.
|
|
58
66
|
*
|
|
@@ -220,6 +228,18 @@ export declare class State<I extends Input = Input> {
|
|
|
220
228
|
*/
|
|
221
229
|
get deepest(): Failure | undefined;
|
|
222
230
|
set deepest(failure: Failure | undefined);
|
|
231
|
+
/**
|
|
232
|
+
* Whether compiled code is running on this state. A compiled run that fails
|
|
233
|
+
* is thrown away (the interpreter runs again to build the error) and one
|
|
234
|
+
* that succeeds records no diagnostics, so interpreted steps called from it
|
|
235
|
+
* (an opaque `Parser.make`, a leaf near the end of a partial input) record
|
|
236
|
+
* a `Backtrack` or `Cut` failure's mode only, without building its
|
|
237
|
+
* {@link Failure} (#82). `Incomplete` failures are still built: a compiled
|
|
238
|
+
* run's `Incomplete` is reported as it stands.
|
|
239
|
+
*
|
|
240
|
+
* @internal
|
|
241
|
+
*/
|
|
242
|
+
compiledRun: boolean;
|
|
223
243
|
/** When defined, `Parser.resumeAfter`/`retryAfter` record failures here. */
|
|
224
244
|
recovered: Array<Failure> | undefined;
|
|
225
245
|
/** When defined, `Parser.trace` reports events here. */
|
|
@@ -245,6 +265,33 @@ export declare class State<I extends Input = Input> {
|
|
|
245
265
|
* @internal
|
|
246
266
|
*/
|
|
247
267
|
syntax: Builder | undefined;
|
|
268
|
+
/**
|
|
269
|
+
* Where the stop characters of compiled `takeTill`s next occur in this
|
|
270
|
+
* state's input, by search site; created on first use. It lives as long
|
|
271
|
+
* as the state. `reset` keeps it for string input (a string never
|
|
272
|
+
* changes, and the positions are absolute, so they hold wherever the next
|
|
273
|
+
* run starts) and drops it for bytes and arrays, which a caller may
|
|
274
|
+
* refill in place between runs.
|
|
275
|
+
*
|
|
276
|
+
* @internal
|
|
277
|
+
*/
|
|
278
|
+
searches: Map<object, Array<number>> | undefined;
|
|
279
|
+
/**
|
|
280
|
+
* A run of ASCII bytes of this state's UTF-8 input, decoded once, from
|
|
281
|
+
* which `Text.utf8` slices the long strings it decodes (see
|
|
282
|
+
* `internal/text.ts`); `reset` clears it with the other per-run fields.
|
|
283
|
+
*
|
|
284
|
+
* @internal
|
|
285
|
+
*/
|
|
286
|
+
asciiRun: AsciiRun | undefined;
|
|
287
|
+
/**
|
|
288
|
+
* A `DataView` of this state's byte input, for the `Binary` parsers;
|
|
289
|
+
* created on first use. It lives as long as the state, whose input never
|
|
290
|
+
* changes: one per read cost most of a number's time.
|
|
291
|
+
*
|
|
292
|
+
* @internal
|
|
293
|
+
*/
|
|
294
|
+
view: DataView | undefined;
|
|
248
295
|
constructor(source: I | Source<I>, options?: {
|
|
249
296
|
readonly partial?: boolean | undefined;
|
|
250
297
|
readonly context?: Context.Context<never> | undefined;
|
|
@@ -263,7 +310,11 @@ export declare class State<I extends Input = Input> {
|
|
|
263
310
|
*
|
|
264
311
|
* Every per-run field is reset: the cursor and end, the latest failure,
|
|
265
312
|
* hints and furthest failure, recorded recoveries, the tracer and tracing
|
|
266
|
-
* depth, the recorded encoding and streaming checkpoints.
|
|
313
|
+
* depth, the recorded encoding and streaming checkpoints. For string
|
|
314
|
+
* input, what the state has learnt about the string (where the stop
|
|
315
|
+
* characters of `takeTill` and the literals of `takeUntilAny` occur) is
|
|
316
|
+
* kept, as a string cannot change; for bytes and arrays it is dropped, so
|
|
317
|
+
* a buffer refilled in place between runs is searched afresh. Like the
|
|
267
318
|
* constructor, `partial` defaults to `false` and `context` to the empty
|
|
268
319
|
* context, so pass them again on every reset.
|
|
269
320
|
*
|
package/dist/Input.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.d.ts","names":["SyntaxBuilder"],"sources":["../src/Input.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Input.d.ts","names":["SyntaxBuilder"],"sources":["../src/Input.ts"],"mappings":";;;;;;;;;;;;;;;;YAkCY,iBAAiB,aAAa;;;;;;;;;;;;;YAc9B,cAAc,kBAAkB;;;;;;;;YAShC,OAAO,KAAK,MAAM,YAAY,cAAc;;;;;;;iBAQvC;GACd,QAAQ,cAAc;GACtB,UAAU,OAAO,QAAQ,OAAO,KAAK;;;;;;;;;;;;;;;;qBAiB3B,YAAY;;;;;;;YAiBb,MAAM,KAAK,4BAEnB,UAAU,sBAER,UAAU,oBAAoB,KAC5B;;;;;;;YASI,MAAM,KAAK,4BAEnB,UAAU,aACR,aACA,UAAU,oBAAoB,KAC5B,cAAc;;;;;;;;qBAUT;;;;;YAMD,cAAc;;;;;;;;;;;YAYd;;;;;;;qBAQC;;WAGA;;WAEA,MAAM;;WAEN,UAAU;;WAEV,SAAS;;WAET;;WAEA;;WAEA;;WAEA;;;EAdA;;EAEA,MAAM;;EAEN,UAAU;;EAEV,SAAS;;EAET;;EAEA;;EAEA;;EAEA;;;qBAUA;;;;;;;iBAQI;WACN;WACA;WACA;WACA;;WAEA,gBAAgB;;WAEhB;WACA,OAAO;;;;;;;;qBASL,MAAM,UAAU,QAAQ;;WAE1B,OAAO;;;;;EAKhB;;EAEA;;WAES;;EAET;;EAEA,SAAS,QAAQ;;EAEjB,MAAM;;;;;;;;;;;EAWN,aAAa;;EAEb,aAAa;;EAEb,aAAa;;EAEb,gBAAgB;;;;;;;;EAQhB;;;;;;;EAOA;;EAEA,cAAc;;;;;;;;;;MAUV,WAAW;MAIX,QAAQ,SAAS;;;;;;;;;;;;EAerB;;EAEA,WAAW,MAAM;;EAEjB,UAAU,OAAO;;EAEjB;;;;;EAKA,UAAU;;;;;;;EAOV,QAAQ,YAAY;;;;;;;EAOpB,QAAQA;;;;;;;;;;;EAWR,UAAU,YAAY;;;;;;;;EAQtB,UAAU;;;;;;;;EAQV,MAAM;EAGJ,YAAA,QAAQ,IAAI,OAAO,IACnB;aACW;aACA,UAAU,QAAQ;aAClB;;;MAcT,WAAW;MAIX,QAAQ,SAAS;;UAQb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiDR,MACE,iBACA;aACW;aACA,UAAU,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyD/B,OAAO;;;;EASP;;;;EAOA;;;;EAOA,MAAM,eAAe,cAAc,MAAM;;;;EAsBzC,UAAU,MAAM,WAAW,WAAU,uBAA+B,kBAA4B;;;;EAWhG,IAAI,MAAM,WAAW,WAAU,uBAA+B,kBAA4B;;;;;EAY1F,WAAW,gBAAgB,WAAU,wBAAgC;;;;;EAWrE,IAAI,MAAM,WAAW,UAAU,uBAAuB,iBAAiB;;;;EAOvE,UAAU,MAAM,SAAS,MAAM,WAAW,gBAAgB,kBAA4B;;;;EAOtF,YAAY,MAAM,SAAS,MAAM,WAAW,iBAAiB,kBAA4B;;;;EAOzF,SAAS,MAAM,SAAS,SAAS,UAAU;;;;;;;;EAwB3C,SAAS,MAAM,SAAS,MAAM,SAAS,MAAM,sBAAsB;;;;;EAenE,eAAe,SAAS;;;;;;EAUxB,mBAAmB;;;;;;EAwBnB,QAAQ,gBAAgB,UAAU;;EAWlC,YAAY,gBAAgB,MAAM,WAAW,UAAU,wBAAwB;;;qBAoBpE,gBAAiB,GAAG,uBAAuB,GAAG,0BAAwB;;;;;;;qBAqBtE,gBAAiB,GAAG,SAAS,GAAG,YAAU;;;;;;;;qBAa1C,oBAAqB,GAAG,SAAS,GAAG,SAAS,UAAU,0BAAwB"}
|