@thomasfosterau/effect-parse 0.1.0 → 0.2.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 +247 -230
- package/dist/Ascii.d.ts +32 -53
- package/dist/Ascii.d.ts.map +1 -1
- package/dist/Ascii.js +576 -571
- package/dist/Ascii.js.map +1 -1
- package/dist/Binary.d.ts +6 -29
- package/dist/Binary.d.ts.map +1 -1
- package/dist/Binary.js +129 -116
- package/dist/Binary.js.map +1 -1
- package/dist/Bits.d.ts +4 -2
- package/dist/Bits.d.ts.map +1 -1
- package/dist/Bits.js +121 -123
- package/dist/Bits.js.map +1 -1
- package/dist/Compiler.d.ts +39 -0
- package/dist/Compiler.d.ts.map +1 -0
- package/dist/Compiler.js +48 -0
- package/dist/Compiler.js.map +1 -0
- package/dist/Encoding.d.ts +29 -46
- package/dist/Encoding.d.ts.map +1 -1
- package/dist/Encoding.js +76 -75
- package/dist/Encoding.js.map +1 -1
- package/dist/Expression.d.ts +15 -49
- package/dist/Expression.d.ts.map +1 -1
- package/dist/Expression.js +143 -131
- package/dist/Expression.js.map +1 -1
- package/dist/Input.d.ts +206 -177
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +317 -299
- package/dist/Input.js.map +1 -1
- package/dist/Nom.d.ts +44 -84
- package/dist/Nom.d.ts.map +1 -1
- package/dist/Nom.js +423 -453
- package/dist/Nom.js.map +1 -1
- package/dist/ParseError.d.ts +54 -49
- package/dist/ParseError.d.ts.map +1 -1
- package/dist/ParseError.js +233 -275
- package/dist/ParseError.js.map +1 -1
- package/dist/Parser.d.ts +345 -313
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +2010 -1802
- package/dist/Parser.js.map +1 -1
- package/dist/ParserSchema.d.ts +8 -7
- package/dist/ParserSchema.d.ts.map +1 -1
- package/dist/ParserSchema.js +49 -49
- package/dist/ParserSchema.js.map +1 -1
- package/dist/ParserStream.d.ts +26 -20
- package/dist/ParserStream.d.ts.map +1 -1
- package/dist/ParserStream.js +267 -255
- package/dist/ParserStream.js.map +1 -1
- package/dist/Syntax.d.ts +401 -0
- package/dist/Syntax.d.ts.map +1 -0
- package/dist/Syntax.js +717 -0
- package/dist/Syntax.js.map +1 -0
- package/dist/Text.d.ts +98 -134
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +534 -496
- package/dist/Text.js.map +1 -1
- package/dist/Token.d.ts +60 -42
- package/dist/Token.d.ts.map +1 -1
- package/dist/Token.js +331 -265
- package/dist/Token.js.map +1 -1
- package/dist/index.d.ts +16 -17
- package/dist/index.js +16 -17
- package/dist/internal/compiler/closure.d.ts +14 -16
- package/dist/internal/compiler/closure.d.ts.map +1 -1
- package/dist/internal/compiler/closure.js +1458 -1637
- package/dist/internal/compiler/closure.js.map +1 -1
- package/dist/internal/compiler/entries.d.ts +11 -11
- package/dist/internal/compiler/entries.d.ts.map +1 -1
- package/dist/internal/compiler/entries.js +36 -26
- package/dist/internal/compiler/entries.js.map +1 -1
- package/dist/internal/compiler/first.d.ts +19 -19
- package/dist/internal/compiler/first.d.ts.map +1 -1
- package/dist/internal/compiler/first.js +251 -227
- package/dist/internal/compiler/first.js.map +1 -1
- package/dist/internal/compiler/jit.d.ts +6 -17
- package/dist/internal/compiler/jit.d.ts.map +1 -1
- package/dist/internal/compiler/jit.js +860 -988
- package/dist/internal/compiler/jit.js.map +1 -1
- package/dist/internal/compiler/registry.d.ts +20 -21
- package/dist/internal/compiler/registry.d.ts.map +1 -1
- package/dist/internal/compiler/registry.js +21 -41
- package/dist/internal/compiler/registry.js.map +1 -1
- package/dist/internal/compiler/sets.d.ts +9 -13
- package/dist/internal/compiler/sets.d.ts.map +1 -1
- package/dist/internal/compiler/sets.js +76 -73
- package/dist/internal/compiler/sets.js.map +1 -1
- package/dist/internal/entries.d.ts +3 -3
- package/dist/internal/entries.d.ts.map +1 -1
- package/dist/internal/entries.js +38 -30
- package/dist/internal/entries.js.map +1 -1
- package/dist/internal/node.d.ts +177 -173
- package/dist/internal/node.d.ts.map +1 -1
- package/dist/internal/node.js +77 -66
- package/dist/internal/node.js.map +1 -1
- package/dist/internal/numbers.d.ts +7 -8
- package/dist/internal/numbers.d.ts.map +1 -1
- package/dist/internal/numbers.js +246 -276
- package/dist/internal/numbers.js.map +1 -1
- package/dist/internal/resume.d.ts +6 -24
- package/dist/internal/resume.d.ts.map +1 -1
- package/dist/internal/resume.js +30 -29
- package/dist/internal/resume.js.map +1 -1
- package/dist/internal/run.d.ts +15 -0
- package/dist/internal/run.d.ts.map +1 -0
- package/dist/internal/run.js +36 -0
- package/dist/internal/run.js.map +1 -0
- package/dist/internal/stack.d.ts +16 -0
- package/dist/internal/stack.d.ts.map +1 -0
- package/dist/internal/stack.js +26 -0
- package/dist/internal/stack.js.map +1 -0
- package/dist/internal/syntax.d.ts +146 -0
- package/dist/internal/syntax.d.ts.map +1 -0
- package/dist/internal/syntax.js +305 -0
- package/dist/internal/syntax.js.map +1 -0
- package/dist/internal/text.d.ts +10 -2
- package/dist/internal/text.d.ts.map +1 -1
- package/dist/internal/text.js +295 -345
- package/dist/internal/text.js.map +1 -1
- package/dist/internal/tokens.d.ts +25 -30
- package/dist/internal/tokens.d.ts.map +1 -1
- package/dist/internal/tokens.js +369 -363
- package/dist/internal/tokens.js.map +1 -1
- package/package.json +42 -28
- package/src/Ascii.ts +278 -187
- package/src/Binary.ts +150 -44
- package/src/Bits.ts +6 -3
- package/src/Compiler.ts +98 -0
- package/src/Expression.ts +10 -5
- package/src/Input.ts +106 -28
- package/src/Nom.ts +4 -3
- package/src/ParseError.ts +48 -51
- package/src/Parser.ts +1163 -795
- package/src/ParserStream.ts +104 -80
- package/src/Syntax.ts +900 -0
- package/src/Text.ts +272 -187
- package/src/Token.ts +180 -87
- package/src/index.ts +2 -0
- package/src/internal/compiler/closure.ts +121 -88
- package/src/internal/compiler/entries.ts +21 -8
- package/src/internal/compiler/first.ts +17 -15
- package/src/internal/compiler/jit.ts +360 -157
- package/src/internal/compiler/registry.ts +12 -33
- package/src/internal/compiler/sets.ts +17 -11
- package/src/internal/entries.ts +4 -2
- package/src/internal/node.ts +51 -37
- package/src/internal/numbers.ts +22 -20
- package/src/internal/resume.ts +8 -4
- package/src/internal/run.ts +41 -0
- package/src/internal/stack.ts +36 -0
- package/src/internal/syntax.ts +421 -0
- package/src/internal/text.ts +32 -25
- package/src/internal/tokens.ts +96 -51
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/Bits.js
CHANGED
|
@@ -1,144 +1,142 @@
|
|
|
1
1
|
import { Fail, Failure } from "./Input.js";
|
|
2
2
|
import { make } from "./Parser.js";
|
|
3
|
+
//#region src/Bits.ts
|
|
3
4
|
const scale = (f, factor) => new Failure(factor < 1 ? Math.floor(f.offset * factor) : f.offset * factor, f.kind, f.expected, f.context, f.hasCause, f.cause, f.message, factor < 1 ? Math.ceil(f.needed * factor) : f.needed * factor);
|
|
4
5
|
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
* Runs `step` with offsets measured in different units (bits vs bytes),
|
|
7
|
+
* converting failure offsets back to the outer units afterwards.
|
|
8
|
+
*/
|
|
8
9
|
const inUnits = (state, factor, step) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return a;
|
|
10
|
+
const end = state.end;
|
|
11
|
+
const deepest = state.deepest;
|
|
12
|
+
state.deepest = void 0;
|
|
13
|
+
state.pos = factor > 1 ? state.pos * factor : Math.ceil(state.pos * factor);
|
|
14
|
+
state.end = end * factor;
|
|
15
|
+
const a = step(state);
|
|
16
|
+
state.end = end;
|
|
17
|
+
const inner = state.deepest;
|
|
18
|
+
state.deepest = deepest;
|
|
19
|
+
if (a === Fail) {
|
|
20
|
+
state.pos = factor > 1 ? Math.floor(state.pos / factor) : state.pos / factor;
|
|
21
|
+
const f = state.failure;
|
|
22
|
+
state.failure = scale(f, 1 / factor);
|
|
23
|
+
if (state.mode === "Cut") state.deepest = void 0;
|
|
24
|
+
if (inner !== void 0) {
|
|
25
|
+
const d = inner === f ? state.failure : scale(inner, 1 / factor);
|
|
26
|
+
if (state.deepest === void 0 || d.offset >= state.deepest.offset) state.deepest = d;
|
|
27
|
+
}
|
|
28
|
+
return Fail;
|
|
29
|
+
}
|
|
30
|
+
state.pos = factor > 1 ? Math.ceil(state.pos / factor) : state.pos / factor;
|
|
31
|
+
if (inner !== void 0) {
|
|
32
|
+
const d = scale(inner, 1 / factor);
|
|
33
|
+
if (deepest === void 0 || d.offset >= deepest.offset) state.deepest = d;
|
|
34
|
+
}
|
|
35
|
+
return a;
|
|
36
36
|
};
|
|
37
37
|
/**
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
* Runs a bit-level parser on byte input (winnow's and nom's `bits`). After
|
|
39
|
+
* success, the input advances to the next byte boundary.
|
|
40
|
+
*
|
|
41
|
+
* @since 0.1.0
|
|
42
|
+
* @category combinators
|
|
43
|
+
*/
|
|
44
|
+
const bits = (self) => {
|
|
45
|
+
const step = self.step;
|
|
46
|
+
return make((state) => inUnits(state, 8, step), "bits");
|
|
47
47
|
};
|
|
48
48
|
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
* Runs a byte-level parser from within a bit-level parser (winnow's and
|
|
50
|
+
* nom's `bytes`). The partly consumed byte, if any, is skipped first.
|
|
51
|
+
*
|
|
52
|
+
* @since 0.1.0
|
|
53
|
+
* @category combinators
|
|
54
|
+
*/
|
|
55
|
+
const bytes = (self) => {
|
|
56
|
+
const step = self.step;
|
|
57
|
+
return make((state) => inUnits(state, 1 / 8, step), "bytes");
|
|
58
58
|
};
|
|
59
59
|
const readBits = (state, count) => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
const input = state.input;
|
|
61
|
+
let pos = state.pos;
|
|
62
|
+
let value = 0;
|
|
63
|
+
for (let i = 0; i < count; i++) {
|
|
64
|
+
const byte = input[pos >>> 3];
|
|
65
|
+
value = value * 2 + (byte >>> 7 - (pos & 7) & 1);
|
|
66
|
+
pos++;
|
|
67
|
+
}
|
|
68
|
+
state.pos = pos;
|
|
69
|
+
return value;
|
|
70
70
|
};
|
|
71
71
|
/**
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return readBits(state, count);
|
|
87
|
-
}, "take");
|
|
72
|
+
* Takes `count` bits (at most 53) as an unsigned number (winnow's and nom's
|
|
73
|
+
* bit-level `take`).
|
|
74
|
+
*
|
|
75
|
+
* @since 0.1.0
|
|
76
|
+
* @category parsers
|
|
77
|
+
*/
|
|
78
|
+
const take = (count) => {
|
|
79
|
+
if (count > 53) throw new RangeError("Bits.take: use Bits.takeBig for more than 53 bits");
|
|
80
|
+
const expected = [`${count} bits`];
|
|
81
|
+
return make((state) => {
|
|
82
|
+
const avail = state.end - state.pos;
|
|
83
|
+
if (avail < count) return state.eoi("Bits", expected, count - avail);
|
|
84
|
+
return readBits(state, count);
|
|
85
|
+
}, "take");
|
|
88
86
|
};
|
|
89
87
|
/**
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}, "takeBig");
|
|
88
|
+
* Takes `count` bits as an unsigned `bigint`.
|
|
89
|
+
*
|
|
90
|
+
* @since 0.1.0
|
|
91
|
+
* @category parsers
|
|
92
|
+
*/
|
|
93
|
+
const takeBig = (count) => {
|
|
94
|
+
const expected = [`${count} bits`];
|
|
95
|
+
return make((state) => {
|
|
96
|
+
const avail = state.end - state.pos;
|
|
97
|
+
if (avail < count) return state.eoi("Bits", expected, count - avail);
|
|
98
|
+
let value = 0n;
|
|
99
|
+
let remaining = count;
|
|
100
|
+
while (remaining > 0) {
|
|
101
|
+
const n = Math.min(remaining, 32);
|
|
102
|
+
value = value << BigInt(n) | BigInt(readBits(state, n));
|
|
103
|
+
remaining -= n;
|
|
104
|
+
}
|
|
105
|
+
return value;
|
|
106
|
+
}, "takeBig");
|
|
110
107
|
};
|
|
111
108
|
/**
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}, "pattern");
|
|
109
|
+
* Matches `count` bits equal to `pattern` (winnow's `pattern`, nom's bit
|
|
110
|
+
* `tag`).
|
|
111
|
+
*
|
|
112
|
+
* @since 0.1.0
|
|
113
|
+
* @category parsers
|
|
114
|
+
*/
|
|
115
|
+
const pattern = (pattern, count) => {
|
|
116
|
+
const expected = [`bit pattern ${pattern.toString(2).padStart(count, "0")}`];
|
|
117
|
+
return make((state) => {
|
|
118
|
+
const start = state.pos;
|
|
119
|
+
const avail = state.end - start;
|
|
120
|
+
if (avail < count) return state.eoi("Bits", expected, count - avail);
|
|
121
|
+
const value = readBits(state, count);
|
|
122
|
+
if (value !== pattern) {
|
|
123
|
+
state.pos = start;
|
|
124
|
+
return state.backtrack("Bits", expected);
|
|
125
|
+
}
|
|
126
|
+
return value;
|
|
127
|
+
}, "pattern");
|
|
132
128
|
};
|
|
133
129
|
/**
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return readBits(state, 1) === 1;
|
|
130
|
+
* Takes one bit as a boolean (winnow's and nom's `bool`).
|
|
131
|
+
*
|
|
132
|
+
* @since 0.1.0
|
|
133
|
+
* @category parsers
|
|
134
|
+
*/
|
|
135
|
+
const bool = /*#__PURE__*/ make((state) => {
|
|
136
|
+
if (state.pos >= state.end) return state.eoi("Bits", ["1 bit"], 1);
|
|
137
|
+
return readBits(state, 1) === 1;
|
|
143
138
|
}, "bool");
|
|
139
|
+
//#endregion
|
|
140
|
+
export { bits, bool, bytes, pattern, take, takeBig };
|
|
141
|
+
|
|
144
142
|
//# sourceMappingURL=Bits.js.map
|
package/dist/Bits.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Bits.js","
|
|
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 as unknown as (state: State<any>) => A | Fail\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 as (state: State<any>) => A | Fail\n return make((state: State<any>) => inUnits(state, 1 / 8, step), \"bytes\")\n}\n\nconst readBits = (state: State<any>, count: number): number => {\n const input = state.input as Uint8Array\n let pos = state.pos\n let value = 0\n for (let i = 0; i < count; i++) {\n const byte = input[pos >>> 3]\n value = value * 2 + ((byte >>> (7 - (pos & 7))) & 1)\n pos++\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.pos = 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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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Input } from "./Input.js";
|
|
2
|
+
import { Parser } from "./Parser.js";
|
|
3
|
+
//#region src/Compiler.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Compiles a parser with the JIT: generated code where `new Function` is
|
|
6
|
+
* allowed, otherwise specialized closures (see {@link closure}). Returns the
|
|
7
|
+
* same parser.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { Ascii, Compiler, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
12
|
+
*
|
|
13
|
+
* const list = Compiler.jit(Parser.separated(Ascii.decInt, Token.literal(",")))
|
|
14
|
+
* Parser.parse(list, "1,2,3") // Result.succeed([1, 2, 3])
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @since 0.2.0
|
|
18
|
+
* @category compilation
|
|
19
|
+
*/
|
|
20
|
+
export declare const jit: <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>;
|
|
21
|
+
/**
|
|
22
|
+
* Compiles a parser into specialized closures. Returns the same parser.
|
|
23
|
+
* Nothing is generated, so it works under a Content Security Policy, and a
|
|
24
|
+
* bundle that compiles only with `closure` contains no `new Function`.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { Ascii, Compiler, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
29
|
+
*
|
|
30
|
+
* const list = Compiler.closure(Parser.separated(Ascii.decInt, Token.literal(",")))
|
|
31
|
+
* Parser.parse(list, "1,2,3") // Result.succeed([1, 2, 3])
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @since 0.2.0
|
|
35
|
+
* @category compilation
|
|
36
|
+
*/
|
|
37
|
+
export declare const closure: <A, E, R, I extends Input>(self: Parser<A, E, R, I>) => Parser<A, E, R, I>;
|
|
38
|
+
//#endregion
|
|
39
|
+
//# sourceMappingURL=Compiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Compiler.d.ts","names":[],"sources":["../src/Compiler.ts"],"mappings":";;;;;;;;;;;;;;;;;;;qBAyEa,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"}
|
package/dist/Compiler.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { backend } from "./internal/compiler/closure.js";
|
|
2
|
+
import { backend as backend$1 } from "./internal/compiler/jit.js";
|
|
3
|
+
import { register } from "./internal/compiler/registry.js";
|
|
4
|
+
//#region src/Compiler.ts
|
|
5
|
+
/**
|
|
6
|
+
* Compiles a parser with the JIT: generated code where `new Function` is
|
|
7
|
+
* allowed, otherwise specialized closures (see {@link closure}). Returns the
|
|
8
|
+
* same parser.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { Ascii, Compiler, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
13
|
+
*
|
|
14
|
+
* const list = Compiler.jit(Parser.separated(Ascii.decInt, Token.literal(",")))
|
|
15
|
+
* Parser.parse(list, "1,2,3") // Result.succeed([1, 2, 3])
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @since 0.2.0
|
|
19
|
+
* @category compilation
|
|
20
|
+
*/
|
|
21
|
+
const jit = (self) => {
|
|
22
|
+
register(self, backend$1);
|
|
23
|
+
return self;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Compiles a parser into specialized closures. Returns the same parser.
|
|
27
|
+
* Nothing is generated, so it works under a Content Security Policy, and a
|
|
28
|
+
* bundle that compiles only with `closure` contains no `new Function`.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { Ascii, Compiler, Parser, Token } from "@thomasfosterau/effect-parse"
|
|
33
|
+
*
|
|
34
|
+
* const list = Compiler.closure(Parser.separated(Ascii.decInt, Token.literal(",")))
|
|
35
|
+
* Parser.parse(list, "1,2,3") // Result.succeed([1, 2, 3])
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @since 0.2.0
|
|
39
|
+
* @category compilation
|
|
40
|
+
*/
|
|
41
|
+
const closure = (self) => {
|
|
42
|
+
register(self, backend);
|
|
43
|
+
return self;
|
|
44
|
+
};
|
|
45
|
+
//#endregion
|
|
46
|
+
export { closure, jit };
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=Compiler.js.map
|
|
@@ -0,0 +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 two compilers, one function each, so a program bundles only the\n * one it uses, and a program that compiles nothing bundles neither:\n *\n * - {@link jit} generates code with `new Function` where it is allowed, and\n * otherwise uses the closure compiler. It is the fastest.\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.\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` and `ParserStream.parseAll` run a build that\n * handles partial input. `ParserStream.parseMany`, `Parser.parseRecoverable`\n * 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.\n *\n * @since 0.2.0\n */\nimport type { Input } from \"./Input.js\"\nimport type { Parser } 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\"\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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAyEA,MAAa,OAAiC,SAAiD;CAC7F,SAAS,MAAMA,SAAU;CACzB,OAAO;AACT;;;;;;;;;;;;;;;;;AAkBA,MAAa,WAAqC,SAAiD;CACjG,SAAS,MAAMC,OAAc;CAC7B,OAAO;AACT"}
|
package/dist/Encoding.d.ts
CHANGED
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Text encodings for the `Text` module.
|
|
3
|
-
*
|
|
4
|
-
* An {@link Encoding} tells the `Text` parsers how to read Unicode code
|
|
5
|
-
* points out of an input. JavaScript strings are read natively, without any
|
|
6
|
-
* conversion. Byte inputs are decoded as they are parsed, so offsets stay
|
|
7
|
-
* byte offsets, slices that are kept as bytes (`Parser.taken`) are
|
|
8
|
-
* zero-copy views, and partial input that ends in the middle of a character
|
|
9
|
-
* reports `Incomplete`.
|
|
10
|
-
*
|
|
11
|
-
* ```ts
|
|
12
|
-
* import { Encoding, Text } from "@thomasfosterau/effect-parse"
|
|
13
|
-
*
|
|
14
|
-
* Text.utf8.encoding === Encoding.utf8
|
|
15
|
-
* Text.make(Encoding.latin1) // the Text parsers for any Encoding, including your own
|
|
16
|
-
* ```
|
|
17
|
-
*
|
|
18
|
-
* @since 0.1.0
|
|
19
|
-
*/
|
|
20
1
|
import * as Option from "effect/Option";
|
|
2
|
+
//#region src/Encoding.d.ts
|
|
21
3
|
/**
|
|
22
4
|
* A text encoding: how to read Unicode code points out of an input. The
|
|
23
5
|
* `Text` module is generic over encodings, so one grammar can parse
|
|
@@ -30,33 +12,33 @@ import * as Option from "effect/Option";
|
|
|
30
12
|
* @category models
|
|
31
13
|
*/
|
|
32
14
|
export interface Encoding<I extends string | Uint8Array = string | Uint8Array> {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
15
|
+
/** The name of the encoding, e.g. `"UTF-8"`. Used in error messages. */
|
|
16
|
+
readonly name: string;
|
|
17
|
+
/**
|
|
18
|
+
* The size of a code unit, in input units: 1 for strings, UTF-8 and
|
|
19
|
+
* Latin-1, 2 for UTF-16 bytes. Code points start at multiples of it.
|
|
20
|
+
*/
|
|
21
|
+
readonly unit: number;
|
|
22
|
+
/**
|
|
23
|
+
* Whether every input unit below `0x80` encodes the ASCII character with
|
|
24
|
+
* that value, and is never part of a longer sequence. Enables fast paths.
|
|
25
|
+
*/
|
|
26
|
+
readonly asciiCompatible: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Decodes the code point starting at `offset` (with `offset < end`).
|
|
29
|
+
* Returns the code point, `-1` if the input is malformed there, or `-2` if
|
|
30
|
+
* the input ends inside a sequence (more input could complete it).
|
|
31
|
+
*/
|
|
32
|
+
readonly decode: (input: I, offset: number, end: number) => number;
|
|
33
|
+
/** The number of input units that encode a code point. */
|
|
34
|
+
readonly width: (codePoint: number) => number;
|
|
35
|
+
/** Encodes a string. Throws if the string can't be represented. */
|
|
36
|
+
readonly encode: (text: string) => I;
|
|
37
|
+
/**
|
|
38
|
+
* Decodes the units `[start, end)` to a string. The parsers only call it
|
|
39
|
+
* on ranges they have checked are well formed.
|
|
40
|
+
*/
|
|
41
|
+
readonly text: (input: I, start: number, end: number) => string;
|
|
60
42
|
}
|
|
61
43
|
/**
|
|
62
44
|
* JavaScript strings, read as UTF-16 code units. Offsets are code-unit
|
|
@@ -113,4 +95,5 @@ export declare const latin1: Encoding<Uint8Array>;
|
|
|
113
95
|
* @category utils
|
|
114
96
|
*/
|
|
115
97
|
export declare const sniff: (bytes: Uint8Array) => Option.Option<Encoding<Uint8Array>>;
|
|
98
|
+
//#endregion
|
|
116
99
|
//# sourceMappingURL=Encoding.d.ts.map
|
package/dist/Encoding.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Encoding.d.ts","
|
|
1
|
+
{"version":3,"file":"Encoding.d.ts","names":[],"sources":["../src/Encoding.ts"],"mappings":";;;;;;;;;;;;;iBAiCiB,SAAS,mBAAmB,sBAAsB;;WAExD;;;;;WAKA;;;;;WAKA;;;;;;WAMA,SAAS,OAAO,GAAG,gBAAgB;;WAEnC,QAAQ;;WAER,SAAS,iBAAiB;;;;;WAK1B,OAAO,OAAO,GAAG,eAAe;;;;;;;;;;qBAW9B,QAAQ;;;;;;;;qBASR,MAAM,SAAS;;;;;;;qBAQf,SAAS,SAAS;;;;;;;qBAQlB,SAAS,SAAS;;;;;;;;qBASlB,QAAQ,SAAS;;;;;;;;;;;;;;;;qBAiBjB,QAAS,OAAO,eAAa,OAAO,OAAO,SAAS"}
|