@thomasfosterau/effect-parse 0.5.0 → 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 +19 -1
- package/dist/Ascii.d.ts.map +1 -1
- package/dist/Ascii.js +5 -3
- 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 +20 -3
- package/dist/Binary.js.map +1 -1
- package/dist/Bits.d.ts.map +1 -1
- package/dist/Bits.js +4 -0
- package/dist/Bits.js.map +1 -1
- package/dist/Input.d.ts +21 -3
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +31 -4
- package/dist/Input.js.map +1 -1
- package/dist/Nom.d.ts.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 +10 -4
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +10 -24
- package/dist/Parser.js.map +1 -1
- package/dist/ParserSchema.d.ts.map +1 -1
- package/dist/ParserSchema.js +1 -2
- package/dist/ParserSchema.js.map +1 -1
- package/dist/ParserStream.d.ts +119 -12
- package/dist/ParserStream.d.ts.map +1 -1
- package/dist/ParserStream.js +282 -55
- package/dist/ParserStream.js.map +1 -1
- package/dist/Syntax.js +1 -1
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +13 -7
- package/dist/Text.js.map +1 -1
- package/dist/Token.d.ts +10 -1
- package/dist/Token.d.ts.map +1 -1
- package/dist/Token.js +14 -5
- 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 +7 -17
- package/dist/internal/compiler/closure.js.map +1 -1
- package/dist/internal/compiler/first.d.ts.map +1 -1
- package/dist/internal/compiler/first.js +2 -1
- package/dist/internal/compiler/first.js.map +1 -1
- package/dist/internal/compiler/graph.d.ts +23 -1
- package/dist/internal/compiler/graph.d.ts.map +1 -1
- package/dist/internal/compiler/graph.js +27 -5
- package/dist/internal/compiler/graph.js.map +1 -1
- package/dist/internal/compiler/jit.d.ts.map +1 -1
- package/dist/internal/compiler/jit.js +26 -13
- package/dist/internal/compiler/jit.js.map +1 -1
- package/dist/internal/compiler/registry.d.ts +1 -1
- package/dist/internal/compiler/wasm.d.ts.map +1 -1
- package/dist/internal/compiler/wasm.js +105 -34
- package/dist/internal/compiler/wasm.js.map +1 -1
- package/dist/internal/node.d.ts +19 -1
- package/dist/internal/node.d.ts.map +1 -1
- package/dist/internal/node.js +42 -8
- package/dist/internal/node.js.map +1 -1
- package/dist/internal/run.d.ts +3 -1
- package/dist/internal/run.d.ts.map +1 -1
- package/dist/internal/run.js +4 -2
- package/dist/internal/run.js.map +1 -1
- package/dist/internal/stack.d.ts +8 -0
- package/dist/internal/stack.d.ts.map +1 -1
- package/dist/internal/stack.js +17 -1
- package/dist/internal/stack.js.map +1 -1
- package/dist/internal/tokens.d.ts +10 -3
- package/dist/internal/tokens.d.ts.map +1 -1
- package/dist/internal/tokens.js +22 -9
- 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 +17 -10
- package/src/Ascii.ts +5 -3
- package/src/Binary.ts +24 -3
- package/src/Bits.ts +4 -0
- package/src/Input.ts +37 -4
- package/src/ParseError.ts +206 -52
- package/src/Parser.ts +19 -29
- package/src/ParserSchema.ts +1 -2
- package/src/ParserStream.ts +336 -62
- package/src/Text.ts +16 -12
- package/src/Token.ts +14 -5
- package/src/internal/compiler/closure.ts +9 -18
- package/src/internal/compiler/first.ts +6 -0
- package/src/internal/compiler/graph.ts +32 -4
- package/src/internal/compiler/jit.ts +37 -17
- package/src/internal/compiler/wasm.ts +141 -68
- package/src/internal/node.ts +49 -3
- package/src/internal/run.ts +4 -2
- package/src/internal/stack.ts +17 -0
- package/src/internal/tokens.ts +20 -10
- package/src/internal/tuple.ts +141 -0
|
@@ -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 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 // SAFETY: `compute` is only called from `of`, which returns before it when `kind` is 2\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 // SAFETY: a `Literal` with an encoding is a `Text` literal, which records the string it encodes\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 \"MapOrFail\":\n case \"Filter\":\n case \"Taken\":\n case \"WithTaken\":\n case \"Span\":\n case \"WithSpan\":\n case \"MapSpan\":\n case \"Context\":\n case \"Expected\":\n case \"Quiet\":\n // A fast path accepts what its grammar accepts (`Parser.withFastPath`)\n case \"FastPath\":\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 case \"SeqWith\":\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 case \"Fixed\":\n return kind !== 1 ? unknown : node.size === 0 ? emptyOptional : anyUnit\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 // SAFETY: `compute` is only called from `of`, which returns before it when `kind` is 2\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 // SAFETY: a `Literal` with an encoding is a `Text` literal, which records the string it encodes\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 \"MapOrFail\":\n case \"Filter\":\n case \"Taken\":\n case \"WithTaken\":\n case \"Span\":\n case \"WithSpan\":\n case \"MapSpan\":\n case \"Context\":\n case \"Expected\":\n case \"Quiet\":\n // A fast path accepts what its grammar accepts (`Parser.withFastPath`)\n case \"FastPath\":\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 // `not(p)` consumes nothing. Where `p`'s first set rules a unit out, `p`\n // backtracks there, so `not(p)` succeeds without consuming: Optional\n // over `p`'s units. On a unit in that set it may also fail, Cut\n // included, which Optional leaves open. So `seq(not(p), q)` starts\n // with `p`'s units and `q`'s, and an `alt` can skip it on any other (#84)\n case \"Not\":\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 case \"SeqWith\":\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 case \"Fixed\":\n return kind !== 1 ? unknown : node.size === 0 ? emptyOptional : anyUnit\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,8 +1,30 @@
|
|
|
1
1
|
import { Node, ParserLike } from "../node.js";
|
|
2
2
|
/** Whether a node is a token or a constant, always generated inline. */
|
|
3
3
|
export declare const isLeaf: (node: Node) => boolean;
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* How many times each parser reachable from `root` is used: one for every
|
|
6
|
+
* place a parent mentions it. A parser used twice is generated once, as a
|
|
7
|
+
* rule the two places call (unless it is small, see {@link isSmall}).
|
|
8
|
+
*
|
|
9
|
+
* Uses are counted, not distinct parents: `seq(p, p)` uses `p` twice. When
|
|
10
|
+
* only parents were counted, such a `p` was inlined at both places, and a
|
|
11
|
+
* grammar that does it at every level (`p = seq(p, p)`, twenty times over)
|
|
12
|
+
* compiled to 2^20 copies: 160 MB of source from twenty lines (#122).
|
|
13
|
+
*/
|
|
5
14
|
export declare const countRefs: (root: ParserLike) => WeakMap<ParserLike, number>;
|
|
15
|
+
/**
|
|
16
|
+
* The most parsers a code-generating compiler inlines for one root. Sharing
|
|
17
|
+
* is what keeps generated code proportional to the grammar; a grammar that
|
|
18
|
+
* is itself enormous (a tree of distinct parsers built by a loop, a derived
|
|
19
|
+
* schema) would still take minutes and gigabytes to generate, so past this
|
|
20
|
+
* many the compiler gives up and the next one down takes over (the JIT for
|
|
21
|
+
* WebAssembly, the closure compiler for the JIT), which costs a closure per
|
|
22
|
+
* parser instead of source text. The largest grammars in this repository
|
|
23
|
+
* and the libraries built on it inline a few thousand.
|
|
24
|
+
*/
|
|
25
|
+
export declare const MaxInlined = 100000;
|
|
26
|
+
/** Counts a parser a compiler is about to inline, failing the compilation past {@link MaxInlined}. */
|
|
27
|
+
export declare const countInlined: (inlined: number) => number;
|
|
6
28
|
/** Whether a parser is small enough to inline wherever it is used. */
|
|
7
29
|
export declare const isSmall: (p: ParserLike) => boolean;
|
|
8
30
|
/** The node a `dispatch` selects on, and whether it is looked at with `peek`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph.d.ts","names":[],"sources":["../../../src/internal/compiler/graph.ts"],"mappings":";;qBAUa,SAAU,MAAM
|
|
1
|
+
{"version":3,"file":"graph.d.ts","names":[],"sources":["../../../src/internal/compiler/graph.ts"],"mappings":";;qBAUa,SAAU,MAAM;;;;;;;;;;;qBAqBhB,YAAa,MAAM,eAAa,QAAQ;;;;;;;;;;;qBAyBxC;;qBAGA,eAAgB;;qBAUhB,UAAW,GAAG;;qBAiBd,aAAc,UAAU;WAAwB,MAAM;WAAe;;;qBAMrE,aAAc;;qBAGd,WAAY"}
|
|
@@ -8,7 +8,16 @@ import { children, nodeOf } from "../node.js";
|
|
|
8
8
|
*/
|
|
9
9
|
/** Whether a node is a token or a constant, always generated inline. */
|
|
10
10
|
const isLeaf = (node) => Predicate.isTagged(node, "Succeed") || Predicate.isTagged(node, "Fail") || Predicate.isTagged(node, "Eof") || Predicate.isTagged(node, "Location") || Predicate.isTagged(node, "RestLen") || Predicate.isTagged(node, "Any") || Predicate.isTagged(node, "Literal") || Predicate.isTagged(node, "OneOf") || Predicate.isTagged(node, "TakeWhile");
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* How many times each parser reachable from `root` is used: one for every
|
|
13
|
+
* place a parent mentions it. A parser used twice is generated once, as a
|
|
14
|
+
* rule the two places call (unless it is small, see {@link isSmall}).
|
|
15
|
+
*
|
|
16
|
+
* Uses are counted, not distinct parents: `seq(p, p)` uses `p` twice. When
|
|
17
|
+
* only parents were counted, such a `p` was inlined at both places, and a
|
|
18
|
+
* grammar that does it at every level (`p = seq(p, p)`, twenty times over)
|
|
19
|
+
* compiled to 2^20 copies: 160 MB of source from twenty lines (#122).
|
|
20
|
+
*/
|
|
12
21
|
const countRefs = (root) => {
|
|
13
22
|
const refs = /* @__PURE__ */ new WeakMap();
|
|
14
23
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
@@ -16,16 +25,29 @@ const countRefs = (root) => {
|
|
|
16
25
|
for (let p = stack.pop(); p !== void 0; p = stack.pop()) {
|
|
17
26
|
if (seen.has(p)) continue;
|
|
18
27
|
seen.add(p);
|
|
19
|
-
const counted = /* @__PURE__ */ new WeakSet();
|
|
20
28
|
for (const c of children(nodeOf(p))) {
|
|
21
|
-
if (counted.has(c)) continue;
|
|
22
|
-
counted.add(c);
|
|
23
29
|
refs.set(c, (refs.get(c) ?? 0) + 1);
|
|
24
30
|
stack.push(c);
|
|
25
31
|
}
|
|
26
32
|
}
|
|
27
33
|
return refs;
|
|
28
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* The most parsers a code-generating compiler inlines for one root. Sharing
|
|
37
|
+
* is what keeps generated code proportional to the grammar; a grammar that
|
|
38
|
+
* is itself enormous (a tree of distinct parsers built by a loop, a derived
|
|
39
|
+
* schema) would still take minutes and gigabytes to generate, so past this
|
|
40
|
+
* many the compiler gives up and the next one down takes over (the JIT for
|
|
41
|
+
* WebAssembly, the closure compiler for the JIT), which costs a closure per
|
|
42
|
+
* parser instead of source text. The largest grammars in this repository
|
|
43
|
+
* and the libraries built on it inline a few thousand.
|
|
44
|
+
*/
|
|
45
|
+
const MaxInlined = 1e5;
|
|
46
|
+
/** Counts a parser a compiler is about to inline, failing the compilation past {@link MaxInlined}. */
|
|
47
|
+
const countInlined = (inlined) => {
|
|
48
|
+
if (inlined >= 1e5) throw new RangeError(`effect-parse: the grammar is too large to generate code for (over ${MaxInlined} parsers inlined)`);
|
|
49
|
+
return inlined + 1;
|
|
50
|
+
};
|
|
29
51
|
/** Whether a parser is small enough to inline wherever it is used. */
|
|
30
52
|
const isSmall = (p) => {
|
|
31
53
|
let budget = 6;
|
|
@@ -51,6 +73,6 @@ const selectorOf = (selector) => {
|
|
|
51
73
|
const lowerAscii = (c) => c >= 65 && c <= 90 ? c + 32 : c;
|
|
52
74
|
/** Whether a code is an ASCII letter. */
|
|
53
75
|
const isLetter = (c) => c >= 65 && c <= 90 || c >= 97 && c <= 122;
|
|
54
|
-
export { countRefs, isLeaf, isLetter, isSmall, lowerAscii, selectorOf };
|
|
76
|
+
export { MaxInlined, countInlined, countRefs, isLeaf, isLetter, isSmall, lowerAscii, selectorOf };
|
|
55
77
|
|
|
56
78
|
//# sourceMappingURL=graph.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph.js","names":[],"sources":["../../../src/internal/compiler/graph.ts"],"sourcesContent":["/**\n * The shape of a grammar, as the code-generating compilers (the JIT and the\n * WebAssembly compiler) see it: which parsers are leaves, which are shared\n * and which are small enough to inline everywhere.\n */\nimport * as Predicate from \"effect/Predicate\"\nimport type { Node, ParserLike } from \"../node.js\"\nimport { children, nodeOf } from \"../node.js\"\n\n/** Whether a node is a token or a constant, always generated inline. */\nexport const isLeaf = (node: Node): boolean =>\n Predicate.isTagged(node, \"Succeed\") ||\n Predicate.isTagged(node, \"Fail\") ||\n Predicate.isTagged(node, \"Eof\") ||\n Predicate.isTagged(node, \"Location\") ||\n Predicate.isTagged(node, \"RestLen\") ||\n Predicate.isTagged(node, \"Any\") ||\n Predicate.isTagged(node, \"Literal\") ||\n Predicate.isTagged(node, \"OneOf\") ||\n Predicate.isTagged(node, \"TakeWhile\")\n\n
|
|
1
|
+
{"version":3,"file":"graph.js","names":[],"sources":["../../../src/internal/compiler/graph.ts"],"sourcesContent":["/**\n * The shape of a grammar, as the code-generating compilers (the JIT and the\n * WebAssembly compiler) see it: which parsers are leaves, which are shared\n * and which are small enough to inline everywhere.\n */\nimport * as Predicate from \"effect/Predicate\"\nimport type { Node, ParserLike } from \"../node.js\"\nimport { children, nodeOf } from \"../node.js\"\n\n/** Whether a node is a token or a constant, always generated inline. */\nexport const isLeaf = (node: Node): boolean =>\n Predicate.isTagged(node, \"Succeed\") ||\n Predicate.isTagged(node, \"Fail\") ||\n Predicate.isTagged(node, \"Eof\") ||\n Predicate.isTagged(node, \"Location\") ||\n Predicate.isTagged(node, \"RestLen\") ||\n Predicate.isTagged(node, \"Any\") ||\n Predicate.isTagged(node, \"Literal\") ||\n Predicate.isTagged(node, \"OneOf\") ||\n Predicate.isTagged(node, \"TakeWhile\")\n\n/**\n * How many times each parser reachable from `root` is used: one for every\n * place a parent mentions it. A parser used twice is generated once, as a\n * rule the two places call (unless it is small, see {@link isSmall}).\n *\n * Uses are counted, not distinct parents: `seq(p, p)` uses `p` twice. When\n * only parents were counted, such a `p` was inlined at both places, and a\n * grammar that does it at every level (`p = seq(p, p)`, twenty times over)\n * compiled to 2^20 copies: 160 MB of source from twenty lines (#122).\n */\nexport const countRefs = (root: ParserLike): WeakMap<ParserLike, number> => {\n const refs = new WeakMap<ParserLike, number>()\n const seen = new WeakSet<ParserLike>()\n const stack = [root]\n for (let p = stack.pop(); p !== undefined; p = stack.pop()) {\n if (seen.has(p)) continue\n seen.add(p)\n for (const c of children(nodeOf(p))) {\n refs.set(c, (refs.get(c) ?? 0) + 1)\n stack.push(c)\n }\n }\n return refs\n}\n\n/**\n * The most parsers a code-generating compiler inlines for one root. Sharing\n * is what keeps generated code proportional to the grammar; a grammar that\n * is itself enormous (a tree of distinct parsers built by a loop, a derived\n * schema) would still take minutes and gigabytes to generate, so past this\n * many the compiler gives up and the next one down takes over (the JIT for\n * WebAssembly, the closure compiler for the JIT), which costs a closure per\n * parser instead of source text. The largest grammars in this repository\n * and the libraries built on it inline a few thousand.\n */\nexport const MaxInlined = 100_000\n\n/** Counts a parser a compiler is about to inline, failing the compilation past {@link MaxInlined}. */\nexport const countInlined = (inlined: number): number => {\n if (inlined >= MaxInlined) {\n throw new RangeError(\n `effect-parse: the grammar is too large to generate code for (over ${MaxInlined} parsers inlined)`\n )\n }\n return inlined + 1\n}\n\n/** Whether a parser is small enough to inline wherever it is used. */\nexport const isSmall = (p: ParserLike): boolean => {\n let budget = 6\n const visit = (q: ParserLike): boolean => {\n const node = nodeOf(q)\n if (\n --budget < 0 ||\n Predicate.isTagged(node, \"Suspend\") ||\n Predicate.isTagged(node, \"Escaped\") ||\n Predicate.isTagged(node, \"Dispatch\")\n )\n return false\n return children(node).every(visit)\n }\n return visit(p)\n}\n\n/** The node a `dispatch` selects on, and whether it is looked at with `peek`. */\nexport const selectorOf = (selector: ParserLike): { readonly node: Node; readonly peek: boolean } => {\n const node = nodeOf(selector)\n return Predicate.isTagged(node, \"Peek\") ? { node: nodeOf(node.self), peek: true } : { node, peek: false }\n}\n\n/** ASCII lower case. */\nexport const lowerAscii = (c: number): number => (c >= 65 && c <= 90 ? c + 32 : c)\n\n/** Whether a code is an ASCII letter. */\nexport const isLetter = (c: number): boolean => (c >= 65 && c <= 90) || (c >= 97 && c <= 122)\n"],"mappings":";;;;;;;;;AAUA,MAAa,UAAU,SACrB,UAAU,SAAS,MAAM,SAAS,KAClC,UAAU,SAAS,MAAM,MAAM,KAC/B,UAAU,SAAS,MAAM,KAAK,KAC9B,UAAU,SAAS,MAAM,UAAU,KACnC,UAAU,SAAS,MAAM,SAAS,KAClC,UAAU,SAAS,MAAM,KAAK,KAC9B,UAAU,SAAS,MAAM,SAAS,KAClC,UAAU,SAAS,MAAM,OAAO,KAChC,UAAU,SAAS,MAAM,WAAW;;;;;;;;;;;AAYtC,MAAa,aAAa,SAAkD;CAC1E,MAAM,uBAAO,IAAI,QAA4B;CAC7C,MAAM,uBAAO,IAAI,QAAoB;CACrC,MAAM,QAAQ,CAAC,IAAI;CACnB,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,MAAM,KAAA,GAAW,IAAI,MAAM,IAAI,GAAG;EAC1D,IAAI,KAAK,IAAI,CAAC,GAAG;EACjB,KAAK,IAAI,CAAC;EACV,KAAK,MAAM,KAAK,SAAS,OAAO,CAAC,CAAC,GAAG;GACnC,KAAK,IAAI,IAAI,KAAK,IAAI,CAAC,KAAK,KAAK,CAAC;GAClC,MAAM,KAAK,CAAC;EACd;CACF;CACA,OAAO;AACT;;;;;;;;;;;AAYA,MAAa,aAAa;;AAG1B,MAAa,gBAAgB,YAA4B;CACvD,IAAI,WAAA,KACF,MAAM,IAAI,WACR,qEAAqE,WAAW,kBAClF;CAEF,OAAO,UAAU;AACnB;;AAGA,MAAa,WAAW,MAA2B;CACjD,IAAI,SAAS;CACb,MAAM,SAAS,MAA2B;EACxC,MAAM,OAAO,OAAO,CAAC;EACrB,IACE,EAAE,SAAS,KACX,UAAU,SAAS,MAAM,SAAS,KAClC,UAAU,SAAS,MAAM,SAAS,KAClC,UAAU,SAAS,MAAM,UAAU,GAEnC,OAAO;EACT,OAAO,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK;CACnC;CACA,OAAO,MAAM,CAAC;AAChB;;AAGA,MAAa,cAAc,aAA0E;CACnG,MAAM,OAAO,OAAO,QAAQ;CAC5B,OAAO,UAAU,SAAS,MAAM,MAAM,IAAI;EAAE,MAAM,OAAO,KAAK,IAAI;EAAG,MAAM;CAAK,IAAI;EAAE;EAAM,MAAM;CAAM;AAC1G;;AAGA,MAAa,cAAc,MAAuB,KAAK,MAAM,KAAK,KAAK,IAAI,KAAK;;AAGhF,MAAa,YAAY,MAAwB,KAAK,MAAM,KAAK,MAAQ,KAAK,MAAM,KAAK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jit.d.ts","names":[],"sources":["../../../src/internal/compiler/jit.ts"],"mappings":";;;;;qBAmGa;;;;;
|
|
1
|
+
{"version":3,"file":"jit.d.ts","names":[],"sources":["../../../src/internal/compiler/jit.ts"],"mappings":";;;;;qBAmGa;;;;;qBAk0CA,SAAS"}
|
|
@@ -3,6 +3,7 @@ import * as Result from "effect/Result";
|
|
|
3
3
|
import { Fail } from "../../Input.js";
|
|
4
4
|
import { floatScan, floatTexts, scanFloatBytes, scanFloatString, toFloat } from "../numbers.js";
|
|
5
5
|
import { Key } from "../key.js";
|
|
6
|
+
import { Defer, NodeId, nodeOf, scansFloat } from "../node.js";
|
|
6
7
|
import * as Resume from "../resume.js";
|
|
7
8
|
import { compileAny } from "../tokens.js";
|
|
8
9
|
import { backend as backend$1, createClosureCompiler } from "./closure.js";
|
|
@@ -11,12 +12,11 @@ import { ShortText, charOf, fastLimit, latin1, string, textIn, utf16be, utf16le,
|
|
|
11
12
|
import * as Arr from "effect/Array";
|
|
12
13
|
import { addEntry, flushEntries, fromEntries, isPlainKey } from "../entries.js";
|
|
13
14
|
import * as Stack from "../stack.js";
|
|
14
|
-
import { Defer, NodeId, nodeOf, scansFloat } from "../node.js";
|
|
15
15
|
import { buildsEntries, pairOf } from "./entries.js";
|
|
16
16
|
import { Strict, planAlt } from "./first.js";
|
|
17
17
|
import { SearchHead, StopCache, nextStop, stopChars } from "./search.js";
|
|
18
18
|
import { TableSize, acceptTable, kindOfEncoding, reachesAbove, textSet, tokenSet } from "./sets.js";
|
|
19
|
-
import { countRefs, isLeaf, isLetter, isSmall, lowerAscii, selectorOf } from "./graph.js";
|
|
19
|
+
import { countInlined, countRefs, isLeaf, isLetter, isSmall, lowerAscii, selectorOf } from "./graph.js";
|
|
20
20
|
// src/internal/compiler/jit.ts
|
|
21
21
|
/**
|
|
22
22
|
* The JIT: emits JavaScript source for a parser's description and builds
|
|
@@ -153,6 +153,8 @@ var Emitter = class {
|
|
|
153
153
|
functions = [];
|
|
154
154
|
rules = [/* @__PURE__ */ new Map(), /* @__PURE__ */ new Map()];
|
|
155
155
|
refs;
|
|
156
|
+
/** How many parsers have been inlined (see `countInlined`). */
|
|
157
|
+
inlined = 0;
|
|
156
158
|
closure;
|
|
157
159
|
next = 0;
|
|
158
160
|
constructor(root, kind, resumable = false) {
|
|
@@ -179,6 +181,16 @@ var Emitter = class {
|
|
|
179
181
|
const text = `${this.const(enc.text)}(I,${start},p)`;
|
|
180
182
|
return enc === utf8 ? `(p-${start}>${ShortText}?R.utf8Text($S,${start},p):${text})` : text;
|
|
181
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* A count or bound as source text. Every number a description contributes
|
|
186
|
+
* to the generated source is written here, so nothing but a non-negative
|
|
187
|
+
* integer can reach it: a bound is a `number` only in the types, and a
|
|
188
|
+
* string written as given would run as code (#121).
|
|
189
|
+
*/
|
|
190
|
+
num(n) {
|
|
191
|
+
if (!Number.isSafeInteger(n) || n < 0) throw new TypeError("effect-parse: a compiled bound must be a non-negative integer");
|
|
192
|
+
return String(n);
|
|
193
|
+
}
|
|
182
194
|
/** A JavaScript literal for simple values, otherwise a constant. */
|
|
183
195
|
lit(value) {
|
|
184
196
|
if (value === void 0) return "void 0";
|
|
@@ -290,12 +302,12 @@ var Emitter = class {
|
|
|
290
302
|
return `if(p>=E){${BT}${fail}}${out === null ? "" : `${out}=I[p];`}p++;`;
|
|
291
303
|
}
|
|
292
304
|
arrayOneOf(node, out, fail) {
|
|
293
|
-
return `if(p>=E||${this.const(compileAny(node.set).forCode.token)}(I[p])===${node.negate}){${BT}${fail}}${out === null ? "" : `${out}=I[p];`}p++;`;
|
|
305
|
+
return `if(p>=E||${this.const(compileAny(node.set).forCode.token)}(I[p])===${node.negate === true}){${BT}${fail}}${out === null ? "" : `${out}=I[p];`}p++;`;
|
|
294
306
|
}
|
|
295
307
|
arrayTakeWhile(node, out, fail, fn) {
|
|
296
308
|
const m = this.const(compileAny(node.set).forCode.token);
|
|
297
309
|
const st = this.v(fn);
|
|
298
|
-
return `${st}=p;while(p<E${node.max === Infinity ? "" : `&&p-${st}<${node.max}`}&&${m}(I[p])!==${node.negate})p++;` + (node.min > 0 ? `if(p-${st}<${node.min}){${BT}${fail}}` : "") + (out === null ? "" : `${out}=I.slice(${st},p);`);
|
|
310
|
+
return `${st}=p;while(p<E${node.max === Infinity ? "" : `&&p-${st}<${this.num(node.max)}`}&&${m}(I[p])!==${node.negate === true})p++;` + (node.min > 0 ? `if(p-${st}<${this.num(node.min)}){${BT}${fail}}` : "") + (out === null ? "" : `${out}=I.slice(${st},p);`);
|
|
299
311
|
}
|
|
300
312
|
call(name, out, fail) {
|
|
301
313
|
if (out === null) return `if(${name}(p)===F){${fail}}p=P;`;
|
|
@@ -311,6 +323,7 @@ var Emitter = class {
|
|
|
311
323
|
return enc === void 0 ? this.kind !== 2 : kindOfEncoding(enc) === this.kind;
|
|
312
324
|
}
|
|
313
325
|
inline(p, used, out, fail, fn, depth) {
|
|
326
|
+
this.inlined = countInlined(this.inlined);
|
|
314
327
|
const node = nodeOf(p);
|
|
315
328
|
const set = (value) => out === null ? "" : `${out}=${value};`;
|
|
316
329
|
const d = depth + 1;
|
|
@@ -469,7 +482,7 @@ var Emitter = class {
|
|
|
469
482
|
case "Fixed": {
|
|
470
483
|
if (this.kind !== 1) return this.delegate(p, used, out, fail, fn);
|
|
471
484
|
const read = used ? `${out ?? this.v(fn)}=${this.const(node.read)}(I,p,$S);` : "";
|
|
472
|
-
return `if(E-p>=${node.size}){${read}p+=${node.size}}else{${this.delegate(p, used, out, fail, fn)}}`;
|
|
485
|
+
return `if(E-p>=${this.num(node.size)}){${read}p+=${this.num(node.size)}}else{${this.delegate(p, used, out, fail, fn)}}`;
|
|
473
486
|
}
|
|
474
487
|
default: return this.delegate(p, used, out, fail, fn);
|
|
475
488
|
}
|
|
@@ -651,13 +664,13 @@ var Emitter = class {
|
|
|
651
664
|
add = `${acc}.push(${x});`;
|
|
652
665
|
}
|
|
653
666
|
}
|
|
654
|
-
const check =
|
|
655
|
-
const bound = max === Infinity ? "" : `${n}<${max}`;
|
|
667
|
+
const check = `if(p===${st}){$S.mode="Cut";${fail}}`;
|
|
668
|
+
const bound = max === Infinity ? "" : `${n}<${this.num(max)}`;
|
|
656
669
|
const r = this.resumable ? this.resumePoint(fn) : void 0;
|
|
657
670
|
const held = collect?.value ?? acc;
|
|
658
671
|
const save = r === void 0 ? "" : `if($S.mode==="Incomplete"&&$S.resume!==void 0)R.save($S,${r.key},${r.entry},{acc:${held},${collect?.saved ?? ""}count:${n},pos:${st}});`;
|
|
659
672
|
const element = collect === void 0 ? `${this.gen(node.self, tracked, x, `break ${bad};`, fn, d)}${check}${add}` : collect.element(`break ${bad};`, check);
|
|
660
|
-
const body = `${loop}:for(;${bound};${n}++){${cond === void 0 ? "" : `if(${min > 0 ? `${n}>=${min}&&` : ""}!${this.const(cond)}(${acc}))break ${loop};`}${st}=p;${bad}:{${element}continue ${loop};}${save}if($S.mode!=="Backtrack"${min > 0 ? `||${n}<${min}` : ""}){${fail}}p=${st};break ${loop};}`;
|
|
673
|
+
const body = `${loop}:for(;${bound};${n}++){${cond === void 0 ? "" : `if(${min > 0 ? `${n}>=${this.num(min)}&&` : ""}!${this.const(cond)}(${acc}))break ${loop};`}${st}=p;${bad}:{${element}continue ${loop};}${save}if($S.mode!=="Backtrack"${min > 0 ? `||${n}<${this.num(min)}` : ""}){${fail}}p=${st};break ${loop};}`;
|
|
661
674
|
if (r === void 0) return `${init}${n}=0;${body}${collect?.finish ?? ""}`;
|
|
662
675
|
return r.wrap(held, `${held}=cp.acc;${collect?.restore ?? ""}${n}=cp.count;p=cp.pos;`, `${init}${n}=0;`, `${body}${collect?.finish ?? ""}`);
|
|
663
676
|
}
|
|
@@ -699,9 +712,9 @@ var Emitter = class {
|
|
|
699
712
|
};
|
|
700
713
|
const self = (f) => collect === void 0 ? this.gen(node.self, keep, x, f, fn, d) : collect.element(f, "");
|
|
701
714
|
const sep = (f) => this.gen(node.separator, false, null, f, fn, d);
|
|
702
|
-
const check =
|
|
715
|
+
const check = `if(p===${st}){$S.mode="Cut";${fail}}`;
|
|
703
716
|
const first = `${collect?.init ?? (keep ? `${acc}=[];` : "")}${n}=0;${st}=p;` + attempt(self, `${push}${n}++;`, min > 0 ? "||true" : "", "");
|
|
704
|
-
const rest = `${loop}:while(${max === Infinity ? "true" : `${n}<${max}`}){${st}=p;` + attempt(sep, "", `||${n}<${min}`, save) + check + attempt(self, `${push}${n}++;continue ${loop};`, `||${n}<${min}`, save) + `}`;
|
|
717
|
+
const rest = `${loop}:while(${max === Infinity ? "true" : `${n}<${this.num(max)}`}){${st}=p;` + attempt(sep, "", `||${n}<${this.num(min)}`, save) + check + attempt(self, `${push}${n}++;continue ${loop};`, `||${n}<${this.num(min)}`, save) + `}`;
|
|
705
718
|
if (r === void 0) return `${done}:{${first}${rest}}${collect?.finish ?? ""}`;
|
|
706
719
|
return r.wrap(held, `${held}=cp.acc;${collect?.restore ?? ""}${n}=cp.count;p=cp.pos;`, "", `${done}:{if(!${r.resumed}){${first}}${rest}}${collect?.finish ?? ""}`);
|
|
707
720
|
}
|
|
@@ -854,9 +867,9 @@ var Emitter = class {
|
|
|
854
867
|
const loop = this.label();
|
|
855
868
|
const counted = max !== Infinity || min > 1;
|
|
856
869
|
const count = counted ? `${n}++;` : "";
|
|
857
|
-
const bound = max !== Infinity ? `&&${n}<${max}` : "";
|
|
870
|
+
const bound = max !== Infinity ? `&&${n}<${this.num(max)}` : "";
|
|
858
871
|
const slice = enc !== void 0 ? this.text(enc, st) : kind === 0 ? `I.slice(${st},p)` : `I.subarray(${st},p)`;
|
|
859
|
-
const finish = (min > 0 ? `if(${counted ? n : `p-${st}`}<${min}){${BT}${fail}}` : "") + (out === null ? "" : `${out}=${slice};`);
|
|
872
|
+
const finish = (min > 0 ? `if(${counted ? n : `p-${st}`}<${this.num(min)}){${BT}${fail}}` : "") + (out === null ? "" : `${out}=${slice};`);
|
|
860
873
|
const head = `${st}=p;${counted ? `${n}=0;` : ""}${loop}:while(p<E${bound}){${c}=${this.unit("p")};`;
|
|
861
874
|
const member = this.member(accept, c);
|
|
862
875
|
if (kind === 1 && (enc === void 0 || fastLimit(enc) >= TableSize)) return `${head}if(!(${member}))break;p++;${count}}${finish}`;
|
|
@@ -915,7 +928,7 @@ var Emitter = class {
|
|
|
915
928
|
const escape = this.gen(node.escape, !raw, x, `${save(b)}${fail}`, fn, d);
|
|
916
929
|
const onNormal = raw ? `if(p===${b}){$S.mode="Cut";${fail}}continue ${loop};` : `if(p!==${b}){${acc}+=${x};continue ${loop}}`;
|
|
917
930
|
const slice = enc !== void 0 ? this.text(enc, st) : this.kind === 0 ? `I.slice(${st},p)` : `I.subarray(${st},p)`;
|
|
918
|
-
const ctrlTest = rd === void 0 ? `p<E&&${this.unit("p")}===${ctrl}` : `${rd.guard("p")}&&${rd.unit("p")}===${ctrl}`;
|
|
931
|
+
const ctrlTest = rd === void 0 ? `p<E&&${this.unit("p")}===${this.num(ctrl)}` : `${rd.guard("p")}&&${rd.unit("p")}===${this.num(ctrl)}`;
|
|
919
932
|
const stop = r === void 0 ? loop : this.label();
|
|
920
933
|
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};}`;
|
|
921
934
|
const body = r === void 0 ? loopCode : `${stop}:{${loopCode}if($S.partial){$S.incomplete(0);${save("p")}${fail}}}`;
|