@thomasfosterau/effect-parse 0.3.0 → 0.4.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/dist/Ascii.d.ts +0 -2
- package/dist/Ascii.d.ts.map +1 -1
- package/dist/Ascii.js +6 -6
- package/dist/Ascii.js.map +1 -1
- package/dist/Binary.d.ts +0 -2
- package/dist/Binary.d.ts.map +1 -1
- package/dist/Binary.js +1 -2
- package/dist/Bits.d.ts +0 -2
- package/dist/Bits.d.ts.map +1 -1
- package/dist/Bits.js +2 -3
- package/dist/Bits.js.map +1 -1
- package/dist/Compiler.d.ts +0 -2
- package/dist/Compiler.d.ts.map +1 -1
- package/dist/Compiler.js +1 -2
- package/dist/Encoding.d.ts +0 -2
- package/dist/Encoding.d.ts.map +1 -1
- package/dist/Encoding.js +1 -2
- package/dist/Expression.d.ts +0 -2
- package/dist/Expression.d.ts.map +1 -1
- package/dist/Expression.js +44 -8
- package/dist/Expression.js.map +1 -1
- package/dist/Input.d.ts +32 -4
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +47 -8
- package/dist/Input.js.map +1 -1
- package/dist/Nom.d.ts +0 -2
- package/dist/Nom.d.ts.map +1 -1
- package/dist/Nom.js +1 -2
- package/dist/ParseError.d.ts +0 -2
- package/dist/ParseError.d.ts.map +1 -1
- package/dist/ParseError.js +6 -9
- package/dist/ParseError.js.map +1 -1
- package/dist/Parser.d.ts +2 -2
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +26 -24
- package/dist/Parser.js.map +1 -1
- package/dist/ParserSchema.d.ts +0 -2
- package/dist/ParserSchema.d.ts.map +1 -1
- package/dist/ParserSchema.js +2 -3
- package/dist/ParserStream.d.ts +0 -2
- package/dist/ParserStream.d.ts.map +1 -1
- package/dist/ParserStream.js +15 -9
- package/dist/ParserStream.js.map +1 -1
- package/dist/Syntax.d.ts +0 -2
- package/dist/Syntax.d.ts.map +1 -1
- package/dist/Syntax.js +13 -11
- package/dist/Syntax.js.map +1 -1
- package/dist/Text.d.ts +0 -2
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +1 -2
- package/dist/Token.d.ts +0 -2
- package/dist/Token.d.ts.map +1 -1
- package/dist/Token.js +1 -2
- package/dist/internal/compiler/closure.d.ts +5 -2
- package/dist/internal/compiler/closure.d.ts.map +1 -1
- package/dist/internal/compiler/closure.js +160 -92
- package/dist/internal/compiler/closure.js.map +1 -1
- package/dist/internal/compiler/entries.d.ts +0 -2
- package/dist/internal/compiler/entries.d.ts.map +1 -1
- package/dist/internal/compiler/entries.js +6 -7
- package/dist/internal/compiler/entries.js.map +1 -1
- package/dist/internal/compiler/first.d.ts +0 -2
- package/dist/internal/compiler/first.d.ts.map +1 -1
- package/dist/internal/compiler/first.js +10 -10
- package/dist/internal/compiler/first.js.map +1 -1
- package/dist/internal/compiler/jit.d.ts +0 -2
- package/dist/internal/compiler/jit.d.ts.map +1 -1
- package/dist/internal/compiler/jit.js +52 -51
- package/dist/internal/compiler/jit.js.map +1 -1
- package/dist/internal/compiler/registry.d.ts +0 -2
- package/dist/internal/compiler/registry.d.ts.map +1 -1
- package/dist/internal/compiler/registry.js +1 -2
- package/dist/internal/compiler/sets.d.ts +2 -2
- package/dist/internal/compiler/sets.d.ts.map +1 -1
- package/dist/internal/compiler/sets.js +8 -3
- package/dist/internal/compiler/sets.js.map +1 -1
- package/dist/internal/entries.d.ts +0 -2
- package/dist/internal/entries.d.ts.map +1 -1
- package/dist/internal/entries.js +1 -2
- package/dist/internal/key.d.ts +10 -0
- package/dist/internal/key.d.ts.map +1 -0
- package/dist/internal/key.js +11 -0
- package/dist/internal/key.js.map +1 -0
- package/dist/internal/node.d.ts +11 -4
- package/dist/internal/node.d.ts.map +1 -1
- package/dist/internal/node.js +15 -3
- package/dist/internal/node.js.map +1 -1
- package/dist/internal/numbers.d.ts +0 -2
- package/dist/internal/numbers.d.ts.map +1 -1
- package/dist/internal/numbers.js +1 -2
- package/dist/internal/resume.d.ts +5 -6
- package/dist/internal/resume.d.ts.map +1 -1
- package/dist/internal/resume.js +1 -2
- package/dist/internal/resume.js.map +1 -1
- package/dist/internal/run.d.ts +0 -2
- package/dist/internal/run.d.ts.map +1 -1
- package/dist/internal/run.js +2 -3
- package/dist/internal/run.js.map +1 -1
- package/dist/internal/stack.d.ts +0 -2
- package/dist/internal/stack.d.ts.map +1 -1
- package/dist/internal/stack.js +1 -2
- package/dist/internal/syntax.d.ts +30 -20
- package/dist/internal/syntax.d.ts.map +1 -1
- package/dist/internal/syntax.js +73 -66
- package/dist/internal/syntax.js.map +1 -1
- package/dist/internal/text.d.ts +5 -2
- package/dist/internal/text.d.ts.map +1 -1
- package/dist/internal/text.js +14 -5
- package/dist/internal/text.js.map +1 -1
- package/dist/internal/ties.d.ts +0 -2
- package/dist/internal/ties.d.ts.map +1 -1
- package/dist/internal/ties.js +1 -2
- package/dist/internal/tokens.d.ts +10 -9
- package/dist/internal/tokens.d.ts.map +1 -1
- package/dist/internal/tokens.js +4 -8
- package/dist/internal/tokens.js.map +1 -1
- package/package.json +6 -6
- package/src/Ascii.ts +6 -5
- package/src/Bits.ts +1 -1
- package/src/Expression.ts +7 -6
- package/src/Input.ts +50 -11
- package/src/ParseError.ts +9 -7
- package/src/Parser.ts +26 -23
- package/src/ParserStream.ts +20 -8
- package/src/Syntax.ts +12 -9
- package/src/internal/compiler/closure.ts +202 -90
- package/src/internal/compiler/entries.ts +14 -11
- package/src/internal/compiler/first.ts +9 -8
- package/src/internal/compiler/jit.ts +95 -74
- package/src/internal/compiler/sets.ts +7 -0
- package/src/internal/key.ts +11 -0
- package/src/internal/node.ts +19 -2
- package/src/internal/resume.ts +5 -4
- package/src/internal/run.ts +1 -1
- package/src/internal/syntax.ts +78 -87
- package/src/internal/text.ts +24 -4
- package/src/internal/tokens.ts +20 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"first.js","names":[],"sources":["../../../src/internal/compiler/first.ts"],"sourcesContent":["/**\n * First sets: which input units can start a match of a parser.\n *\n * A first set has a mode:\n *\n * - `Strict`: when the next unit is not in `units` (or the input has\n * ended), the parser fails with `Backtrack`.\n * - `Optional`: in that case, the parser either fails with `Backtrack` or\n * succeeds without consuming input.\n * - `Unknown`: no guarantee.\n *\n * Units are UTF-16 code units for strings and bytes for byte inputs; units\n * from `TableSize` up are summarized by `high`. Array inputs have no units.\n *\n * Skipping a parser that is certain to fail also skips the callbacks it\n * would have run before failing, which is why callbacks must be pure.\n */\nimport * as Predicate from \"effect/Predicate\"\nimport type { Encoding } from \"../../Encoding.js\"\nimport type { Node, ParserLike } from \"../node.js\"\nimport { nodeOf } from \"../node.js\"\nimport { fastLimit } from \"../text.js\"\nimport type { CharSet } from \"./sets.js\"\nimport { kindOfEncoding, reachesAbove, TableSize, textSet, tokenSet } from \"./sets.js\"\n\nexport const Strict = 0\nconst Optional = 1\nconst Unknown = 2\n\nexport interface First {\n readonly mode: 0 | 1 | 2\n readonly units: Uint8Array\n readonly high: boolean\n}\n\nconst none = /*#__PURE__*/ new Uint8Array(TableSize)\nconst all = /*#__PURE__*/ new Uint8Array(TableSize).fill(1)\n\nconst unknown: First = { mode: Unknown, units: all, high: true }\nconst emptyOptional: First = { mode: Optional, units: none, high: false }\nconst failing: First = { mode: Strict, units: none, high: false }\nconst anyUnit: First = { mode: Strict, units: all, high: true }\n\nconst union = (a: First, b: First, mode: 0 | 1 | 2): First => {\n const units = new Uint8Array(TableSize)\n for (let i = 0; i < TableSize; i++) units[i] = a.units[i] | b.units[i]\n return { mode, units, high: a.high || b.high }\n}\n\nconst withMode = (f: First, mode: 0 | 1 | 2): First => (f.mode === mode ? f : { ...f, mode })\n\nconst lowerAscii = (c: number): number => (c >= 65 && c <= 90 ? c + 32 : c)\nconst upperAscii = (c: number): number => (c >= 97 && c <= 122 ? c - 32 : c)\n\nconst ofUnits = (codes: ReadonlyArray<number>, mode: 0 | 1 | 2 = Strict): First => {\n const units = new Uint8Array(TableSize)\n let high = false\n for (const c of codes) {\n if (c < TableSize) units[c] = 1\n else high = true\n }\n return { mode, units, high }\n}\n\nexport class FirstSets {\n private readonly memo = new Map<ParserLike, First | undefined>()\n constructor(readonly kind: 0 | 1 | 2) {}\n\n of(p: ParserLike): First {\n if (this.kind === 2) return unknown\n if (this.memo.has(p)) return this.memo.get(p) ?? unknown // in progress: a cycle\n this.memo.set(p, undefined)\n const f = this.compute(nodeOf(p))\n this.memo.set(p, f)\n return f\n }\n\n /** Units of the code points of a set, as an encoding (or `Token`) reads them. */\n private setUnits(set: CharSet, enc: Encoding<any> | undefined, mode: 0 | 1): First | undefined {\n if (enc === undefined || kindOfEncoding(enc) === 0) {\n if (this.kind === 1) return { mode, units: set.table, high: false }\n return { mode, units: set.table, high: reachesAbove(set, TableSize) }\n }\n if (enc.unit !== 1) return undefined\n const fast = fastLimit(enc)\n if (fast === 0) return undefined\n const units = set.table.slice()\n // Multi-unit sequences start with a unit at or above `fast`\n if (fast < TableSize) units.fill(reachesAbove(set, fast) ? 1 : 0, fast)\n return { mode, units, high: false }\n }\n\n private compute(node: Node): First {\n const kind = this.kind as 0 | 1\n switch (node._tag) {\n case \"Succeed\":\n case \"Sync\":\n case \"Location\":\n case \"RestLen\":\n case \"Eof\":\n return emptyOptional\n case \"Fail\":\n return node.mode === \"Backtrack\" ? failing : unknown\n case \"Any\":\n return node.encoding !== undefined && kindOfEncoding(node.encoding) !== kind ? unknown : anyUnit\n case \"Take\":\n return node.count === 0 ? emptyOptional : anyUnit\n case \"Literal\": {\n const lit = node.literal\n if (node.encoding !== undefined) {\n if (kindOfEncoding(node.encoding) !== kind) return unknown\n if (node.caseless) return lit.length === 0 ? unknown : anyUnit\n const encoded = node.encoding.encode(lit as string)\n if (encoded.length === 0) return emptyOptional\n return ofUnits([Predicate.isString(encoded) ? encoded.charCodeAt(0) : encoded[0]])\n }\n if (lit.length === 0) return emptyOptional\n let first: number\n if (Predicate.isString(lit)) {\n first = kind === 0 ? lit.charCodeAt(0) : new TextEncoder().encode(lit)[0]\n } else if (lit instanceof Uint8Array && kind === 1) {\n first = lit[0]\n } else {\n return unknown\n }\n return ofUnits(node.caseless ? [first, lowerAscii(first), upperAscii(first)] : [first])\n }\n case \"OneOf\":\n case \"TakeWhile\": {\n if (node.encoding !== undefined && kindOfEncoding(node.encoding) !== kind) return unknown\n const min = node._tag === \"OneOf\" ? 1 : node.min\n if (node._tag === \"TakeWhile\" && node.max === 0) return emptyOptional\n const mode = min > 0 ? Strict : Optional\n if (node.negate) return mode === Strict ? anyUnit : withMode(anyUnit, Optional)\n const set = node.encoding === undefined ? tokenSet(node.set, kind) : textSet(node.set)\n return this.setUnits(set, node.encoding, mode) ?? (mode === Strict ? anyUnit : unknown)\n }\n case \"Map\":\n case \"As\":\n case \"Tap\":\n case \"TryMap\":\n case \"FilterMap\":\n case \"Filter\":\n case \"Taken\":\n case \"WithTaken\":\n case \"Span\":\n case \"WithSpan\":\n case \"Context\":\n case \"Expected\":\n case \"MapError\":\n case \"OrFail\":\n case \"Peek\":\n case \"Trace\":\n case \"Syntax\":\n case \"ResumeAfter\":\n case \"RetryAfter\":\n return this.of(node.self)\n case \"FlatMap\":\n case \"SeparatedFold\":\n case \"Dispatch\": {\n const f = this.of(node._tag === \"Dispatch\" ? node.selector : node.self)\n return f.mode === Strict ? f : unknown\n }\n case \"Mode\": {\n const f = this.of(node.self)\n return node.from === \"Backtrack\" ? (f.mode === Unknown ? f : unknown) : f\n }\n case \"Opt\":\n case \"OrElseSucceed\": {\n const f = this.of(node.self)\n return f.mode === Unknown ? f : withMode(f, Optional)\n }\n case \"Seq\":\n case \"Struct\":\n return this.sequence(node.parsers)\n case \"ZipWith\":\n return this.sequence([node.self, node.that])\n case \"Alt\": {\n if (node.parsers.length === 0) return failing\n let acc: First | undefined\n let mode: 0 | 1 | 2 = Strict\n for (const p of node.parsers) {\n const f = this.of(p)\n if (f.mode === Unknown) return unknown\n if (f.mode === Optional) mode = Optional\n acc = acc === undefined ? f : union(acc, f, mode)\n }\n return acc === undefined ? failing : withMode(acc, mode)\n }\n case \"Repeat\":\n case \"Fold\":\n case \"Separated\": {\n if (node.max === 0) return emptyOptional\n const f = this.of(node.self)\n if (f.mode !== Strict) return unknown\n return node.min === 0 ? withMode(f, Optional) : f\n }\n case \"Suspend\":\n return this.of(node.resolve())\n default:\n return unknown\n }\n }\n\n private sequence(parsers: ReadonlyArray<ParserLike>): First {\n let acc: First | undefined\n for (const p of parsers) {\n const f = this.of(p)\n if (f.mode === Unknown) return unknown\n acc = acc === undefined ? f : union(acc, f, f.mode)\n if (f.mode === Strict) return acc\n }\n return acc ?? emptyOptional\n }\n}\n\n/**\n * For an `Alt`: the branches worth trying for each next unit, each next\n * high unit, and at the end of the input, or `undefined` when pruning\n * would never skip a branch.\n */\nexport interface AltPlan {\n /** Indexed by unit: indexes into `lists`. */\n readonly byUnit: Uint8Array\n readonly high: number\n readonly end: number\n readonly lists: ReadonlyArray<ReadonlyArray<number>>\n}\n\nexport const planAlt = (firsts: ReadonlyArray<First>): AltPlan | undefined => {\n const n = firsts.length\n if (n < 2 || n > 64) return undefined\n const lists: Array<ReadonlyArray<number>> = []\n const index = new Map<string, number>()\n const listOf = (keep: (f: First) => boolean): number => {\n const list: Array<number> = []\n for (let i = 0; i < n; i++) if (keep(firsts[i])) list.push(i)\n const key = list.join(\",\")\n let k = index.get(key)\n if (k === undefined) {\n k = lists.length\n lists.push(list)\n index.set(key, k)\n }\n return k\n }\n const byUnit = new Uint8Array(TableSize)\n for (let u = 0; u < TableSize; u++) byUnit[u] = listOf((f) => f.mode !== Strict || f.units[u] === 1)\n const high = listOf((f) => f.mode !== Strict || f.high)\n const end = listOf((f) => f.mode !== Strict)\n if (lists.length === 1 && lists[0].length === n) return undefined\n if (lists.length > 255) return undefined\n return { byUnit, high, end, lists }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"first.js","names":[],"sources":["../../../src/internal/compiler/first.ts"],"sourcesContent":["/**\n * First sets: which input units can start a match of a parser.\n *\n * A first set has a mode:\n *\n * - `Strict`: when the next unit is not in `units` (or the input has\n * ended), the parser fails with `Backtrack`.\n * - `Optional`: in that case, the parser either fails with `Backtrack` or\n * succeeds without consuming input.\n * - `Unknown`: no guarantee.\n *\n * Units are UTF-16 code units for strings and bytes for byte inputs; units\n * from `TableSize` up are summarized by `high`. Array inputs have no units.\n *\n * Skipping a parser that is certain to fail also skips the callbacks it\n * would have run before failing, which is why callbacks must be pure.\n */\nimport * as Arr from \"effect/Array\"\nimport * as Predicate from \"effect/Predicate\"\nimport type { Encoding } from \"../../Encoding.js\"\nimport type { Node, ParserLike } from \"../node.js\"\nimport { nodeOf } from \"../node.js\"\nimport { fastLimit, isEmptyUnits } from \"../text.js\"\nimport type { CharSet } from \"./sets.js\"\nimport { kindOfEncoding, reachesAbove, TableSize, textSet, tokenSet } from \"./sets.js\"\n\nexport const Strict = 0\nconst Optional = 1\nconst Unknown = 2\n\nexport interface First {\n readonly mode: 0 | 1 | 2\n readonly units: Uint8Array\n readonly high: boolean\n}\n\nconst none = /*#__PURE__*/ new Uint8Array(TableSize)\nconst all = /*#__PURE__*/ new Uint8Array(TableSize).fill(1)\n\nconst unknown: First = { mode: Unknown, units: all, high: true }\nconst emptyOptional: First = { mode: Optional, units: none, high: false }\nconst failing: First = { mode: Strict, units: none, high: false }\nconst anyUnit: First = { mode: Strict, units: all, high: true }\n\nconst union = (a: First, b: First, mode: 0 | 1 | 2): First => {\n const units = new Uint8Array(TableSize)\n for (let i = 0; i < TableSize; i++) units[i] = a.units[i] | b.units[i]\n return { mode, units, high: a.high || b.high }\n}\n\nconst withMode = (f: First, mode: 0 | 1 | 2): First => (f.mode === mode ? f : { ...f, mode })\n\nconst lowerAscii = (c: number): number => (c >= 65 && c <= 90 ? c + 32 : c)\nconst upperAscii = (c: number): number => (c >= 97 && c <= 122 ? c - 32 : c)\n\nconst ofUnits = (codes: ReadonlyArray<number>, mode: 0 | 1 | 2 = Strict): First => {\n const units = new Uint8Array(TableSize)\n let high = false\n for (const c of codes) {\n if (c < TableSize) units[c] = 1\n else high = true\n }\n return { mode, units, high }\n}\n\nexport class FirstSets {\n private readonly memo = new Map<ParserLike, First | undefined>()\n constructor(readonly kind: 0 | 1 | 2) {}\n\n of(p: ParserLike): First {\n if (this.kind === 2) return unknown\n if (this.memo.has(p)) return this.memo.get(p) ?? unknown // in progress: a cycle\n this.memo.set(p, undefined)\n const f = this.compute(nodeOf(p))\n this.memo.set(p, f)\n return f\n }\n\n /** Units of the code points of a set, as an encoding (or `Token`) reads them. */\n private setUnits(set: CharSet, enc: Encoding<any> | undefined, mode: 0 | 1): First | undefined {\n if (enc === undefined || kindOfEncoding(enc) === 0) {\n if (this.kind === 1) return { mode, units: set.table, high: false }\n return { mode, units: set.table, high: reachesAbove(set, TableSize) }\n }\n if (enc.unit !== 1) return undefined\n const fast = fastLimit(enc)\n if (fast === 0) return undefined\n const units = set.table.slice()\n // Multi-unit sequences start with a unit at or above `fast`\n if (fast < TableSize) units.fill(reachesAbove(set, fast) ? 1 : 0, fast)\n return { mode, units, high: false }\n }\n\n private compute(node: Node): First {\n const kind = this.kind as 0 | 1\n switch (node._tag) {\n case \"Succeed\":\n case \"Sync\":\n case \"Location\":\n case \"RestLen\":\n case \"Eof\":\n return emptyOptional\n case \"Fail\":\n return node.mode === \"Backtrack\" ? failing : unknown\n case \"Any\":\n return node.encoding !== undefined && kindOfEncoding(node.encoding) !== kind ? unknown : anyUnit\n case \"Take\":\n return node.count === 0 ? emptyOptional : anyUnit\n case \"Literal\": {\n const lit = node.literal\n if (node.encoding !== undefined) {\n if (kindOfEncoding(node.encoding) !== kind) return unknown\n if (node.caseless) return isEmptyUnits(lit) ? unknown : anyUnit\n const encoded = node.encoding.encode(lit as string)\n if (isEmptyUnits(encoded)) return emptyOptional\n return ofUnits([Predicate.isString(encoded) ? encoded.charCodeAt(0) : encoded[0]])\n }\n if (isEmptyUnits(lit)) return emptyOptional\n let first: number\n if (Predicate.isString(lit)) {\n first = kind === 0 ? lit.charCodeAt(0) : new TextEncoder().encode(lit)[0]\n } else if (lit instanceof Uint8Array && kind === 1) {\n first = lit[0]\n } else {\n return unknown\n }\n return ofUnits(node.caseless ? [first, lowerAscii(first), upperAscii(first)] : [first])\n }\n case \"OneOf\":\n case \"TakeWhile\": {\n if (node.encoding !== undefined && kindOfEncoding(node.encoding) !== kind) return unknown\n const min = Predicate.isTagged(node, \"OneOf\") ? 1 : node.min\n if (Predicate.isTagged(node, \"TakeWhile\") && node.max === 0) return emptyOptional\n const mode = min > 0 ? Strict : Optional\n if (node.negate) return mode === Strict ? anyUnit : withMode(anyUnit, Optional)\n const set = node.encoding === undefined ? tokenSet(node.set, kind) : textSet(node.set)\n return this.setUnits(set, node.encoding, mode) ?? (mode === Strict ? anyUnit : unknown)\n }\n case \"Map\":\n case \"As\":\n case \"Tap\":\n case \"TryMap\":\n case \"FilterMap\":\n case \"Filter\":\n case \"Taken\":\n case \"WithTaken\":\n case \"Span\":\n case \"WithSpan\":\n case \"Context\":\n case \"Expected\":\n case \"MapError\":\n case \"OrFail\":\n case \"Peek\":\n case \"Trace\":\n case \"Syntax\":\n case \"ResumeAfter\":\n case \"RetryAfter\":\n return this.of(node.self)\n case \"FlatMap\":\n case \"SeparatedFold\":\n case \"Dispatch\": {\n const f = this.of(Predicate.isTagged(node, \"Dispatch\") ? node.selector : node.self)\n return f.mode === Strict ? f : unknown\n }\n case \"Mode\": {\n const f = this.of(node.self)\n return node.from === \"Backtrack\" ? (f.mode === Unknown ? f : unknown) : f\n }\n case \"Opt\":\n case \"OrElseSucceed\": {\n const f = this.of(node.self)\n return f.mode === Unknown ? f : withMode(f, Optional)\n }\n case \"Seq\":\n case \"Struct\":\n return this.sequence(node.parsers)\n case \"ZipWith\":\n return this.sequence([node.self, node.that])\n case \"Alt\": {\n if (Arr.isReadonlyArrayEmpty(node.parsers)) return failing\n let acc: First | undefined\n let mode: 0 | 1 | 2 = Strict\n for (const p of node.parsers) {\n const f = this.of(p)\n if (f.mode === Unknown) return unknown\n if (f.mode === Optional) mode = Optional\n acc = acc === undefined ? f : union(acc, f, mode)\n }\n return acc === undefined ? failing : withMode(acc, mode)\n }\n case \"Repeat\":\n case \"Fold\":\n case \"Separated\": {\n if (node.max === 0) return emptyOptional\n const f = this.of(node.self)\n if (f.mode !== Strict) return unknown\n return node.min === 0 ? withMode(f, Optional) : f\n }\n case \"Suspend\":\n return this.of(node.resolve())\n default:\n return unknown\n }\n }\n\n private sequence(parsers: ReadonlyArray<ParserLike>): First {\n let acc: First | undefined\n for (const p of parsers) {\n const f = this.of(p)\n if (f.mode === Unknown) return unknown\n acc = acc === undefined ? f : union(acc, f, f.mode)\n if (f.mode === Strict) return acc\n }\n return acc ?? emptyOptional\n }\n}\n\n/**\n * For an `Alt`: the branches worth trying for each next unit, each next\n * high unit, and at the end of the input, or `undefined` when pruning\n * would never skip a branch.\n */\nexport interface AltPlan {\n /** Indexed by unit: indexes into `lists`. */\n readonly byUnit: Uint8Array\n readonly high: number\n readonly end: number\n readonly lists: ReadonlyArray<ReadonlyArray<number>>\n}\n\nexport const planAlt = (firsts: ReadonlyArray<First>): AltPlan | undefined => {\n const n = firsts.length\n if (n < 2 || n > 64) return undefined\n const lists: Array<ReadonlyArray<number>> = []\n const index = new Map<string, number>()\n const listOf = (keep: (f: First) => boolean): number => {\n const list: Array<number> = []\n for (let i = 0; i < n; i++) if (keep(firsts[i])) list.push(i)\n const key = list.join(\",\")\n let k = index.get(key)\n if (k === undefined) {\n k = lists.length\n lists.push(list)\n index.set(key, k)\n }\n return k\n }\n const byUnit = new Uint8Array(TableSize)\n for (let u = 0; u < TableSize; u++) byUnit[u] = listOf((f) => f.mode !== Strict || f.units[u] === 1)\n const high = listOf((f) => f.mode !== Strict || f.high)\n const end = listOf((f) => f.mode !== Strict)\n if (lists.length === 1 && lists[0].length === n) return undefined\n if (lists.length > 255) return undefined\n return { byUnit, high, end, lists }\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Backend } from "./registry.js";
|
|
2
|
-
//#region src/internal/compiler/jit.d.ts
|
|
3
2
|
/**
|
|
4
3
|
* The JIT as a backend: generated code where `new Function` is allowed,
|
|
5
4
|
* otherwise (or if generating fails) the closure compiler.
|
|
6
5
|
*/
|
|
7
6
|
export declare const backend: Backend;
|
|
8
|
-
//#endregion
|
|
9
7
|
//# sourceMappingURL=jit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jit.d.ts","names":[],"sources":["../../../src/internal/compiler/jit.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"jit.d.ts","names":[],"sources":["../../../src/internal/compiler/jit.ts"],"mappings":";;;;;qBAgxCa,SAAS"}
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import * as Predicate from "effect/Predicate";
|
|
2
|
+
import * as Result from "effect/Result";
|
|
2
3
|
import { Fail } from "../../Input.js";
|
|
3
4
|
import { floatScan, floatTexts, scanFloatBytes, scanFloatString, toFloat } from "../numbers.js";
|
|
5
|
+
import { Key } from "../key.js";
|
|
4
6
|
import * as Resume from "../resume.js";
|
|
5
7
|
import { compileAny } from "../tokens.js";
|
|
6
8
|
import { backend as backend$1, createClosureCompiler } from "./closure.js";
|
|
7
9
|
import * as Option from "effect/Option";
|
|
8
10
|
import { charOf, fastLimit, latin1, string, utf16be, utf16le, utf8, validate } from "../text.js";
|
|
11
|
+
import * as Arr from "effect/Array";
|
|
9
12
|
import { addEntry, flushEntries, fromEntries, isPlainKey } from "../entries.js";
|
|
10
|
-
import { children, nodeOf } from "../node.js";
|
|
13
|
+
import { children, nodeOf, scansFloat } from "../node.js";
|
|
11
14
|
import { buildsEntries, pairOf } from "./entries.js";
|
|
12
15
|
import { Strict, planAlt } from "./first.js";
|
|
13
|
-
import { TableSize, kindOfEncoding, reachesAbove, textSet, tokenSet } from "./sets.js";
|
|
14
|
-
|
|
16
|
+
import { TableSize, acceptTable, kindOfEncoding, reachesAbove, textSet, tokenSet } from "./sets.js";
|
|
17
|
+
// src/internal/compiler/jit.ts
|
|
15
18
|
/**
|
|
16
19
|
* The JIT: emits JavaScript source for a parser's description and builds
|
|
17
20
|
* it with `new Function`.
|
|
@@ -65,11 +68,8 @@ let supported = false;
|
|
|
65
68
|
const jitSupported = () => {
|
|
66
69
|
if (checked !== globalThis.Function) {
|
|
67
70
|
checked = globalThis.Function;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
} catch {
|
|
71
|
-
supported = false;
|
|
72
|
-
}
|
|
71
|
+
const fn = checked;
|
|
72
|
+
supported = Result.getOrElse(Result.try(() => fn("return true")() === true), () => false);
|
|
73
73
|
}
|
|
74
74
|
return supported;
|
|
75
75
|
};
|
|
@@ -117,7 +117,7 @@ const runsOf = (table) => {
|
|
|
117
117
|
};
|
|
118
118
|
/** A JavaScript expression testing `v` against ranges, or `undefined` if too long. */
|
|
119
119
|
const rangeTest = (runs, v) => {
|
|
120
|
-
if (runs
|
|
120
|
+
if (Arr.isReadonlyArrayEmpty(runs)) return "false";
|
|
121
121
|
if (runs.length > 4) return void 0;
|
|
122
122
|
return runs.map(([a, b]) => a === b ? `${v}===${a}` : `(${v}>=${a}&&${v}<=${b})`).join("||");
|
|
123
123
|
};
|
|
@@ -144,8 +144,8 @@ const runCost = ([a, b], size) => a === b || a === 0 || b === size - 1 ? 1 : 2;
|
|
|
144
144
|
const tableTest = (table, v, size) => {
|
|
145
145
|
const accept = runsWhere(table, size, 1);
|
|
146
146
|
const reject = runsWhere(table, size, 0);
|
|
147
|
-
if (accept
|
|
148
|
-
if (reject
|
|
147
|
+
if (Arr.isReadonlyArrayEmpty(accept)) return "false";
|
|
148
|
+
if (Arr.isReadonlyArrayEmpty(reject)) return "true";
|
|
149
149
|
const cost = (runs) => runs.reduce((n, r) => n + runCost(r, size), 0);
|
|
150
150
|
const acceptCost = cost(accept);
|
|
151
151
|
const rejectCost = cost(reject);
|
|
@@ -247,7 +247,7 @@ var Emitter = class {
|
|
|
247
247
|
const out = used ? this.v(fn) : null;
|
|
248
248
|
const done = this.label();
|
|
249
249
|
const body = this.inline(p, used, out, `break ${done};`, fn, 0);
|
|
250
|
-
this.functions.push(`function ${name}(p){const I=$I,E=$E;${fn.vars
|
|
250
|
+
this.functions.push(`function ${name}(p){const I=$I,E=$E;${Arr.isArrayNonEmpty(fn.vars) ? `let ${fn.vars.join(",")};` : ""}${done}:{${body}P=p;return ${out ?? "void 0"}}return F}`);
|
|
251
251
|
return name;
|
|
252
252
|
}
|
|
253
253
|
/**
|
|
@@ -256,7 +256,7 @@ var Emitter = class {
|
|
|
256
256
|
*/
|
|
257
257
|
gen(p, used, out, fail, fn, depth) {
|
|
258
258
|
const node = nodeOf(p);
|
|
259
|
-
if (node
|
|
259
|
+
if (Predicate.isTagged(node, "Suspend")) return this.call(this.rule(node.resolve(), used), out, fail);
|
|
260
260
|
if (!isLeaf(node) && ((this.refs.get(p) ?? 0) > 1 && !this.small(p) || depth > 32)) return this.call(this.rule(p, used), out, fail);
|
|
261
261
|
return this.inline(p, used, out, fail, fn, depth);
|
|
262
262
|
}
|
|
@@ -265,7 +265,7 @@ var Emitter = class {
|
|
|
265
265
|
let budget = 6;
|
|
266
266
|
const visit = (q) => {
|
|
267
267
|
const node = nodeOf(q);
|
|
268
|
-
if (--budget < 0 || node
|
|
268
|
+
if (--budget < 0 || Predicate.isTagged(node, "Suspend") || Predicate.isTagged(node, "Escaped") || Predicate.isTagged(node, "Dispatch")) return false;
|
|
269
269
|
return children(node).every(visit);
|
|
270
270
|
};
|
|
271
271
|
return visit(p);
|
|
@@ -359,7 +359,7 @@ var Emitter = class {
|
|
|
359
359
|
return this.leaf(p, node, used, out, fail, fn);
|
|
360
360
|
case "Literal": return this.leaf(p, node, used, out, fail, fn, node.literal.length * 4);
|
|
361
361
|
case "Escaped":
|
|
362
|
-
if (!this.native(node.encoding)
|
|
362
|
+
if (!this.native(node.encoding)) return this.delegate(p, used, out, fail, fn);
|
|
363
363
|
return this.escaped(p, node, out, fail, fn, d);
|
|
364
364
|
case "Map": {
|
|
365
365
|
if (!used) return this.gen(node.self, false, null, fail, fn, d);
|
|
@@ -380,7 +380,7 @@ var Emitter = class {
|
|
|
380
380
|
case "FilterMap": {
|
|
381
381
|
const t = this.v(fn);
|
|
382
382
|
const r = this.v(fn);
|
|
383
|
-
const [tag, field] = node
|
|
383
|
+
const [tag, field] = Predicate.isTagged(node, "TryMap") ? ["Success", "success"] : ["Some", "value"];
|
|
384
384
|
return this.gen(node.self, true, t, fail, fn, d) + `${r}=${this.const(node.f)}(${t});if(${r}._tag!=="${tag}"){${BT}${fail}}${set(`${r}.${field}`)}`;
|
|
385
385
|
}
|
|
386
386
|
case "Filter": {
|
|
@@ -406,7 +406,7 @@ var Emitter = class {
|
|
|
406
406
|
case "WithSpan": {
|
|
407
407
|
const st = this.v(fn);
|
|
408
408
|
const t = this.v(fn);
|
|
409
|
-
const extra = node
|
|
409
|
+
const extra = Predicate.isTagged(node, "WithSpan") ? `{start:${st},end:p}` : `$S.slice(${st},p)`;
|
|
410
410
|
return `${st}=p;` + this.gen(node.self, true, t, fail, fn, d) + set(`[${t},${extra}]`);
|
|
411
411
|
}
|
|
412
412
|
case "Span": {
|
|
@@ -436,8 +436,8 @@ var Emitter = class {
|
|
|
436
436
|
const ok = this.label();
|
|
437
437
|
const bad = this.label();
|
|
438
438
|
const t = out === null ? null : this.v(fn);
|
|
439
|
-
const some = node
|
|
440
|
-
const orElse = node
|
|
439
|
+
const some = Predicate.isTagged(node, "Opt") ? `R.some(${t})` : `${t}`;
|
|
440
|
+
const orElse = Predicate.isTagged(node, "Opt") ? "R.none()" : `${this.const(node.value)}()`;
|
|
441
441
|
return `${st}=p;${ok}:{${bad}:{${this.gen(node.self, used, t, `break ${bad};`, fn, d)}${set(some)}break ${ok};}if($S.mode!=="Backtrack"){${fail}}p=${st};${set(orElse)}}`;
|
|
442
442
|
}
|
|
443
443
|
case "Peek": {
|
|
@@ -481,11 +481,7 @@ var Emitter = class {
|
|
|
481
481
|
*/
|
|
482
482
|
float(node, out, fail, fn, d) {
|
|
483
483
|
if (!floatTexts.has(node.self) || this.kind === 2) return void 0;
|
|
484
|
-
|
|
485
|
-
while (taken._tag === "Expected") taken = nodeOf(taken.self);
|
|
486
|
-
if (taken._tag !== "Taken") return void 0;
|
|
487
|
-
const enc = taken.encoding;
|
|
488
|
-
if (enc !== void 0 && !(this.native(enc) && enc.unit === 1 && enc.asciiCompatible)) return void 0;
|
|
484
|
+
if (!scansFloat(node.self, (enc) => this.native(enc))) return void 0;
|
|
489
485
|
const t = this.v(fn);
|
|
490
486
|
const scan = this.const(floatScan);
|
|
491
487
|
const near = this.resumable ? `||$S.partial&&${scan}.read+${Margin}>E` : "";
|
|
@@ -509,7 +505,7 @@ var Emitter = class {
|
|
|
509
505
|
}
|
|
510
506
|
alt(node, used, out, fail, fn, d) {
|
|
511
507
|
const parsers = node.parsers;
|
|
512
|
-
if (parsers
|
|
508
|
+
if (Arr.isReadonlyArrayEmpty(parsers)) return `${BT}${fail}`;
|
|
513
509
|
if (parsers.length === 1) return this.gen(parsers[0], used, out, fail, fn, d);
|
|
514
510
|
const firsts = this.kind === 2 ? void 0 : parsers.map((q) => this.closure.firsts.of(q));
|
|
515
511
|
const prune = firsts !== void 0 && planAlt(firsts) !== void 0;
|
|
@@ -557,9 +553,9 @@ var Emitter = class {
|
|
|
557
553
|
return code + `default:{$S.pos=p;${r}=${q}.step($S);if(${r}===F){${fail}}p=$S.pos;}}`;
|
|
558
554
|
};
|
|
559
555
|
let sel = nodeOf(node.selector);
|
|
560
|
-
const peek = sel
|
|
556
|
+
const peek = Predicate.isTagged(sel, "Peek");
|
|
561
557
|
if (peek) sel = nodeOf(sel.self);
|
|
562
|
-
if (sel
|
|
558
|
+
if (!Predicate.isTagged(sel, "Any") || !this.native(sel.encoding)) return general(true);
|
|
563
559
|
const enc = sel.encoding;
|
|
564
560
|
const r = enc === void 0 ? void 0 : this.reader(enc);
|
|
565
561
|
const limit = r === void 0 ? this.kind === 0 ? 55296 : TableSize : Math.min(r.fast, 55296);
|
|
@@ -587,7 +583,7 @@ var Emitter = class {
|
|
|
587
583
|
const bad = this.label();
|
|
588
584
|
const n = this.v(fn);
|
|
589
585
|
const st = this.v(fn);
|
|
590
|
-
const isFold = node
|
|
586
|
+
const isFold = Predicate.isTagged(node, "Fold");
|
|
591
587
|
const cond = isFold ? node.while : void 0;
|
|
592
588
|
const keep = out !== null && used && collect === void 0;
|
|
593
589
|
const tracked = keep || cond !== void 0;
|
|
@@ -619,7 +615,7 @@ var Emitter = class {
|
|
|
619
615
|
* of a `Done` one; a resumed repetition records its result when it ends.
|
|
620
616
|
*/
|
|
621
617
|
resumePoint(fn) {
|
|
622
|
-
const key = this.const(
|
|
618
|
+
const key = this.const(new Key());
|
|
623
619
|
const entry = this.v(fn);
|
|
624
620
|
const resumed = this.v(fn);
|
|
625
621
|
const done = this.label();
|
|
@@ -690,7 +686,7 @@ var Emitter = class {
|
|
|
690
686
|
element: (f, check) => pair.parsers.map((q, j) => this.gen(q, j === pair.key || j === pair.value, j === pair.key ? key : j === pair.value ? value : null, f, fn, d)).join("") + check + `if(${deferred}===void 0&&R.isPlainKey(${key}))${out}[${key}]=${value};else ${deferred}=R.addEntry(${out},${deferred},${key},${value});`,
|
|
691
687
|
finish: `if(${deferred}!==void 0)R.flushEntries(${out},${deferred});`
|
|
692
688
|
};
|
|
693
|
-
return node
|
|
689
|
+
return Predicate.isTagged(node, "Repeat") ? this.repeat(node, true, out, fail, fn, d, collect) : this.separated(node, true, out, fail, fn, d, collect);
|
|
694
690
|
}
|
|
695
691
|
default: return this.entries(node.self, out, fail, fn, d);
|
|
696
692
|
}
|
|
@@ -823,35 +819,43 @@ var Emitter = class {
|
|
|
823
819
|
const always = highTest(c) === "true";
|
|
824
820
|
return `${head}if(${c}<${small}){if(!(${member}))break;p++}else ${never && !negate ? `break;` : always && !counted ? `p++;` : `if(${c}<${fast}||${c}>56319){if(!(${highTest(c)}))break ${loop};p++}else{${cp}=${c};if(p+1<I.length){const d=I.charCodeAt(p+1);if((d&64512)===56320)${cp}=((${c}-55296)<<10)+(d-56320)+65536}if(!(${highTest(cp)}))break ${loop};p+=${cp}>65535?2:1}`}${count}}${finish}`;
|
|
825
821
|
}
|
|
822
|
+
/**
|
|
823
|
+
* `escaped`. In a resumable build it keeps the closure compiler's
|
|
824
|
+
* checkpoints: where the next segment starts and, unless raw, the text
|
|
825
|
+
* so far, saved when a segment or an escape runs out of input.
|
|
826
|
+
*/
|
|
826
827
|
escaped(p, node, out, fail, fn, d) {
|
|
827
828
|
const enc = node.encoding;
|
|
828
829
|
const ctrl = node.control;
|
|
829
|
-
const
|
|
830
|
-
if (
|
|
830
|
+
const rd = enc === void 0 ? void 0 : this.reader(enc);
|
|
831
|
+
if (rd !== void 0 && !(ctrl < rd.fast)) return this.delegate(p, !node.raw, out, fail, fn);
|
|
831
832
|
const raw = node.raw;
|
|
833
|
+
const r = this.resumable ? this.resumePoint(fn) : void 0;
|
|
832
834
|
const acc = raw ? null : out ?? this.v(fn);
|
|
833
835
|
const x = raw ? null : this.v(fn);
|
|
834
836
|
const b = this.v(fn);
|
|
835
|
-
const st = this.v(fn);
|
|
837
|
+
const st = r?.entry ?? this.v(fn);
|
|
836
838
|
const okv = this.v(fn);
|
|
837
839
|
const loop = this.label();
|
|
838
840
|
const bad = this.label();
|
|
841
|
+
/** Saves the checkpoint of a segment starting at `pos`, when the parse ran out of input. */
|
|
842
|
+
const save = (pos) => r === void 0 ? "" : `if($S.mode==="Incomplete"&&$S.resume!==void 0)R.save($S,${r.key},${r.entry},${raw ? pos : `{out:${acc},pos:${pos}}`});`;
|
|
839
843
|
const normal = this.gen(node.normal, !raw, x, `break ${bad};`, fn, d);
|
|
840
|
-
const escape = this.gen(node.escape, !raw, x, fail
|
|
844
|
+
const escape = this.gen(node.escape, !raw, x, `${save(b)}${fail}`, fn, d);
|
|
841
845
|
const onNormal = raw ? `if(p===${b}){$S.mode="Cut";${fail}}continue ${loop};` : `if(p!==${b}){${acc}+=${x};continue ${loop}}`;
|
|
842
846
|
const slice = enc !== void 0 ? `${this.const(enc.text)}(I,${st},p)` : this.kind === 0 ? `I.slice(${st},p)` : `I.subarray(${st},p)`;
|
|
843
|
-
const ctrlTest =
|
|
844
|
-
|
|
847
|
+
const ctrlTest = rd === void 0 ? `p<E&&${this.unit("p")}===${ctrl}` : `${rd.guard("p")}&&${rd.unit("p")}===${ctrl}`;
|
|
848
|
+
const stop = r === void 0 ? loop : this.label();
|
|
849
|
+
const loopCode = `${loop}:while(p<E){${b}=p;${okv}=false;${bad}:{${normal}${okv}=true;}if(${okv}){${onNormal}}else{if($S.mode!=="Backtrack"){${save(b)}${fail}}p=${b}}if(${ctrlTest}){p+=${rd?.width ?? 1};${escape}${raw ? "" : `${acc}+=${x};`}}else break ${stop};}`;
|
|
850
|
+
const body = r === void 0 ? loopCode : `${stop}:{${loopCode}if($S.partial){$S.mode="Incomplete";${save("p")}${fail}}}`;
|
|
851
|
+
if (r === void 0) return `${raw ? `${st}=p;` : `${acc}="";`}${body}${raw && out !== null ? `${out}=${slice};` : ""}`;
|
|
852
|
+
if (acc !== null) return r.wrap(acc, `${acc}=cp.out;p=cp.pos;`, `${acc}="";`, body);
|
|
853
|
+
const value = out ?? this.v(fn);
|
|
854
|
+
return r.wrap(value, "p=cp;", "", `${body}${value}=${out === null ? "void 0" : slice};`);
|
|
845
855
|
}
|
|
846
856
|
};
|
|
847
857
|
/** The UTF-16 code units of a string. */
|
|
848
858
|
const unitsOf = (s) => Array.from({ length: s.length }, (_, i) => s.charCodeAt(i));
|
|
849
|
-
/** 1 where a small code is accepted (taking `negate` into account). */
|
|
850
|
-
const acceptTable = (set, negate) => {
|
|
851
|
-
const t = new Uint8Array(TableSize);
|
|
852
|
-
for (let c = 0; c < TableSize; c++) t[c] = set.table[c] === 1 !== negate ? 1 : 0;
|
|
853
|
-
return t;
|
|
854
|
-
};
|
|
855
859
|
/** Generates the source of a compiled parser, without building it. */
|
|
856
860
|
const generate = (root, kind, resumable = false) => {
|
|
857
861
|
const e = new Emitter(root, kind, resumable);
|
|
@@ -880,23 +884,20 @@ const compileJit = (root, kind, resumable = false) => {
|
|
|
880
884
|
*/
|
|
881
885
|
const backend = { build: (p, kind, resumable) => {
|
|
882
886
|
if (!jitSupported()) return backend$1.build(p, kind, resumable);
|
|
883
|
-
try {
|
|
884
|
-
|
|
885
|
-
return {
|
|
887
|
+
return Result.match(Result.try(() => compileJit(p, kind, resumable)), {
|
|
888
|
+
onSuccess: ({ fallbacks, source, step }) => ({
|
|
886
889
|
backend: "jit",
|
|
887
890
|
step,
|
|
888
891
|
fallbacks,
|
|
889
892
|
error: void 0,
|
|
890
893
|
source
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
return {
|
|
894
|
+
}),
|
|
895
|
+
onFailure: (error) => ({
|
|
894
896
|
...backend$1.build(p, kind, resumable),
|
|
895
897
|
jitError: error
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
+
})
|
|
899
|
+
});
|
|
898
900
|
} };
|
|
899
|
-
//#endregion
|
|
900
901
|
export { backend };
|
|
901
902
|
|
|
902
903
|
//# sourceMappingURL=jit.js.map
|