@thomasfosterau/effect-parse 0.1.0 → 0.3.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.
Files changed (161) hide show
  1. package/README.md +291 -231
  2. package/dist/Ascii.d.ts +32 -53
  3. package/dist/Ascii.d.ts.map +1 -1
  4. package/dist/Ascii.js +576 -571
  5. package/dist/Ascii.js.map +1 -1
  6. package/dist/Binary.d.ts +6 -29
  7. package/dist/Binary.d.ts.map +1 -1
  8. package/dist/Binary.js +129 -116
  9. package/dist/Binary.js.map +1 -1
  10. package/dist/Bits.d.ts +4 -2
  11. package/dist/Bits.d.ts.map +1 -1
  12. package/dist/Bits.js +121 -123
  13. package/dist/Bits.js.map +1 -1
  14. package/dist/Compiler.d.ts +39 -0
  15. package/dist/Compiler.d.ts.map +1 -0
  16. package/dist/Compiler.js +48 -0
  17. package/dist/Compiler.js.map +1 -0
  18. package/dist/Encoding.d.ts +29 -46
  19. package/dist/Encoding.d.ts.map +1 -1
  20. package/dist/Encoding.js +76 -75
  21. package/dist/Encoding.js.map +1 -1
  22. package/dist/Expression.d.ts +15 -49
  23. package/dist/Expression.d.ts.map +1 -1
  24. package/dist/Expression.js +151 -132
  25. package/dist/Expression.js.map +1 -1
  26. package/dist/Input.d.ts +251 -177
  27. package/dist/Input.d.ts.map +1 -1
  28. package/dist/Input.js +409 -299
  29. package/dist/Input.js.map +1 -1
  30. package/dist/Nom.d.ts +45 -85
  31. package/dist/Nom.d.ts.map +1 -1
  32. package/dist/Nom.js +423 -453
  33. package/dist/Nom.js.map +1 -1
  34. package/dist/ParseError.d.ts +54 -49
  35. package/dist/ParseError.d.ts.map +1 -1
  36. package/dist/ParseError.js +232 -275
  37. package/dist/ParseError.js.map +1 -1
  38. package/dist/Parser.d.ts +345 -313
  39. package/dist/Parser.d.ts.map +1 -1
  40. package/dist/Parser.js +2034 -1802
  41. package/dist/Parser.js.map +1 -1
  42. package/dist/ParserSchema.d.ts +206 -7
  43. package/dist/ParserSchema.d.ts.map +1 -1
  44. package/dist/ParserSchema.js +678 -49
  45. package/dist/ParserSchema.js.map +1 -1
  46. package/dist/ParserStream.d.ts +26 -20
  47. package/dist/ParserStream.d.ts.map +1 -1
  48. package/dist/ParserStream.js +267 -255
  49. package/dist/ParserStream.js.map +1 -1
  50. package/dist/Syntax.d.ts +401 -0
  51. package/dist/Syntax.d.ts.map +1 -0
  52. package/dist/Syntax.js +717 -0
  53. package/dist/Syntax.js.map +1 -0
  54. package/dist/Text.d.ts +98 -134
  55. package/dist/Text.d.ts.map +1 -1
  56. package/dist/Text.js +534 -496
  57. package/dist/Text.js.map +1 -1
  58. package/dist/Token.d.ts +60 -42
  59. package/dist/Token.d.ts.map +1 -1
  60. package/dist/Token.js +331 -265
  61. package/dist/Token.js.map +1 -1
  62. package/dist/index.d.ts +16 -17
  63. package/dist/index.js +16 -17
  64. package/dist/internal/compiler/closure.d.ts +14 -16
  65. package/dist/internal/compiler/closure.d.ts.map +1 -1
  66. package/dist/internal/compiler/closure.js +1458 -1637
  67. package/dist/internal/compiler/closure.js.map +1 -1
  68. package/dist/internal/compiler/entries.d.ts +11 -11
  69. package/dist/internal/compiler/entries.d.ts.map +1 -1
  70. package/dist/internal/compiler/entries.js +36 -26
  71. package/dist/internal/compiler/entries.js.map +1 -1
  72. package/dist/internal/compiler/first.d.ts +19 -19
  73. package/dist/internal/compiler/first.d.ts.map +1 -1
  74. package/dist/internal/compiler/first.js +251 -227
  75. package/dist/internal/compiler/first.js.map +1 -1
  76. package/dist/internal/compiler/jit.d.ts +6 -17
  77. package/dist/internal/compiler/jit.d.ts.map +1 -1
  78. package/dist/internal/compiler/jit.js +860 -988
  79. package/dist/internal/compiler/jit.js.map +1 -1
  80. package/dist/internal/compiler/registry.d.ts +20 -21
  81. package/dist/internal/compiler/registry.d.ts.map +1 -1
  82. package/dist/internal/compiler/registry.js +21 -41
  83. package/dist/internal/compiler/registry.js.map +1 -1
  84. package/dist/internal/compiler/sets.d.ts +9 -13
  85. package/dist/internal/compiler/sets.d.ts.map +1 -1
  86. package/dist/internal/compiler/sets.js +76 -73
  87. package/dist/internal/compiler/sets.js.map +1 -1
  88. package/dist/internal/entries.d.ts +3 -3
  89. package/dist/internal/entries.d.ts.map +1 -1
  90. package/dist/internal/entries.js +38 -30
  91. package/dist/internal/entries.js.map +1 -1
  92. package/dist/internal/node.d.ts +177 -173
  93. package/dist/internal/node.d.ts.map +1 -1
  94. package/dist/internal/node.js +77 -66
  95. package/dist/internal/node.js.map +1 -1
  96. package/dist/internal/numbers.d.ts +7 -8
  97. package/dist/internal/numbers.d.ts.map +1 -1
  98. package/dist/internal/numbers.js +246 -276
  99. package/dist/internal/numbers.js.map +1 -1
  100. package/dist/internal/resume.d.ts +6 -24
  101. package/dist/internal/resume.d.ts.map +1 -1
  102. package/dist/internal/resume.js +30 -29
  103. package/dist/internal/resume.js.map +1 -1
  104. package/dist/internal/run.d.ts +15 -0
  105. package/dist/internal/run.d.ts.map +1 -0
  106. package/dist/internal/run.js +36 -0
  107. package/dist/internal/run.js.map +1 -0
  108. package/dist/internal/stack.d.ts +16 -0
  109. package/dist/internal/stack.d.ts.map +1 -0
  110. package/dist/internal/stack.js +36 -0
  111. package/dist/internal/stack.js.map +1 -0
  112. package/dist/internal/syntax.d.ts +147 -0
  113. package/dist/internal/syntax.d.ts.map +1 -0
  114. package/dist/internal/syntax.js +309 -0
  115. package/dist/internal/syntax.js.map +1 -0
  116. package/dist/internal/text.d.ts +10 -2
  117. package/dist/internal/text.d.ts.map +1 -1
  118. package/dist/internal/text.js +295 -345
  119. package/dist/internal/text.js.map +1 -1
  120. package/dist/internal/ties.d.ts +30 -0
  121. package/dist/internal/ties.d.ts.map +1 -0
  122. package/dist/internal/ties.js +67 -0
  123. package/dist/internal/ties.js.map +1 -0
  124. package/dist/internal/tokens.d.ts +25 -30
  125. package/dist/internal/tokens.d.ts.map +1 -1
  126. package/dist/internal/tokens.js +369 -363
  127. package/dist/internal/tokens.js.map +1 -1
  128. package/package.json +42 -28
  129. package/src/Ascii.ts +278 -187
  130. package/src/Binary.ts +150 -44
  131. package/src/Bits.ts +6 -3
  132. package/src/Compiler.ts +98 -0
  133. package/src/Expression.ts +24 -16
  134. package/src/Input.ts +210 -35
  135. package/src/Nom.ts +4 -3
  136. package/src/ParseError.ts +49 -52
  137. package/src/Parser.ts +1199 -799
  138. package/src/ParserSchema.ts +982 -23
  139. package/src/ParserStream.ts +104 -80
  140. package/src/Syntax.ts +900 -0
  141. package/src/Text.ts +272 -187
  142. package/src/Token.ts +180 -87
  143. package/src/index.ts +2 -0
  144. package/src/internal/compiler/closure.ts +121 -88
  145. package/src/internal/compiler/entries.ts +21 -8
  146. package/src/internal/compiler/first.ts +17 -15
  147. package/src/internal/compiler/jit.ts +360 -157
  148. package/src/internal/compiler/registry.ts +12 -33
  149. package/src/internal/compiler/sets.ts +17 -11
  150. package/src/internal/entries.ts +4 -2
  151. package/src/internal/node.ts +51 -37
  152. package/src/internal/numbers.ts +22 -20
  153. package/src/internal/resume.ts +8 -4
  154. package/src/internal/run.ts +41 -0
  155. package/src/internal/stack.ts +41 -0
  156. package/src/internal/syntax.ts +426 -0
  157. package/src/internal/text.ts +32 -25
  158. package/src/internal/ties.ts +83 -0
  159. package/src/internal/tokens.ts +96 -51
  160. package/dist/index.d.ts.map +0 -1
  161. package/dist/index.js.map +0 -1
package/src/Binary.ts CHANGED
@@ -17,6 +17,7 @@
17
17
  *
18
18
  * @since 0.1.0
19
19
  */
20
+ import * as Predicate from "effect/Predicate"
20
21
  import type { Input, Slice, State } from "./Input.js"
21
22
  import { Fail } from "./Input.js"
22
23
  import type { Parser } from "./Parser.js"
@@ -41,9 +42,13 @@ export {
41
42
  */
42
43
  export type Endianness = "big" | "little" | "native"
43
44
 
44
- const nativeLittle = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1
45
+ const nativeLittle = /*#__PURE__*/ new Uint8Array(/*#__PURE__*/ new Uint16Array([1]).buffer)[0] === 1
45
46
 
46
- const fixed = <A>(size: number, name: string, read: (view: DataView, offset: number) => A): Parser<A, never, never, Uint8Array> => {
47
+ const fixed = <A>(
48
+ size: number,
49
+ name: string,
50
+ read: (view: DataView, offset: number) => A
51
+ ): Parser<A, never, never, Uint8Array> => {
47
52
  const expected = [`${size} byte${size === 1 ? "" : "s"}`]
48
53
  return P.make((state: State<Uint8Array>) => {
49
54
  const pos = state.pos
@@ -86,7 +91,7 @@ const readI128 = (little: boolean) => {
86
91
  * @since 0.1.0
87
92
  * @category integers
88
93
  */
89
- export const u8: Parser<number, never, never, Uint8Array> = fixed(1, "u8", (v, o) => v.getUint8(o))
94
+ export const u8: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(1, "u8", (v, o) => v.getUint8(o))
90
95
 
91
96
  /**
92
97
  * A signed byte.
@@ -94,60 +99,126 @@ export const u8: Parser<number, never, never, Uint8Array> = fixed(1, "u8", (v, o
94
99
  * @since 0.1.0
95
100
  * @category integers
96
101
  */
97
- export const i8: Parser<number, never, never, Uint8Array> = fixed(1, "i8", (v, o) => v.getInt8(o))
102
+ export const i8: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(1, "i8", (v, o) => v.getInt8(o))
98
103
 
99
104
  /** @since 0.1.0 @category integers */
100
- export const beU16: Parser<number, never, never, Uint8Array> = fixed(2, "beU16", (v, o) => v.getUint16(o, false))
105
+ export const beU16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(2, "beU16", (v, o) =>
106
+ v.getUint16(o, false)
107
+ )
101
108
  /** @since 0.1.0 @category integers */
102
- export const leU16: Parser<number, never, never, Uint8Array> = fixed(2, "leU16", (v, o) => v.getUint16(o, true))
109
+ export const leU16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(2, "leU16", (v, o) =>
110
+ v.getUint16(o, true)
111
+ )
103
112
  /** @since 0.1.0 @category integers */
104
- export const beI16: Parser<number, never, never, Uint8Array> = fixed(2, "beI16", (v, o) => v.getInt16(o, false))
113
+ export const beI16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(2, "beI16", (v, o) =>
114
+ v.getInt16(o, false)
115
+ )
105
116
  /** @since 0.1.0 @category integers */
106
- export const leI16: Parser<number, never, never, Uint8Array> = fixed(2, "leI16", (v, o) => v.getInt16(o, true))
117
+ export const leI16: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(2, "leI16", (v, o) =>
118
+ v.getInt16(o, true)
119
+ )
107
120
  /** @since 0.1.0 @category integers */
108
- export const beU24: Parser<number, never, never, Uint8Array> = fixed(3, "beU24", readU24(false))
121
+ export const beU24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(
122
+ 3,
123
+ "beU24",
124
+ /*#__PURE__*/ readU24(false)
125
+ )
109
126
  /** @since 0.1.0 @category integers */
110
- export const leU24: Parser<number, never, never, Uint8Array> = fixed(3, "leU24", readU24(true))
127
+ export const leU24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(
128
+ 3,
129
+ "leU24",
130
+ /*#__PURE__*/ readU24(true)
131
+ )
111
132
  /** @since 0.1.0 @category integers */
112
- export const beI24: Parser<number, never, never, Uint8Array> = fixed(3, "beI24", readI24(false))
133
+ export const beI24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(
134
+ 3,
135
+ "beI24",
136
+ /*#__PURE__*/ readI24(false)
137
+ )
113
138
  /** @since 0.1.0 @category integers */
114
- export const leI24: Parser<number, never, never, Uint8Array> = fixed(3, "leI24", readI24(true))
139
+ export const leI24: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(
140
+ 3,
141
+ "leI24",
142
+ /*#__PURE__*/ readI24(true)
143
+ )
115
144
  /** @since 0.1.0 @category integers */
116
- export const beU32: Parser<number, never, never, Uint8Array> = fixed(4, "beU32", (v, o) => v.getUint32(o, false))
145
+ export const beU32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, "beU32", (v, o) =>
146
+ v.getUint32(o, false)
147
+ )
117
148
  /** @since 0.1.0 @category integers */
118
- export const leU32: Parser<number, never, never, Uint8Array> = fixed(4, "leU32", (v, o) => v.getUint32(o, true))
149
+ export const leU32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, "leU32", (v, o) =>
150
+ v.getUint32(o, true)
151
+ )
119
152
  /** @since 0.1.0 @category integers */
120
- export const beI32: Parser<number, never, never, Uint8Array> = fixed(4, "beI32", (v, o) => v.getInt32(o, false))
153
+ export const beI32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, "beI32", (v, o) =>
154
+ v.getInt32(o, false)
155
+ )
121
156
  /** @since 0.1.0 @category integers */
122
- export const leI32: Parser<number, never, never, Uint8Array> = fixed(4, "leI32", (v, o) => v.getInt32(o, true))
157
+ export const leI32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, "leI32", (v, o) =>
158
+ v.getInt32(o, true)
159
+ )
123
160
  /** @since 0.1.0 @category integers */
124
- export const beU64: Parser<bigint, never, never, Uint8Array> = fixed(8, "beU64", (v, o) => v.getBigUint64(o, false))
161
+ export const beU64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, "beU64", (v, o) =>
162
+ v.getBigUint64(o, false)
163
+ )
125
164
  /** @since 0.1.0 @category integers */
126
- export const leU64: Parser<bigint, never, never, Uint8Array> = fixed(8, "leU64", (v, o) => v.getBigUint64(o, true))
165
+ export const leU64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, "leU64", (v, o) =>
166
+ v.getBigUint64(o, true)
167
+ )
127
168
  /** @since 0.1.0 @category integers */
128
- export const beI64: Parser<bigint, never, never, Uint8Array> = fixed(8, "beI64", (v, o) => v.getBigInt64(o, false))
169
+ export const beI64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, "beI64", (v, o) =>
170
+ v.getBigInt64(o, false)
171
+ )
129
172
  /** @since 0.1.0 @category integers */
130
- export const leI64: Parser<bigint, never, never, Uint8Array> = fixed(8, "leI64", (v, o) => v.getBigInt64(o, true))
173
+ export const leI64: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, "leI64", (v, o) =>
174
+ v.getBigInt64(o, true)
175
+ )
131
176
  /** @since 0.1.0 @category integers */
132
- export const beU128: Parser<bigint, never, never, Uint8Array> = fixed(16, "beU128", readU128(false))
177
+ export const beU128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(
178
+ 16,
179
+ "beU128",
180
+ /*#__PURE__*/ readU128(false)
181
+ )
133
182
  /** @since 0.1.0 @category integers */
134
- export const leU128: Parser<bigint, never, never, Uint8Array> = fixed(16, "leU128", readU128(true))
183
+ export const leU128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(
184
+ 16,
185
+ "leU128",
186
+ /*#__PURE__*/ readU128(true)
187
+ )
135
188
  /** @since 0.1.0 @category integers */
136
- export const beI128: Parser<bigint, never, never, Uint8Array> = fixed(16, "beI128", readI128(false))
189
+ export const beI128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(
190
+ 16,
191
+ "beI128",
192
+ /*#__PURE__*/ readI128(false)
193
+ )
137
194
  /** @since 0.1.0 @category integers */
138
- export const leI128: Parser<bigint, never, never, Uint8Array> = fixed(16, "leI128", readI128(true))
195
+ export const leI128: Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ fixed(
196
+ 16,
197
+ "leI128",
198
+ /*#__PURE__*/ readI128(true)
199
+ )
139
200
 
140
201
  /** @since 0.1.0 @category floats */
141
- export const beF32: Parser<number, never, never, Uint8Array> = fixed(4, "beF32", (v, o) => v.getFloat32(o, false))
202
+ export const beF32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, "beF32", (v, o) =>
203
+ v.getFloat32(o, false)
204
+ )
142
205
  /** @since 0.1.0 @category floats */
143
- export const leF32: Parser<number, never, never, Uint8Array> = fixed(4, "leF32", (v, o) => v.getFloat32(o, true))
206
+ export const leF32: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(4, "leF32", (v, o) =>
207
+ v.getFloat32(o, true)
208
+ )
144
209
  /** @since 0.1.0 @category floats */
145
- export const beF64: Parser<number, never, never, Uint8Array> = fixed(8, "beF64", (v, o) => v.getFloat64(o, false))
210
+ export const beF64: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, "beF64", (v, o) =>
211
+ v.getFloat64(o, false)
212
+ )
146
213
  /** @since 0.1.0 @category floats */
147
- export const leF64: Parser<number, never, never, Uint8Array> = fixed(8, "leF64", (v, o) => v.getFloat64(o, true))
214
+ export const leF64: Parser<number, never, never, Uint8Array> = /*#__PURE__*/ fixed(8, "leF64", (v, o) =>
215
+ v.getFloat64(o, true)
216
+ )
148
217
 
149
- const byEndian = <A>(big: A, little: A) => (endian: Endianness): A =>
150
- endian === "big" ? big : endian === "little" ? little : nativeLittle ? little : big
218
+ const byEndian =
219
+ <A>(big: A, little: A) =>
220
+ (endian: Endianness): A =>
221
+ endian === "big" ? big : endian === "little" ? little : nativeLittle ? little : big
151
222
 
152
223
  /**
153
224
  * An unsigned 16-bit integer in the given byte order (winnow's `u16`).
@@ -155,32 +226,67 @@ const byEndian = <A>(big: A, little: A) => (endian: Endianness): A =>
155
226
  * @since 0.1.0
156
227
  * @category integers
157
228
  */
158
- export const u16: (endian: Endianness) => Parser<number, never, never, Uint8Array> = byEndian(beU16, leU16)
229
+ export const u16: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
230
+ beU16,
231
+ leU16
232
+ )
159
233
  /** @since 0.1.0 @category integers */
160
- export const i16: (endian: Endianness) => Parser<number, never, never, Uint8Array> = byEndian(beI16, leI16)
234
+ export const i16: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
235
+ beI16,
236
+ leI16
237
+ )
161
238
  /** @since 0.1.0 @category integers */
162
- export const u24: (endian: Endianness) => Parser<number, never, never, Uint8Array> = byEndian(beU24, leU24)
239
+ export const u24: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
240
+ beU24,
241
+ leU24
242
+ )
163
243
  /** @since 0.1.0 @category integers */
164
- export const i24: (endian: Endianness) => Parser<number, never, never, Uint8Array> = byEndian(beI24, leI24)
244
+ export const i24: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
245
+ beI24,
246
+ leI24
247
+ )
165
248
  /** @since 0.1.0 @category integers */
166
- export const u32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = byEndian(beU32, leU32)
249
+ export const u32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
250
+ beU32,
251
+ leU32
252
+ )
167
253
  /** @since 0.1.0 @category integers */
168
- export const i32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = byEndian(beI32, leI32)
254
+ export const i32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
255
+ beI32,
256
+ leI32
257
+ )
169
258
  /** @since 0.1.0 @category integers */
170
- export const u64: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = byEndian(beU64, leU64)
259
+ export const u64: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
260
+ beU64,
261
+ leU64
262
+ )
171
263
  /** @since 0.1.0 @category integers */
172
- export const i64: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = byEndian(beI64, leI64)
264
+ export const i64: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
265
+ beI64,
266
+ leI64
267
+ )
173
268
  /** @since 0.1.0 @category integers */
174
- export const u128: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = byEndian(beU128, leU128)
269
+ export const u128: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
270
+ beU128,
271
+ leU128
272
+ )
175
273
  /** @since 0.1.0 @category integers */
176
- export const i128: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = byEndian(beI128, leI128)
274
+ export const i128: (endian: Endianness) => Parser<bigint, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
275
+ beI128,
276
+ leI128
277
+ )
177
278
  /** @since 0.1.0 @category floats */
178
- export const f32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = byEndian(beF32, leF32)
279
+ export const f32: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
280
+ beF32,
281
+ leF32
282
+ )
179
283
  /** @since 0.1.0 @category floats */
180
- export const f64: (endian: Endianness) => Parser<number, never, never, Uint8Array> = byEndian(beF64, leF64)
284
+ export const f64: (endian: Endianness) => Parser<number, never, never, Uint8Array> = /*#__PURE__*/ byEndian(
285
+ beF64,
286
+ leF64
287
+ )
181
288
 
182
-
183
- const toCount = (n: number | bigint): number => typeof n === "bigint" ? Number(n) : n
289
+ const toCount = (n: number | bigint): number => (Predicate.isBigInt(n) ? Number(n) : n)
184
290
 
185
291
  /**
186
292
  * Parses a length with `count`, then takes that many tokens (winnow's
package/src/Bits.ts CHANGED
@@ -68,9 +68,12 @@ const inUnits = <A>(state: State<any>, factor: number, step: (state: State<any>)
68
68
  state.pos = factor > 1 ? Math.floor(state.pos / factor) : state.pos / factor
69
69
  const f = state.failure
70
70
  state.failure = scale(f, 1 / factor)
71
+ // A committed failure keeps only the failures recorded after the commit
72
+ // (see `Parser.cut`), so none from before these units
73
+ if (state.mode === "Cut") state.deepest = undefined
71
74
  if (inner !== undefined) {
72
75
  const d = inner === f ? state.failure : scale(inner, 1 / factor)
73
- if (deepest === undefined || d.offset >= deepest.offset) state.deepest = d
76
+ if (state.deepest === undefined || d.offset >= state.deepest.offset) state.deepest = d
74
77
  }
75
78
  return Fail
76
79
  }
@@ -111,7 +114,7 @@ const readBits = (state: State<any>, count: number): number => {
111
114
  let pos = state.pos
112
115
  let value = 0
113
116
  for (let i = 0; i < count; i++) {
114
- const byte = input[pos >>> 3]!
117
+ const byte = input[pos >>> 3]
115
118
  value = value * 2 + ((byte >>> (7 - (pos & 7))) & 1)
116
119
  pos++
117
120
  }
@@ -186,7 +189,7 @@ export const pattern = (pattern: number, count: number): Parser<number, never, n
186
189
  * @since 0.1.0
187
190
  * @category parsers
188
191
  */
189
- export const bool: Parser<boolean, never, never, BitInput> = make((state: State<any>) => {
192
+ export const bool: Parser<boolean, never, never, BitInput> = /*#__PURE__*/ make((state: State<any>) => {
190
193
  if (state.pos >= state.end) return state.eoi("Bits", ["1 bit"], 1)
191
194
  return readBits(state, 1) === 1
192
195
  }, "bool")
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Compiles parsers into fused, specialized code. Grammars are written as
3
+ * usual; compiling the root of a grammar only makes `Parser.parse`,
4
+ * `Parser.parseSync`, `Parser.parsePeek`, `Parser.parsePartial` and
5
+ * `Parser.parseEffect` faster, from any `offset`.
6
+ *
7
+ * There are two compilers, one function each, so a program bundles only the
8
+ * one it uses, and a program that compiles nothing bundles neither:
9
+ *
10
+ * - {@link jit} generates code with `new Function` where it is allowed, and
11
+ * otherwise uses the closure compiler. It is the fastest.
12
+ * - {@link closure} builds specialized closures only. It never generates
13
+ * code, and a bundle that uses only it contains no `new Function`, so it
14
+ * is the choice under a Content Security Policy, where even probing for
15
+ * `new Function` is reported as a violation.
16
+ *
17
+ * ```ts
18
+ * import { Ascii, Compiler, Parser, Token } from "@thomasfosterau/effect-parse"
19
+ *
20
+ * export const list = Compiler.jit(
21
+ * Parser.separated(Ascii.decInt, Token.literal(","))
22
+ * )
23
+ * Parser.parse(list, "1,2,3") // Result.succeed([1, 2, 3]), compiled
24
+ * ```
25
+ *
26
+ * Both return the same parser, so they also work in a pipe:
27
+ * `p.pipe(Compiler.closure)`. The code is built lazily on the first run, for
28
+ * each kind of input (string, bytes or array), and cached with the parser.
29
+ * Compiling a parser again, with either function, replaces its compiled
30
+ * form.
31
+ *
32
+ * **Results and errors are unchanged.** Compiled code records no
33
+ * diagnostics. When it fails, the parser runs again, interpreted, from the
34
+ * same offset, so every `ParseError` (offset, expected, context, cause and
35
+ * message) is exactly the one the interpreter reports.
36
+ *
37
+ * **Callbacks should be pure.** On an input that fails, the callbacks given
38
+ * to `map`, `filter`, `tryMap`, `tap`, `fold`, ... may run twice, once
39
+ * compiled and once interpreted. Callbacks whose results are discarded
40
+ * (a `map` inside `taken` or `preceded`, for example) may not run at all,
41
+ * nor those of a branch that is certain to fail, and token-set predicates
42
+ * may be called once per character code and cached.
43
+ *
44
+ * `Parser.parsePartial` and `ParserStream.parseAll` run a build that
45
+ * handles partial input. `ParserStream.parseMany`, `Parser.parseRecoverable`
46
+ * and runs with the `trace` option are always interpreted. Parsers that
47
+ * can't be described, such as `Parser.make` and `Parser.gen`, run
48
+ * interpreted inside compiled code.
49
+ *
50
+ * @since 0.2.0
51
+ */
52
+ import type { Input } from "./Input.js"
53
+ import type { Parser } from "./Parser.js"
54
+ import { backend as closureBackend } from "./internal/compiler/closure.js"
55
+ import { backend as jitBackend } from "./internal/compiler/jit.js"
56
+ import { register } from "./internal/compiler/registry.js"
57
+
58
+ /**
59
+ * Compiles a parser with the JIT: generated code where `new Function` is
60
+ * allowed, otherwise specialized closures (see {@link closure}). Returns the
61
+ * same parser.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * import { Ascii, Compiler, Parser, Token } from "@thomasfosterau/effect-parse"
66
+ *
67
+ * const list = Compiler.jit(Parser.separated(Ascii.decInt, Token.literal(",")))
68
+ * Parser.parse(list, "1,2,3") // Result.succeed([1, 2, 3])
69
+ * ```
70
+ *
71
+ * @since 0.2.0
72
+ * @category compilation
73
+ */
74
+ export const jit = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> => {
75
+ register(self, jitBackend)
76
+ return self
77
+ }
78
+
79
+ /**
80
+ * Compiles a parser into specialized closures. Returns the same parser.
81
+ * Nothing is generated, so it works under a Content Security Policy, and a
82
+ * bundle that compiles only with `closure` contains no `new Function`.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * import { Ascii, Compiler, Parser, Token } from "@thomasfosterau/effect-parse"
87
+ *
88
+ * const list = Compiler.closure(Parser.separated(Ascii.decInt, Token.literal(",")))
89
+ * Parser.parse(list, "1,2,3") // Result.succeed([1, 2, 3])
90
+ * ```
91
+ *
92
+ * @since 0.2.0
93
+ * @category compilation
94
+ */
95
+ export const closure = <A, E, R, I extends Input>(self: Parser<A, E, R, I>): Parser<A, E, R, I> => {
96
+ register(self, closureBackend)
97
+ return self
98
+ }
package/src/Expression.ts CHANGED
@@ -35,10 +35,10 @@
35
35
  * @since 0.1.0
36
36
  */
37
37
  import type { Input, State } from "./Input.js"
38
- import { Fail, mergeFailures } from "./Input.js"
39
- import type { Failure } from "./Input.js"
38
+ import { Fail } from "./Input.js"
40
39
  import type { Parser } from "./Parser.js"
41
40
  import { make as makeParser } from "./Parser.js"
41
+ import { TiedFailures } from "./internal/ties.js"
42
42
 
43
43
  /**
44
44
  * An operator in an expression grammar.
@@ -160,13 +160,15 @@ export const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<O
160
160
 
161
161
  // Attempts each operator in turn. Returns the index of the first match
162
162
  // (with its output in `matched`), -1 if none matched, or -2 on a fatal
163
- // failure. Expectations of failed attempts are accumulated in `failure`.
163
+ // failure. Failed attempts are folded into `failures`, merged only when
164
+ // read (#44): a round in which an operator matches discards them unmerged.
165
+ // Like `matched`, it is shared by nested expressions, which clear it.
164
166
  let matched: unknown
165
- let failure: Failure | undefined
167
+ const failures = new TiedFailures()
166
168
  const tryOps = (state: State<any>, ops: ReadonlyArray<OperatorBase<any, any, any>>, mustConsume: boolean): number => {
167
169
  const start = state.pos
168
170
  for (let i = 0; i < ops.length; i++) {
169
- const out = ops[i]!.parser.step(state)
171
+ const out = ops[i].parser.step(state)
170
172
  if (out !== Fail) {
171
173
  // A prefix or postfix operator matching nothing would apply forever
172
174
  if (mustConsume && state.pos === start) {
@@ -177,29 +179,36 @@ export const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<O
177
179
  return i
178
180
  }
179
181
  if (state.mode !== "Backtrack") return -2
180
- failure = failure === undefined ? state.failure : mergeFailures(failure, state.failure)
181
182
  state.pos = start
183
+ failures.add(state)
182
184
  }
183
185
  return -1
184
186
  }
185
187
 
186
188
  const expr = (state: State<any>, minPower: number): A | Fail => {
187
189
  let lhs: A | Fail
188
- failure = undefined
190
+ failures.clear()
189
191
  const p = tryOps(state, prefixes, true)
190
192
  if (p === -2) return Fail
191
193
  if (p >= 0) {
192
- const op = prefixes[p]!
194
+ const op = prefixes[p]
193
195
  const opOut = matched
194
196
  const operandValue = expr(state, op.precedence * 2)
195
197
  if (operandValue === Fail) return Fail
196
198
  lhs = op.fold(opOut, operandValue)
197
199
  } else {
198
- const prefixFailure = failure
200
+ const prefixFailure = failures.failure
201
+ const prefixTie1 = failures.tie1
202
+ const prefixTie2 = failures.tie2
199
203
  lhs = operand(state)
200
204
  if (lhs === Fail) {
201
205
  if (prefixFailure !== undefined && state.mode === "Backtrack") {
202
- state.failWith("Backtrack", mergeFailures(prefixFailure, state.failure))
206
+ // The operand may have parsed nested expressions, which reuse `failures`
207
+ failures.failure = prefixFailure
208
+ failures.tie1 = prefixTie1
209
+ failures.tie2 = prefixTie2
210
+ failures.add(state)
211
+ failures.fail(state)
203
212
  }
204
213
  return Fail
205
214
  }
@@ -207,11 +216,11 @@ export const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<O
207
216
 
208
217
  while (true) {
209
218
  const start = state.pos
210
- failure = undefined
219
+ failures.clear()
211
220
  const q = tryOps(state, postfixes, true)
212
221
  if (q === -2) return Fail
213
222
  if (q >= 0) {
214
- const op = postfixes[q]!
223
+ const op = postfixes[q]
215
224
  if (op.precedence * 2 < minPower) {
216
225
  state.pos = start
217
226
  break
@@ -219,15 +228,14 @@ export const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<O
219
228
  lhs = op.fold(lhs, matched)
220
229
  continue
221
230
  }
222
- const postfixFailure = failure
231
+ // The infix attempts are folded on top of the postfix ones
223
232
  const i = tryOps(state, infixes, false)
224
233
  if (i === -2) return Fail
225
234
  if (i < 0) {
226
- const f = postfixFailure === undefined ? failure : failure === undefined ? postfixFailure : mergeFailures(postfixFailure, failure)
227
- if (f !== undefined && f.offset === state.pos) state.setHint(f.offset, f.expected)
235
+ failures.hint(state)
228
236
  break
229
237
  }
230
- const op = infixes[i]!
238
+ const op = infixes[i]
231
239
  const leftPower = op.precedence * 2
232
240
  if (leftPower < minPower) {
233
241
  state.pos = start