@thomasfosterau/effect-parse 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -14
- package/dist/Ascii.d.ts +11 -4
- package/dist/Ascii.d.ts.map +1 -1
- package/dist/Ascii.js +7 -1
- package/dist/Ascii.js.map +1 -1
- package/dist/Binary.d.ts.map +1 -1
- package/dist/Binary.js +64 -35
- package/dist/Binary.js.map +1 -1
- package/dist/Bits.d.ts.map +1 -1
- package/dist/Bits.js +7 -4
- package/dist/Bits.js.map +1 -1
- package/dist/Compiler.d.ts +74 -2
- package/dist/Compiler.d.ts.map +1 -1
- package/dist/Compiler.js +78 -1
- package/dist/Compiler.js.map +1 -1
- package/dist/Expression.d.ts.map +1 -1
- package/dist/Expression.js +86 -74
- package/dist/Expression.js.map +1 -1
- package/dist/Input.d.ts +37 -4
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +42 -0
- package/dist/Input.js.map +1 -1
- package/dist/Nom.d.ts +5 -15
- package/dist/Nom.d.ts.map +1 -1
- package/dist/Nom.js.map +1 -1
- package/dist/ParseError.d.ts +2 -2
- package/dist/ParseError.d.ts.map +1 -1
- package/dist/ParseError.js +1 -1
- package/dist/ParseError.js.map +1 -1
- package/dist/Parser.d.ts +370 -28
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +390 -19
- package/dist/Parser.js.map +1 -1
- package/dist/ParserSchema.js +2 -2
- package/dist/ParserSchema.js.map +1 -1
- package/dist/ParserStream.d.ts +3 -2
- package/dist/ParserStream.d.ts.map +1 -1
- package/dist/ParserStream.js +15 -10
- package/dist/ParserStream.js.map +1 -1
- package/dist/Syntax.d.ts +23 -5
- package/dist/Syntax.d.ts.map +1 -1
- package/dist/Syntax.js.map +1 -1
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +9 -9
- package/dist/Text.js.map +1 -1
- package/dist/Token.d.ts +55 -10
- package/dist/Token.d.ts.map +1 -1
- package/dist/Token.js +59 -21
- package/dist/Token.js.map +1 -1
- package/dist/internal/compiler/closure.d.ts.map +1 -1
- package/dist/internal/compiler/closure.js +257 -97
- package/dist/internal/compiler/closure.js.map +1 -1
- package/dist/internal/compiler/entries.d.ts +3 -1
- package/dist/internal/compiler/entries.d.ts.map +1 -1
- package/dist/internal/compiler/entries.js +3 -2
- package/dist/internal/compiler/entries.js.map +1 -1
- package/dist/internal/compiler/first.d.ts.map +1 -1
- package/dist/internal/compiler/first.js +7 -1
- package/dist/internal/compiler/first.js.map +1 -1
- package/dist/internal/compiler/graph.d.ts +17 -0
- package/dist/internal/compiler/graph.d.ts.map +1 -0
- package/dist/internal/compiler/graph.js +56 -0
- package/dist/internal/compiler/graph.js.map +1 -0
- package/dist/internal/compiler/jit.d.ts +5 -0
- package/dist/internal/compiler/jit.d.ts.map +1 -1
- package/dist/internal/compiler/jit.js +185 -96
- package/dist/internal/compiler/jit.js.map +1 -1
- package/dist/internal/compiler/registry.d.ts +10 -2
- package/dist/internal/compiler/registry.d.ts.map +1 -1
- package/dist/internal/compiler/registry.js.map +1 -1
- package/dist/internal/compiler/search.d.ts +32 -0
- package/dist/internal/compiler/search.d.ts.map +1 -0
- package/dist/internal/compiler/search.js +68 -0
- package/dist/internal/compiler/search.js.map +1 -0
- package/dist/internal/compiler/sets.d.ts.map +1 -1
- package/dist/internal/compiler/sets.js +1 -1
- package/dist/internal/compiler/sets.js.map +1 -1
- package/dist/internal/compiler/wasm.d.ts +8 -0
- package/dist/internal/compiler/wasm.d.ts.map +1 -0
- package/dist/internal/compiler/wasm.js +2769 -0
- package/dist/internal/compiler/wasm.js.map +1 -0
- package/dist/internal/compiler/wasmAsm.d.ts +199 -0
- package/dist/internal/compiler/wasmAsm.d.ts.map +1 -0
- package/dist/internal/compiler/wasmAsm.js +427 -0
- package/dist/internal/compiler/wasmAsm.js.map +1 -0
- package/dist/internal/entries.d.ts +3 -1
- package/dist/internal/entries.d.ts.map +1 -1
- package/dist/internal/entries.js +1 -2
- package/dist/internal/entries.js.map +1 -1
- package/dist/internal/node.d.ts +58 -2
- package/dist/internal/node.d.ts.map +1 -1
- package/dist/internal/node.js +13 -3
- package/dist/internal/node.js.map +1 -1
- package/dist/internal/numbers.d.ts.map +1 -1
- package/dist/internal/numbers.js.map +1 -1
- package/dist/internal/run.d.ts +12 -0
- package/dist/internal/run.d.ts.map +1 -1
- package/dist/internal/run.js +51 -11
- package/dist/internal/run.js.map +1 -1
- package/dist/internal/stack.d.ts +6 -0
- package/dist/internal/stack.d.ts.map +1 -1
- package/dist/internal/stack.js +8 -2
- package/dist/internal/stack.js.map +1 -1
- package/dist/internal/syntax.d.ts +4 -4
- package/dist/internal/syntax.d.ts.map +1 -1
- package/dist/internal/syntax.js +18 -10
- package/dist/internal/syntax.js.map +1 -1
- package/dist/internal/text.d.ts +32 -0
- package/dist/internal/text.d.ts.map +1 -1
- package/dist/internal/text.js +68 -14
- package/dist/internal/text.js.map +1 -1
- package/dist/internal/tokens.d.ts +13 -0
- package/dist/internal/tokens.d.ts.map +1 -1
- package/dist/internal/tokens.js +59 -39
- package/dist/internal/tokens.js.map +1 -1
- package/package.json +5 -4
- package/src/Ascii.ts +42 -9
- package/src/Binary.ts +151 -71
- package/src/Bits.ts +12 -6
- package/src/Compiler.ts +101 -10
- package/src/Expression.ts +94 -81
- package/src/Input.ts +65 -6
- package/src/Nom.ts +15 -5
- package/src/ParseError.ts +9 -4
- package/src/Parser.ts +682 -129
- package/src/ParserSchema.ts +1 -1
- package/src/ParserStream.ts +40 -19
- package/src/Syntax.ts +60 -36
- package/src/Text.ts +16 -15
- package/src/Token.ts +138 -29
- package/src/internal/compiler/closure.ts +362 -135
- package/src/internal/compiler/entries.ts +4 -2
- package/src/internal/compiler/first.ts +10 -0
- package/src/internal/compiler/graph.ts +68 -0
- package/src/internal/compiler/jit.ts +284 -154
- package/src/internal/compiler/registry.ts +10 -2
- package/src/internal/compiler/search.ts +68 -0
- package/src/internal/compiler/sets.ts +7 -3
- package/src/internal/compiler/wasm.ts +3203 -0
- package/src/internal/compiler/wasmAsm.ts +484 -0
- package/src/internal/entries.ts +10 -4
- package/src/internal/node.ts +54 -4
- package/src/internal/numbers.ts +3 -1
- package/src/internal/run.ts +71 -12
- package/src/internal/stack.ts +8 -1
- package/src/internal/syntax.ts +39 -18
- package/src/internal/text.ts +97 -9
- package/src/internal/tokens.ts +96 -14
package/dist/Binary.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Binary.js","names":["Token"],"sources":["../src/Binary.ts"],"sourcesContent":["/**\n * Parsers for binary formats: fixed-width integers and floats in either\n * byte order, and length-prefixed data (winnow's `binary` module, nom's\n * `number` and `multi::length_*` parsers).\n *\n * Integers up to 32 bits are returned as `number`, wider integers as\n * `bigint`.\n *\n * @example\n * ```ts\n * import { Binary, Parser } from \"@thomasfosterau/effect-parse\"\n *\n * // A length-prefixed (u16 big-endian) payload\n * const frame = Binary.lengthTake(Binary.beU16)\n * Parser.parse(frame, new Uint8Array([0, 2, 0xca, 0xfe])) // Uint8Array [0xca, 0xfe]\n * ```\n *\n * @since 0.1.0\n */\nimport * as Predicate from \"effect/Predicate\"\nimport type { Input, Slice, State } from \"./Input.js\"\nimport { Fail } from \"./Input.js\"\nimport type { Parser } from \"./Parser.js\"\nimport * as P from \"./Parser.js\"\nimport * as Token from \"./Token.js\"\n\nexport {\n /**\n * Runs a bit-level parser on byte input. See the `Bits` module.\n *\n * @since 0.1.0\n * @category bits\n */\n bits\n} from \"./Bits.js\"\n\n/**\n * A byte order. `\"native\"` is the byte order of the current platform.\n *\n * @since 0.1.0\n * @category models\n */\nexport type Endianness = \"big\" | \"little\" | \"native\"\n\nconst nativeLittle = /*#__PURE__*/ new Uint8Array(/*#__PURE__*/ new Uint16Array([1]).buffer)[0] === 1\n\nconst fixed = <A>(\n size: number,\n name: string,\n read: (view: DataView, offset: number) => A\n): Parser<A, never, never, Uint8Array> => {\n const expected = [`${size} byte${size === 1 ? \"\" : \"s\"}`]\n return P.make((state: State<Uint8Array>) => {\n const pos = state.pos\n const avail = state.end - pos\n if (avail < size) return state.eoi(\"Token\", expected, size - avail)\n const bytes = state.input\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n state.pos = pos + size\n return read(view, pos)\n }, name)\n}\n\nconst readU24 = (little: boolean) => (v: DataView, o: number) =>\n little\n ? v.getUint8(o) | (v.getUint8(o + 1) << 8) | (v.getUint8(o + 2) << 16)\n : (v.getUint8(o) << 16) | (v.getUint8(o + 1) << 8) | v.getUint8(o + 2)\n\nconst readI24 = (little: boolean) => {\n const u = readU24(little)\n return (v: DataView, o: number) => {\n const x = u(v, o)\n return x & 0x800000 ? x - 0x1000000 : x\n }\n}\n\nconst readU128 = (little: boolean) => (v: DataView, o: number) => {\n const a = v.getBigUint64(o, little)\n const b = v.getBigUint64(o + 8, little)\n return little ? (b << 64n) | a : (a << 64n) | b\n}\n\nconst readI128 = (little: boolean) => {\n const u = readU128(little)\n return (v: DataView, o: number) => BigInt.asIntN(128, u(v, o))\n}\n\n/**\n * An unsigned byte.\n *\n * @since 0.1.0\n * @category integers\n */\nexport const u8: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(1, \"u8\", (v, o) => v.getUint8(o))\n\n/**\n * A signed byte.\n *\n * @since 0.1.0\n * @category integers\n */\nexport const i8: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(1, \"i8\", (v, o) => v.getInt8(o))\n\n/** @since 0.1.0 @category integers */\nexport const beU16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(2, \"beU16\", (v, o) =>\n v.getUint16(o, false)\n)\n/** @since 0.1.0 @category integers */\nexport const leU16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(2, \"leU16\", (v, o) =>\n v.getUint16(o, true)\n)\n/** @since 0.1.0 @category integers */\nexport const beI16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(2, \"beI16\", (v, o) =>\n v.getInt16(o, false)\n)\n/** @since 0.1.0 @category integers */\nexport const leI16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(2, \"leI16\", (v, o) =>\n v.getInt16(o, true)\n)\n/** @since 0.1.0 @category integers */\nexport const beU24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 3,\n \"beU24\",\n /*#__PURE__*/ readU24(false)\n)\n/** @since 0.1.0 @category integers */\nexport const leU24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 3,\n \"leU24\",\n /*#__PURE__*/ readU24(true)\n)\n/** @since 0.1.0 @category integers */\nexport const beI24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 3,\n \"beI24\",\n /*#__PURE__*/ readI24(false)\n)\n/** @since 0.1.0 @category integers */\nexport const leI24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 3,\n \"leI24\",\n /*#__PURE__*/ readI24(true)\n)\n/** @since 0.1.0 @category integers */\nexport const beU32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, \"beU32\", (v, o) =>\n v.getUint32(o, false)\n)\n/** @since 0.1.0 @category integers */\nexport const leU32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, \"leU32\", (v, o) =>\n v.getUint32(o, true)\n)\n/** @since 0.1.0 @category integers */\nexport const beI32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, \"beI32\", (v, o) =>\n v.getInt32(o, false)\n)\n/** @since 0.1.0 @category integers */\nexport const leI32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, \"leI32\", (v, o) =>\n v.getInt32(o, true)\n)\n/** @since 0.1.0 @category integers */\nexport const beU64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, \"beU64\", (v, o) =>\n v.getBigUint64(o, false)\n)\n/** @since 0.1.0 @category integers */\nexport const leU64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, \"leU64\", (v, o) =>\n v.getBigUint64(o, true)\n)\n/** @since 0.1.0 @category integers */\nexport const beI64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, \"beI64\", (v, o) =>\n v.getBigInt64(o, false)\n)\n/** @since 0.1.0 @category integers */\nexport const leI64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, \"leI64\", (v, o) =>\n v.getBigInt64(o, true)\n)\n/** @since 0.1.0 @category integers */\nexport const beU128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 16,\n \"beU128\",\n /*#__PURE__*/ readU128(false)\n)\n/** @since 0.1.0 @category integers */\nexport const leU128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 16,\n \"leU128\",\n /*#__PURE__*/ readU128(true)\n)\n/** @since 0.1.0 @category integers */\nexport const beI128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 16,\n \"beI128\",\n /*#__PURE__*/ readI128(false)\n)\n/** @since 0.1.0 @category integers */\nexport const leI128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 16,\n \"leI128\",\n /*#__PURE__*/ readI128(true)\n)\n\n/** @since 0.1.0 @category floats */\nexport const beF32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, \"beF32\", (v, o) =>\n v.getFloat32(o, false)\n)\n/** @since 0.1.0 @category floats */\nexport const leF32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, \"leF32\", (v, o) =>\n v.getFloat32(o, true)\n)\n/** @since 0.1.0 @category floats */\nexport const beF64: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, \"beF64\", (v, o) =>\n v.getFloat64(o, false)\n)\n/** @since 0.1.0 @category floats */\nexport const leF64: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, \"leF64\", (v, o) =>\n v.getFloat64(o, true)\n)\n\nconst byEndian =\n <A>(big: A, little: A) =>\n (endian: Endianness): A =>\n endian === \"big\" ? big : endian === \"little\" ? little : nativeLittle ? little : big\n\n/**\n * An unsigned 16-bit integer in the given byte order (winnow's `u16`).\n *\n * @since 0.1.0\n * @category integers\n */\nexport const u16: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beU16,\n leU16\n)\n/** @since 0.1.0 @category integers */\nexport const i16: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beI16,\n leI16\n)\n/** @since 0.1.0 @category integers */\nexport const u24: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beU24,\n leU24\n)\n/** @since 0.1.0 @category integers */\nexport const i24: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beI24,\n leI24\n)\n/** @since 0.1.0 @category integers */\nexport const u32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beU32,\n leU32\n)\n/** @since 0.1.0 @category integers */\nexport const i32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beI32,\n leI32\n)\n/** @since 0.1.0 @category integers */\nexport const u64: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beU64,\n leU64\n)\n/** @since 0.1.0 @category integers */\nexport const i64: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beI64,\n leI64\n)\n/** @since 0.1.0 @category integers */\nexport const u128: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beU128,\n leU128\n)\n/** @since 0.1.0 @category integers */\nexport const i128: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beI128,\n leI128\n)\n/** @since 0.1.0 @category floats */\nexport const f32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beF32,\n leF32\n)\n/** @since 0.1.0 @category floats */\nexport const f64: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beF64,\n leF64\n)\n\nconst toCount = (n: number | bigint): number => (Predicate.isBigInt(n) ? Number(n) : n)\n\n/**\n * Parses a length with `count`, then takes that many tokens (winnow's\n * `length_take`, nom's `length_data`).\n *\n * @since 0.1.0\n * @category length-prefixed\n */\nexport const lengthTake = <E, R, I extends Input = Uint8Array>(\n count: Parser<number | bigint, E, R, I>\n): Parser<Slice<I>, E, R, I> => {\n const countStep = count.step\n return P.make((state: State<I>) => {\n const n = countStep(state)\n if (n === Fail) return Fail\n return (Token.take<I>(toCount(n)).step as any)(state)\n }, \"lengthTake\")\n}\n\n/**\n * Parses a length with `count`, then applies `parser` that many times\n * (winnow's `length_repeat`, nom's `length_count`).\n *\n * @since 0.1.0\n * @category length-prefixed\n */\nexport const lengthRepeat = <E, R, I extends Input, A, E2, R2, I2 extends Input>(\n count: Parser<number | bigint, E, R, I>,\n parser: Parser<A, E2, R2, I2>\n): Parser<Array<A>, E | E2, R | R2, I & I2> =>\n P.flatMap(count, (n) => P.repeat(parser, toCount(n)) as Parser<Array<A>, E2, R2, I2>)\n\n/**\n * Parses a length with `count`, takes that many tokens, and applies\n * `parser` to them (winnow's `length_and_then`, nom's `length_value`).\n * `parser` does not need to consume the whole slice.\n *\n * @since 0.1.0\n * @category length-prefixed\n */\nexport const lengthAndThen = <E, R, I extends Input, A, E2, R2>(\n count: Parser<number | bigint, E, R, I>,\n parser: Parser<A, E2, R2, Slice<I> & Input>\n): Parser<A, E | E2, R | R2, I> =>\n P.mapParser(lengthTake(count) as Parser<Slice<I> & Input, E, R, I>, P.complete(parser))\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Binary.js","names":["Token"],"sources":["../src/Binary.ts"],"sourcesContent":["/**\n * Parsers for binary formats: fixed-width integers and floats in either\n * byte order, and length-prefixed data (winnow's `binary` module, nom's\n * `number` and `multi::length_*` parsers).\n *\n * Integers up to 32 bits are returned as `number`, wider integers as\n * `bigint`.\n *\n * @example\n * ```ts\n * import { Binary, Parser } from \"@thomasfosterau/effect-parse\"\n *\n * // A length-prefixed (u16 big-endian) payload\n * const frame = Binary.lengthTake(Binary.beU16)\n * Parser.parse(frame, new Uint8Array([0, 2, 0xca, 0xfe])) // Uint8Array [0xca, 0xfe]\n * ```\n *\n * @since 0.1.0\n */\nimport * as Predicate from \"effect/Predicate\"\nimport type { Input, Slice, State } from \"./Input.js\"\nimport { Fail } from \"./Input.js\"\nimport type { Parser } from \"./Parser.js\"\nimport * as P from \"./Parser.js\"\nimport * as Token from \"./Token.js\"\n\nexport {\n /**\n * Runs a bit-level parser on byte input. See the `Bits` module.\n *\n * @since 0.1.0\n * @category bits\n */\n bits\n} from \"./Bits.js\"\n\n/**\n * A byte order. `\"native\"` is the byte order of the current platform.\n *\n * @since 0.1.0\n * @category models\n */\nexport type Endianness = \"big\" | \"little\" | \"native\"\n\nconst nativeLittle = /*#__PURE__*/ new Uint8Array(/*#__PURE__*/ new Uint16Array([1]).buffer)[0] === 1\n\n/** Reads a number at an offset of a state's bytes. */\ntype Read<A> = (bytes: Uint8Array, offset: number, state: State<Uint8Array>) => A\n\n/**\n * A `DataView` of a state's bytes, for the numbers integer arithmetic can't\n * read: created once per state (whose input never changes), as one per\n * read cost most of a number's time.\n */\nconst viewOf = (state: State<Uint8Array>): DataView => {\n const b = state.input\n return (state.view ??= new DataView(b.buffer, b.byteOffset, b.byteLength))\n}\n\n/** A {@link Read} through the state's view. */\nconst viewed =\n <A>(read: (view: DataView, offset: number) => A): Read<A> =>\n (_, o, s) =>\n read(viewOf(s), o)\n\nconst fixed = <A>(size: number, name: string, read: Read<A>): Parser<A, never, never, Uint8Array> => {\n const expected = [`${size} byte${size === 1 ? \"\" : \"s\"}`]\n return P.described(\n (state: State<Uint8Array>) => {\n const pos = state.pos\n const avail = state.end - pos\n if (avail < size) return state.eoi(\"Token\", expected, size - avail)\n state.pos = pos + size\n return read(state.input, pos, state)\n },\n name,\n { _tag: \"Fixed\", size, read }\n )\n}\n\n// Integers of up to 32 bits are read from the bytes; the rest through a view\nconst readU24 =\n (little: boolean): Read<number> =>\n (b, o) =>\n little ? b[o] | (b[o + 1] << 8) | (b[o + 2] << 16) : (b[o] << 16) | (b[o + 1] << 8) | b[o + 2]\n\nconst readI24 = (little: boolean): Read<number> => {\n const u = readU24(little)\n return (b, o, s) => (u(b, o, s) << 8) >> 8\n}\n\nconst readU128 = (little: boolean): Read<bigint> =>\n viewed((v, o) => {\n const a = v.getBigUint64(o, little)\n const b = v.getBigUint64(o + 8, little)\n return little ? (b << 64n) | a : (a << 64n) | b\n })\n\nconst readI128 = (little: boolean): Read<bigint> => {\n const u = readU128(little)\n return (b, o, s) => BigInt.asIntN(128, u(b, o, s))\n}\n\n/**\n * An unsigned byte.\n *\n * @since 0.1.0\n * @category integers\n */\nexport const u8: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(1, \"u8\", (b, o) => b[o])\n\n/**\n * A signed byte.\n *\n * @since 0.1.0\n * @category integers\n */\nexport const i8: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(1, \"i8\", (b, o) => (b[o] << 24) >> 24)\n\n/** @since 0.1.0 @category integers */\nexport const beU16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 2,\n \"beU16\",\n (b, o) => (b[o] << 8) | b[o + 1]\n)\n/** @since 0.1.0 @category integers */\nexport const leU16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 2,\n \"leU16\",\n (b, o) => b[o] | (b[o + 1] << 8)\n)\n/** @since 0.1.0 @category integers */\nexport const beI16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 2,\n \"beI16\",\n (b, o) => (((b[o] << 8) | b[o + 1]) << 16) >> 16\n)\n/** @since 0.1.0 @category integers */\nexport const leI16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 2,\n \"leI16\",\n (b, o) => ((b[o] | (b[o + 1] << 8)) << 16) >> 16\n)\n/** @since 0.1.0 @category integers */\nexport const beU24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 3,\n \"beU24\",\n /*#__PURE__*/ readU24(false)\n)\n/** @since 0.1.0 @category integers */\nexport const leU24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 3,\n \"leU24\",\n /*#__PURE__*/ readU24(true)\n)\n/** @since 0.1.0 @category integers */\nexport const beI24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 3,\n \"beI24\",\n /*#__PURE__*/ readI24(false)\n)\n/** @since 0.1.0 @category integers */\nexport const leI24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 3,\n \"leI24\",\n /*#__PURE__*/ readI24(true)\n)\n/** @since 0.1.0 @category integers */\nexport const beU32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 4,\n \"beU32\",\n (b, o) => ((b[o] << 24) | (b[o + 1] << 16) | (b[o + 2] << 8) | b[o + 3]) >>> 0\n)\n/** @since 0.1.0 @category integers */\nexport const leU32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 4,\n \"leU32\",\n (b, o) => (b[o] | (b[o + 1] << 8) | (b[o + 2] << 16) | (b[o + 3] << 24)) >>> 0\n)\n/** @since 0.1.0 @category integers */\nexport const beI32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 4,\n \"beI32\",\n (b, o) => (b[o] << 24) | (b[o + 1] << 16) | (b[o + 2] << 8) | b[o + 3]\n)\n/** @since 0.1.0 @category integers */\nexport const leI32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 4,\n \"leI32\",\n (b, o) => b[o] | (b[o + 1] << 8) | (b[o + 2] << 16) | (b[o + 3] << 24)\n)\n/** @since 0.1.0 @category integers */\nexport const beU64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 8,\n \"beU64\",\n /*#__PURE__*/ viewed((v, o) => v.getBigUint64(o, false))\n)\n/** @since 0.1.0 @category integers */\nexport const leU64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 8,\n \"leU64\",\n /*#__PURE__*/ viewed((v, o) => v.getBigUint64(o, true))\n)\n/** @since 0.1.0 @category integers */\nexport const beI64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 8,\n \"beI64\",\n /*#__PURE__*/ viewed((v, o) => v.getBigInt64(o, false))\n)\n/** @since 0.1.0 @category integers */\nexport const leI64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 8,\n \"leI64\",\n /*#__PURE__*/ viewed((v, o) => v.getBigInt64(o, true))\n)\n/** @since 0.1.0 @category integers */\nexport const beU128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 16,\n \"beU128\",\n /*#__PURE__*/ readU128(false)\n)\n/** @since 0.1.0 @category integers */\nexport const leU128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 16,\n \"leU128\",\n /*#__PURE__*/ readU128(true)\n)\n/** @since 0.1.0 @category integers */\nexport const beI128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 16,\n \"beI128\",\n /*#__PURE__*/ readI128(false)\n)\n/** @since 0.1.0 @category integers */\nexport const leI128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 16,\n \"leI128\",\n /*#__PURE__*/ readI128(true)\n)\n\n/** @since 0.1.0 @category floats */\nexport const beF32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 4,\n \"beF32\",\n /*#__PURE__*/ viewed((v, o) => v.getFloat32(o, false))\n)\n/** @since 0.1.0 @category floats */\nexport const leF32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 4,\n \"leF32\",\n /*#__PURE__*/ viewed((v, o) => v.getFloat32(o, true))\n)\n/** @since 0.1.0 @category floats */\nexport const beF64: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 8,\n \"beF64\",\n /*#__PURE__*/ viewed((v, o) => v.getFloat64(o, false))\n)\n/** @since 0.1.0 @category floats */\nexport const leF64: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(\n 8,\n \"leF64\",\n /*#__PURE__*/ viewed((v, o) => v.getFloat64(o, true))\n)\n\nconst byEndian =\n <A>(big: A, little: A) =>\n (endian: Endianness): A =>\n endian === \"big\" ? big : endian === \"little\" ? little : nativeLittle ? little : big\n\n/**\n * An unsigned 16-bit integer in the given byte order (winnow's `u16`).\n *\n * @since 0.1.0\n * @category integers\n */\nexport const u16: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beU16,\n leU16\n)\n/** @since 0.1.0 @category integers */\nexport const i16: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beI16,\n leI16\n)\n/** @since 0.1.0 @category integers */\nexport const u24: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beU24,\n leU24\n)\n/** @since 0.1.0 @category integers */\nexport const i24: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beI24,\n leI24\n)\n/** @since 0.1.0 @category integers */\nexport const u32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beU32,\n leU32\n)\n/** @since 0.1.0 @category integers */\nexport const i32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beI32,\n leI32\n)\n/** @since 0.1.0 @category integers */\nexport const u64: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beU64,\n leU64\n)\n/** @since 0.1.0 @category integers */\nexport const i64: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beI64,\n leI64\n)\n/** @since 0.1.0 @category integers */\nexport const u128: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beU128,\n leU128\n)\n/** @since 0.1.0 @category integers */\nexport const i128: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beI128,\n leI128\n)\n/** @since 0.1.0 @category floats */\nexport const f32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beF32,\n leF32\n)\n/** @since 0.1.0 @category floats */\nexport const f64: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(\n beF64,\n leF64\n)\n\nconst toCount = (n: number | bigint): number => (Predicate.isBigInt(n) ? Number(n) : n)\n\n/** How many counts {@link byCount} keeps the parsers of. */\nconst CountCache = 256\n\n/**\n * `build`, keeping the parsers it built for the first {@link CountCache}\n * counts seen: length-prefixed data repeats a few lengths, and building a\n * parser per value cost several times the parse.\n */\nconst byCount = <A>(build: (n: number) => A): ((n: number | bigint) => A) => {\n const built = new Map<number, A>()\n return (n) => {\n const count = toCount(n)\n let a = built.get(count)\n if (a === undefined) {\n a = build(count)\n if (built.size < CountCache) built.set(count, a)\n }\n return a\n }\n}\n\n/**\n * Parses a length with `count`, then takes that many tokens (winnow's\n * `length_take`, nom's `length_data`).\n *\n * @since 0.1.0\n * @category length-prefixed\n */\nexport const lengthTake = <E, R, I extends Input = Uint8Array>(\n count: Parser<number | bigint, E, R, I>\n): Parser<Slice<I>, E, R, I> => {\n const take = byCount((n) => Token.take<I>(n).step)\n // The count compiles with the grammar: the step is built from its (see `Parser.combinator`)\n return P.combinator(\n [count],\n ([countStep]) =>\n (state: State<I>) => {\n // SAFETY: the count parser's step, interpreted or compiled, returns its output (a number or bigint) or `Fail`\n const n = countStep(state) as number | bigint | Fail\n if (n === Fail) return Fail\n return take(n)(state)\n },\n \"lengthTake\"\n )\n}\n\n/**\n * Parses a length with `count`, then applies `parser` that many times\n * (winnow's `length_repeat`, nom's `length_count`).\n *\n * @since 0.1.0\n * @category length-prefixed\n */\nexport const lengthRepeat = <E, R, I extends Input, A, E2, R2, I2 extends Input>(\n count: Parser<number | bigint, E, R, I>,\n parser: Parser<A, E2, R2, I2>\n): Parser<Array<A>, E | E2, R | R2, I & I2> =>\n P.flatMap(\n count,\n byCount((n) => P.repeat(parser, n))\n )\n\n/**\n * Parses a length with `count`, takes that many tokens, and applies\n * `parser` to them (winnow's `length_and_then`, nom's `length_value`).\n * `parser` does not need to consume the whole slice.\n *\n * @since 0.1.0\n * @category length-prefixed\n */\nexport const lengthAndThen = <E, R, I extends Input, A, E2, R2>(\n count: Parser<number | bigint, E, R, I>,\n parser: Parser<A, E2, R2, Slice<I> & Input>\n): Parser<A, E | E2, R | R2, I> =>\n // SAFETY: a slice of an input is itself an input (a string, a `Uint8Array` or an array), so `Slice<I>` is an `Input`\n P.mapParser(lengthTake(count) as Parser<Slice<I> & Input, E, R, I>, P.complete(parser))\n"],"mappings":"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"}
|
package/dist/Bits.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Bits.d.ts","names":[],"sources":["../src/Bits.ts"],"mappings":";cA2Bc;;;;;;;;iBASG,iBAAiB;YACtB;;;;;;;;;qBAyDC,OAAQ,GAAG,GAAG,GAAG,MAAM,OAAO,GAAG,GAAG,GAAG,cAAY,OAAO,GAAG,GAAG,GAAG;;;;;;;;qBAYnE,QAAS,GAAG,GAAG,GAAG,MAAM,OAAO,GAAG,GAAG,GAAG,gBAAc,OAAO,GAAG,GAAG,GAAG;;;;;;;;
|
|
1
|
+
{"version":3,"file":"Bits.d.ts","names":[],"sources":["../src/Bits.ts"],"mappings":";cA2Bc;;;;;;;;iBASG,iBAAiB;YACtB;;;;;;;;;qBAyDC,OAAQ,GAAG,GAAG,GAAG,MAAM,OAAO,GAAG,GAAG,GAAG,cAAY,OAAO,GAAG,GAAG,GAAG;;;;;;;;qBAYnE,QAAS,GAAG,GAAG,GAAG,MAAM,OAAO,GAAG,GAAG,GAAG,gBAAc,OAAO,GAAG,GAAG,GAAG;;;;;;;;qBA+BtE,OAAQ,kBAAgB,6BAA6B;;;;;;;qBAgBrD,UAAW,kBAAgB,6BAA6B;;;;;;;;qBAuBxD,UAAW,iBAAiB,kBAAgB,6BAA6B;;;;;;;qBAqBzE,MAAM,8BAA8B"}
|
package/dist/Bits.js
CHANGED
|
@@ -60,10 +60,13 @@ const readBits = (state, count) => {
|
|
|
60
60
|
const input = state.input;
|
|
61
61
|
let pos = state.pos;
|
|
62
62
|
let value = 0;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
let left = count;
|
|
64
|
+
while (left > 0) {
|
|
65
|
+
const avail = 8 - (pos & 7);
|
|
66
|
+
const n = left < avail ? left : avail;
|
|
67
|
+
value = value * (1 << n) + (input[pos >>> 3] >>> avail - n & (1 << n) - 1);
|
|
68
|
+
pos += n;
|
|
69
|
+
left -= n;
|
|
67
70
|
}
|
|
68
71
|
state.pos = pos;
|
|
69
72
|
return value;
|
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\"\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 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 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 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
|
|