@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.
Files changed (155) hide show
  1. package/README.md +247 -230
  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 +143 -131
  25. package/dist/Expression.js.map +1 -1
  26. package/dist/Input.d.ts +206 -177
  27. package/dist/Input.d.ts.map +1 -1
  28. package/dist/Input.js +317 -299
  29. package/dist/Input.js.map +1 -1
  30. package/dist/Nom.d.ts +44 -84
  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 +233 -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 +2010 -1802
  41. package/dist/Parser.js.map +1 -1
  42. package/dist/ParserSchema.d.ts +8 -7
  43. package/dist/ParserSchema.d.ts.map +1 -1
  44. package/dist/ParserSchema.js +49 -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 +26 -0
  111. package/dist/internal/stack.js.map +1 -0
  112. package/dist/internal/syntax.d.ts +146 -0
  113. package/dist/internal/syntax.d.ts.map +1 -0
  114. package/dist/internal/syntax.js +305 -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/tokens.d.ts +25 -30
  121. package/dist/internal/tokens.d.ts.map +1 -1
  122. package/dist/internal/tokens.js +369 -363
  123. package/dist/internal/tokens.js.map +1 -1
  124. package/package.json +42 -28
  125. package/src/Ascii.ts +278 -187
  126. package/src/Binary.ts +150 -44
  127. package/src/Bits.ts +6 -3
  128. package/src/Compiler.ts +98 -0
  129. package/src/Expression.ts +10 -5
  130. package/src/Input.ts +106 -28
  131. package/src/Nom.ts +4 -3
  132. package/src/ParseError.ts +48 -51
  133. package/src/Parser.ts +1163 -795
  134. package/src/ParserStream.ts +104 -80
  135. package/src/Syntax.ts +900 -0
  136. package/src/Text.ts +272 -187
  137. package/src/Token.ts +180 -87
  138. package/src/index.ts +2 -0
  139. package/src/internal/compiler/closure.ts +121 -88
  140. package/src/internal/compiler/entries.ts +21 -8
  141. package/src/internal/compiler/first.ts +17 -15
  142. package/src/internal/compiler/jit.ts +360 -157
  143. package/src/internal/compiler/registry.ts +12 -33
  144. package/src/internal/compiler/sets.ts +17 -11
  145. package/src/internal/entries.ts +4 -2
  146. package/src/internal/node.ts +51 -37
  147. package/src/internal/numbers.ts +22 -20
  148. package/src/internal/resume.ts +8 -4
  149. package/src/internal/run.ts +41 -0
  150. package/src/internal/stack.ts +36 -0
  151. package/src/internal/syntax.ts +421 -0
  152. package/src/internal/text.ts +32 -25
  153. package/src/internal/tokens.ts +96 -51
  154. package/dist/index.d.ts.map +0 -1
  155. 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
@@ -166,7 +166,7 @@ export const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<O
166
166
  const tryOps = (state: State<any>, ops: ReadonlyArray<OperatorBase<any, any, any>>, mustConsume: boolean): number => {
167
167
  const start = state.pos
168
168
  for (let i = 0; i < ops.length; i++) {
169
- const out = ops[i]!.parser.step(state)
169
+ const out = ops[i].parser.step(state)
170
170
  if (out !== Fail) {
171
171
  // A prefix or postfix operator matching nothing would apply forever
172
172
  if (mustConsume && state.pos === start) {
@@ -189,7 +189,7 @@ export const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<O
189
189
  const p = tryOps(state, prefixes, true)
190
190
  if (p === -2) return Fail
191
191
  if (p >= 0) {
192
- const op = prefixes[p]!
192
+ const op = prefixes[p]
193
193
  const opOut = matched
194
194
  const operandValue = expr(state, op.precedence * 2)
195
195
  if (operandValue === Fail) return Fail
@@ -211,7 +211,7 @@ export const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<O
211
211
  const q = tryOps(state, postfixes, true)
212
212
  if (q === -2) return Fail
213
213
  if (q >= 0) {
214
- const op = postfixes[q]!
214
+ const op = postfixes[q]
215
215
  if (op.precedence * 2 < minPower) {
216
216
  state.pos = start
217
217
  break
@@ -223,11 +223,16 @@ export const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<O
223
223
  const i = tryOps(state, infixes, false)
224
224
  if (i === -2) return Fail
225
225
  if (i < 0) {
226
- const f = postfixFailure === undefined ? failure : failure === undefined ? postfixFailure : mergeFailures(postfixFailure, failure)
226
+ const f =
227
+ postfixFailure === undefined
228
+ ? failure
229
+ : failure === undefined
230
+ ? postfixFailure
231
+ : mergeFailures(postfixFailure, failure)
227
232
  if (f !== undefined && f.offset === state.pos) state.setHint(f.offset, f.expected)
228
233
  break
229
234
  }
230
- const op = infixes[i]!
235
+ const op = infixes[i]
231
236
  const leftPower = op.precedence * 2
232
237
  if (leftPower < minPower) {
233
238
  state.pos = start
package/src/Input.ts CHANGED
@@ -8,13 +8,16 @@
8
8
  * failure.
9
9
  *
10
10
  * Most users never touch `State` directly. It is exposed for writing custom
11
- * low-level parsers with `Parser.make`.
11
+ * low-level parsers with `Parser.make`, and for drivers that run a parser's
12
+ * `step` many times over one input, reusing a state with {@link State.reset}.
12
13
  *
13
14
  * @since 0.1.0
14
15
  */
16
+ import * as Predicate from "effect/Predicate"
15
17
  import * as Context from "effect/Context"
16
18
  import type { Encoding } from "./Encoding.js"
17
19
  import type { ErrorKind } from "./ParseError.js"
20
+ import type { Builder as SyntaxBuilder } from "./internal/syntax.js"
18
21
 
19
22
  /**
20
23
  * The kinds of input a parser can consume.
@@ -70,7 +73,7 @@ export const fromSource: {
70
73
  (source: BinaryInput): Uint8Array
71
74
  <I extends Input>(source: Source<I>): I
72
75
  } = (source: Input | BinaryInput): any => {
73
- if (typeof source === "string" || source instanceof Uint8Array || Array.isArray(source)) return source
76
+ if (Predicate.isString(source) || source instanceof Uint8Array || Array.isArray(source)) return source
74
77
  if (ArrayBuffer.isView(source)) return new Uint8Array(source.buffer, source.byteOffset, source.byteLength)
75
78
  // An explicit length fixes the view's size even for a resizable buffer
76
79
  if (isArrayBufferLike(source)) return new Uint8Array(source, 0, source.byteLength)
@@ -78,7 +81,7 @@ export const fromSource: {
78
81
  }
79
82
 
80
83
  const isArrayBufferLike = (u: unknown): u is ArrayBufferLike =>
81
- u instanceof ArrayBuffer || (typeof SharedArrayBuffer !== "undefined" && u instanceof SharedArrayBuffer)
84
+ u instanceof ArrayBuffer || (globalThis.SharedArrayBuffer !== undefined && u instanceof SharedArrayBuffer)
82
85
 
83
86
  /**
84
87
  * The type of a single token of an input.
@@ -86,10 +89,13 @@ const isArrayBufferLike = (u: unknown): u is ArrayBufferLike =>
86
89
  * @since 0.1.0
87
90
  * @category models
88
91
  */
89
- export type Token<I> = I extends string ? string
90
- : I extends Uint8Array ? number
91
- : I extends ReadonlyArray<infer T> ? T
92
- : never
92
+ export type Token<I> = I extends string
93
+ ? string
94
+ : I extends Uint8Array
95
+ ? number
96
+ : I extends ReadonlyArray<infer T>
97
+ ? T
98
+ : never
93
99
 
94
100
  /**
95
101
  * The type of a contiguous slice of an input.
@@ -97,10 +103,13 @@ export type Token<I> = I extends string ? string
97
103
  * @since 0.1.0
98
104
  * @category models
99
105
  */
100
- export type Slice<I> = I extends string ? string
101
- : I extends Uint8Array ? Uint8Array
102
- : I extends ReadonlyArray<infer T> ? ReadonlyArray<T>
103
- : never
106
+ export type Slice<I> = I extends string
107
+ ? string
108
+ : I extends Uint8Array
109
+ ? Uint8Array
110
+ : I extends ReadonlyArray<infer T>
111
+ ? ReadonlyArray<T>
112
+ : never
104
113
 
105
114
  /**
106
115
  * Sentinel returned by a parser step to signal failure. The failure details
@@ -109,7 +118,7 @@ export type Slice<I> = I extends string ? string
109
118
  * @since 0.1.0
110
119
  * @category failure
111
120
  */
112
- export const Fail: unique symbol = Symbol.for("effect-parse/Fail")
121
+ export const Fail: unique symbol = /*#__PURE__*/ Symbol.for("effect-parse/Fail")
113
122
 
114
123
  /**
115
124
  * @since 0.1.0
@@ -158,6 +167,9 @@ export class Failure {
158
167
 
159
168
  const empty: ReadonlyArray<string> = []
160
169
 
170
+ /** The failure a {@link State} starts with, before any step has failed. */
171
+ const initialFailure = /*#__PURE__*/ new Failure(0, "Fail", empty, empty, false, undefined, undefined, 0)
172
+
161
173
  /** @internal */
162
174
  export const emptyStrings = empty
163
175
 
@@ -189,7 +201,8 @@ export class State<I extends Input = Input> {
189
201
  /** The full input being parsed. */
190
202
  readonly input: I
191
203
  /** The current offset. Advanced by parsers, rewound on backtracking. */
192
- pos: number
204
+ // Declared, not defined, so that a subclass can make it an accessor
205
+ declare pos: number
193
206
  /** The end offset (the input's length; in bits inside `Bits.bits`). */
194
207
  end: number
195
208
  /** 0 = string, 1 = Uint8Array, 2 = array. */
@@ -216,7 +229,9 @@ export class State<I extends Input = Input> {
216
229
  * were later swallowed by backtracking (for example a trailing separator
217
230
  * followed by an invalid element). It is reported instead of the final
218
231
  * failure when it lies further into the input. This is the classic PEG
219
- * "farthest failure" heuristic.
232
+ * "farthest failure" heuristic. `Parser.cut` keeps only the failures
233
+ * recorded inside it when it commits, and `Parser.peek` and `Parser.not`
234
+ * forget the failures of a lookahead that succeeded.
220
235
  */
221
236
  deepest: Failure | undefined = undefined
222
237
  /** When defined, `Parser.resumeAfter`/`retryAfter` record failures here. */
@@ -237,20 +252,81 @@ export class State<I extends Input = Input> {
237
252
  * @internal
238
253
  */
239
254
  resume: Map<object, Map<number, unknown>> | undefined = undefined
255
+ /**
256
+ * The tree builder of a `Syntax` parse; `undefined` otherwise.
257
+ *
258
+ * @internal
259
+ */
260
+ syntax: SyntaxBuilder | undefined = undefined
240
261
 
241
- constructor(source: I | Source<I>, options?: {
242
- readonly partial?: boolean | undefined
243
- readonly context?: Context.Context<never> | undefined
244
- readonly offset?: number | undefined
245
- }) {
262
+ constructor(
263
+ source: I | Source<I>,
264
+ options?: {
265
+ readonly partial?: boolean | undefined
266
+ readonly context?: Context.Context<never> | undefined
267
+ readonly offset?: number | undefined
268
+ }
269
+ ) {
246
270
  const input = fromSource(source as Input) as I
247
271
  this.input = input
248
272
  this.end = input.length
249
273
  this.pos = options?.offset ?? 0
250
274
  this.partial = options?.partial ?? false
251
275
  this.context = options?.context ?? Context.empty()
252
- this.inputKind = typeof input === "string" ? 0 : input instanceof Uint8Array ? 1 : 2
253
- this.failure = new Failure(0, "Fail", empty, empty, false, undefined, undefined, 0)
276
+ this.inputKind = Predicate.isString(input) ? 0 : input instanceof Uint8Array ? 1 : 2
277
+ this.failure = initialFailure
278
+ }
279
+
280
+ /**
281
+ * Prepares the state for another run over the same input, starting at
282
+ * `offset`: afterwards it behaves exactly like
283
+ * `new State(state.input, { ...options, offset })`, without allocating a
284
+ * new state.
285
+ *
286
+ * Every per-run field is reset: the cursor and end, the latest failure,
287
+ * hints and furthest failure, recorded recoveries, the tracer and tracing
288
+ * depth, the recorded encoding and streaming checkpoints. Like the
289
+ * constructor, `partial` defaults to `false` and `context` to the empty
290
+ * context, so pass them again on every reset.
291
+ *
292
+ * Use it to run many small parses over one buffer, for example one per
293
+ * token, with `parser.step`. A state can be reused after any run,
294
+ * including one that failed, returned `Incomplete` or threw.
295
+ *
296
+ * @example
297
+ * ```ts
298
+ * import { Ascii, Input } from "@thomasfosterau/effect-parse"
299
+ *
300
+ * const state = new Input.State("12 34")
301
+ * Ascii.decUint.step(state) // 12
302
+ * state.reset(3)
303
+ * Ascii.decUint.step(state) // 34
304
+ * ```
305
+ *
306
+ * @since 0.2.0
307
+ */
308
+ reset(
309
+ offset: number = 0,
310
+ options?: {
311
+ readonly partial?: boolean | undefined
312
+ readonly context?: Context.Context<never> | undefined
313
+ }
314
+ ): this {
315
+ this.pos = offset
316
+ this.end = this.input.length
317
+ this.partial = options?.partial ?? false
318
+ this.context = options?.context ?? Context.empty()
319
+ this.mode = "Backtrack"
320
+ this.failure = initialFailure
321
+ this.hintOffset = -1
322
+ this.hintExpected = empty
323
+ this.deepest = undefined
324
+ this.recovered = undefined
325
+ this.tracer = undefined
326
+ this.depth = 0
327
+ this.encoding = undefined
328
+ this.resume = undefined
329
+ return this
254
330
  }
255
331
 
256
332
  /**
@@ -359,12 +435,17 @@ export class State<I extends Input = Input> {
359
435
  const f = this.failure
360
436
  const d = this.deepest
361
437
  if (
362
- d === undefined || d === f || d.offset <= f.offset || this.mode === "Incomplete" ||
363
- f.hasCause || f.message !== undefined
438
+ d === undefined ||
439
+ d === f ||
440
+ d.offset <= f.offset ||
441
+ this.mode === "Incomplete" ||
442
+ f.hasCause ||
443
+ f.message !== undefined
364
444
  ) {
365
445
  return f
366
446
  }
367
- const context = d.context.length === 0 ? f.context : [...d.context, ...f.context.filter((l) => !d.context.includes(l))]
447
+ const context =
448
+ d.context.length === 0 ? f.context : [...d.context, ...f.context.filter((l) => !d.context.includes(l))]
368
449
  return new Failure(d.offset, d.kind, d.expected, context, d.hasCause, d.cause, d.message, d.needed)
369
450
  }
370
451
 
@@ -392,10 +473,7 @@ export class State<I extends Input = Input> {
392
473
  }
393
474
 
394
475
  /** @internal */
395
- export const mergeExpected = (
396
- a: ReadonlyArray<string>,
397
- b: ReadonlyArray<string>
398
- ): ReadonlyArray<string> => {
476
+ export const mergeExpected = (a: ReadonlyArray<string>, b: ReadonlyArray<string>): ReadonlyArray<string> => {
399
477
  if (a.length === 0) return b
400
478
  if (b.length === 0) return a
401
479
  const out = a.slice()