@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/dist/Ascii.js CHANGED
@@ -1,610 +1,615 @@
1
- /**
2
- * Parsers for ASCII text: character classes, line endings, numbers and
3
- * escaped strings (winnow's `ascii` module, nom's `character` module).
4
- *
5
- * The parsers are typed for `string` input. Each also works on
6
- * `Uint8Array` input (treating bytes as ASCII), and `Ascii.bytes` gives the
7
- * same parsers typed for bytes:
8
- *
9
- * ```ts
10
- * import { Ascii, Parser } from "@thomasfosterau/effect-parse"
11
- *
12
- * Parser.parse(Ascii.decUint, "42") // 42
13
- * Parser.parse(Ascii.bytes.decUint, new TextEncoder().encode("42")) // 42
14
- * ```
15
- *
16
- * Partial (streaming) input is supported: for example `digit1` on the
17
- * partial input `"123"` reports `Incomplete`, since more digits may follow.
18
- *
19
- * For Unicode character classes, or for text in other encodings (UTF-8,
20
- * UTF-16), use the `Text` module.
21
- *
22
- * @since 0.1.0
23
- */
1
+ import * as Predicate from "effect/Predicate";
24
2
  import * as Result from "effect/Result";
25
3
  import { Fail } from "./Input.js";
26
4
  import * as P from "./Parser.js";
27
5
  import * as numbers from "./internal/numbers.js";
28
6
  import * as Resume from "./internal/resume.js";
29
- import { latin1 } from "./internal/text.js";
30
7
  import { codePointPredicate } from "./internal/tokens.js";
8
+ import * as Token$1 from "./Token.js";
31
9
  import { literalImpl, range, takeWhileImpl } from "./Token.js";
32
- import * as Token from "./Token.js";
33
- // -----------------------------------------------------------------------------
34
- // Character predicates
35
- // -----------------------------------------------------------------------------
36
- const code = (c) => typeof c === "number" ? c : c.charCodeAt(0);
37
- /**
38
- * `[a-zA-Z]`
39
- *
40
- * @since 0.1.0
41
- * @category predicates
42
- */
43
- export const isAlpha = codePointPredicate("isAlpha", (c) => {
44
- const x = code(c);
45
- return (x >= 65 && x <= 90) || (x >= 97 && x <= 122);
10
+ //#region src/Ascii.ts
11
+ /**
12
+ * Parsers for ASCII text: character classes, line endings, numbers and
13
+ * escaped strings (winnow's `ascii` module, nom's `character` module).
14
+ *
15
+ * The parsers are typed for `string` input. Each also works on
16
+ * `Uint8Array` input (treating bytes as ASCII), and `Ascii.bytes` gives the
17
+ * same parsers typed for bytes:
18
+ *
19
+ * ```ts
20
+ * import { Ascii, Parser } from "@thomasfosterau/effect-parse"
21
+ *
22
+ * Parser.parse(Ascii.decUint, "42") // 42
23
+ * Parser.parse(Ascii.bytes.decUint, new TextEncoder().encode("42")) // 42
24
+ * ```
25
+ *
26
+ * Partial (streaming) input is supported: for example `digit1` on the
27
+ * partial input `"123"` reports `Incomplete`, since more digits may follow.
28
+ *
29
+ * For Unicode character classes, or for text in other encodings (UTF-8,
30
+ * UTF-16), use the `Text` module.
31
+ *
32
+ * @since 0.1.0
33
+ */
34
+ const code = (c) => Predicate.isNumber(c) ? c : c.charCodeAt(0);
35
+ /**
36
+ * `[a-zA-Z]`
37
+ *
38
+ * @since 0.1.0
39
+ * @category predicates
40
+ */
41
+ const isAlpha = /*#__PURE__*/ codePointPredicate("isAlpha", (c) => {
42
+ const x = code(c);
43
+ return x >= 65 && x <= 90 || x >= 97 && x <= 122;
46
44
  }, [[65, 90], [97, 122]]);
47
45
  /**
48
- * `[0-9]`
49
- *
50
- * @since 0.1.0
51
- * @category predicates
52
- */
53
- export const isDigit = codePointPredicate("isDigit", (c) => {
54
- const x = code(c);
55
- return x >= 48 && x <= 57;
46
+ * `[0-9]`
47
+ *
48
+ * @since 0.1.0
49
+ * @category predicates
50
+ */
51
+ const isDigit = /*#__PURE__*/ codePointPredicate("isDigit", (c) => {
52
+ const x = code(c);
53
+ return x >= 48 && x <= 57;
56
54
  }, [[48, 57]]);
57
55
  /**
58
- * `[0-9a-fA-F]`
59
- *
60
- * @since 0.1.0
61
- * @category predicates
62
- */
63
- export const isHexDigit = codePointPredicate("isHexDigit", (c) => {
64
- const x = code(c);
65
- return (x >= 48 && x <= 57) || (x >= 65 && x <= 70) || (x >= 97 && x <= 102);
66
- }, [[48, 57], [65, 70], [97, 102]]);
67
- /**
68
- * `[0-7]`
69
- *
70
- * @since 0.1.0
71
- * @category predicates
72
- */
73
- export const isOctDigit = codePointPredicate("isOctDigit", (c) => {
74
- const x = code(c);
75
- return x >= 48 && x <= 55;
56
+ * `[0-9a-fA-F]`
57
+ *
58
+ * @since 0.1.0
59
+ * @category predicates
60
+ */
61
+ const isHexDigit = /*#__PURE__*/ codePointPredicate("isHexDigit", (c) => {
62
+ const x = code(c);
63
+ return x >= 48 && x <= 57 || x >= 65 && x <= 70 || x >= 97 && x <= 102;
64
+ }, [
65
+ [48, 57],
66
+ [65, 70],
67
+ [97, 102]
68
+ ]);
69
+ /**
70
+ * `[0-7]`
71
+ *
72
+ * @since 0.1.0
73
+ * @category predicates
74
+ */
75
+ const isOctDigit = /*#__PURE__*/ codePointPredicate("isOctDigit", (c) => {
76
+ const x = code(c);
77
+ return x >= 48 && x <= 55;
76
78
  }, [[48, 55]]);
77
79
  /**
78
- * `[0-9a-zA-Z]`
79
- *
80
- * @since 0.1.0
81
- * @category predicates
82
- */
83
- export const isAlphanumeric = codePointPredicate("isAlphanumeric", (c) => isAlpha(c) || isDigit(c), [[48, 57], [65, 90], [97, 122]]);
84
- /**
85
- * `[ \t]`
86
- *
87
- * @since 0.1.0
88
- * @category predicates
89
- */
90
- export const isSpace = codePointPredicate("isSpace", (c) => {
91
- const x = code(c);
92
- return x === 32 || x === 9;
80
+ * `[0-9a-zA-Z]`
81
+ *
82
+ * @since 0.1.0
83
+ * @category predicates
84
+ */
85
+ const isAlphanumeric = /*#__PURE__*/ codePointPredicate("isAlphanumeric", (c) => isAlpha(c) || isDigit(c), [
86
+ [48, 57],
87
+ [65, 90],
88
+ [97, 122]
89
+ ]);
90
+ /**
91
+ * `[ \t]`
92
+ *
93
+ * @since 0.1.0
94
+ * @category predicates
95
+ */
96
+ const isSpace = /*#__PURE__*/ codePointPredicate("isSpace", (c) => {
97
+ const x = code(c);
98
+ return x === 32 || x === 9;
93
99
  }, [[9, 9], [32, 32]]);
94
100
  /**
95
- * `[ \t\r\n]`
96
- *
97
- * @since 0.1.0
98
- * @category predicates
99
- */
100
- export const isMultispace = codePointPredicate("isMultispace", (c) => {
101
- const x = code(c);
102
- return x === 32 || x === 9 || x === 10 || x === 13;
103
- }, [[9, 10], [13, 13], [32, 32]]);
104
- /**
105
- * `\n`
106
- *
107
- * @since 0.1.0
108
- * @category predicates
109
- */
110
- export const isNewline = codePointPredicate("isNewline", (c) => code(c) === 10, [[10, 10]]);
111
- // Token sets usable for both string and byte input
112
- const alphaSet = [range("a", "z"), range("A", "Z")];
113
- const digitSet = range("0", "9");
114
- const hexSet = [range("0", "9"), range("a", "f"), range("A", "F")];
115
- const octSet = range("0", "7");
116
- const alnumSet = [range("a", "z"), range("A", "Z"), range("0", "9")];
117
- const spaceSet = " \t";
118
- const multispaceSet = " \t\r\n";
101
+ * `[ \t\r\n]`
102
+ *
103
+ * @since 0.1.0
104
+ * @category predicates
105
+ */
106
+ const isMultispace = /*#__PURE__*/ codePointPredicate("isMultispace", (c) => {
107
+ const x = code(c);
108
+ return x === 32 || x === 9 || x === 10 || x === 13;
109
+ }, [
110
+ [9, 10],
111
+ [13, 13],
112
+ [32, 32]
113
+ ]);
114
+ /**
115
+ * `\n`
116
+ *
117
+ * @since 0.1.0
118
+ * @category predicates
119
+ */
120
+ const isNewline = /*#__PURE__*/ codePointPredicate("isNewline", (c) => code(c) === 10, [[10, 10]]);
121
+ const alphaSet = [/*#__PURE__*/ range("a", "z"), /*#__PURE__*/ range("A", "Z")];
122
+ const digitSet = /*#__PURE__*/ range("0", "9");
123
+ const hexSet = [
124
+ /*#__PURE__*/ range("0", "9"),
125
+ /*#__PURE__*/ range("a", "f"),
126
+ /*#__PURE__*/ range("A", "F")
127
+ ];
128
+ const octSet = /*#__PURE__*/ range("0", "7");
129
+ const alnumSet = [
130
+ /*#__PURE__*/ range("a", "z"),
131
+ /*#__PURE__*/ range("A", "Z"),
132
+ /*#__PURE__*/ range("0", "9")
133
+ ];
134
+ const spaceSet = " ";
135
+ const multispaceSet = " \r\n";
119
136
  const cls = (set, min, description, kind, hint = true) => takeWhileImpl(set, { min }, false, `${kind.toLowerCase()}${min}`, description, kind, hint);
120
- // -----------------------------------------------------------------------------
121
- // Character classes
122
- // -----------------------------------------------------------------------------
123
- /**
124
- * Zero or more ASCII letters, `[a-zA-Z]*`.
125
- *
126
- * @since 0.1.0
127
- * @category character classes
128
- */
129
- export const alpha0 = cls(alphaSet, 0, "letter", "Alpha");
130
- /**
131
- * One or more ASCII letters, `[a-zA-Z]+`.
132
- *
133
- * @since 0.1.0
134
- * @category character classes
135
- */
136
- export const alpha1 = cls(alphaSet, 1, "letter", "Alpha");
137
- /**
138
- * Zero or more ASCII digits, `[0-9]*`.
139
- *
140
- * @since 0.1.0
141
- * @category character classes
142
- */
143
- export const digit0 = cls(digitSet, 0, "digit", "Digit");
144
- /**
145
- * One or more ASCII digits, `[0-9]+`.
146
- *
147
- * @since 0.1.0
148
- * @category character classes
149
- */
150
- export const digit1 = cls(digitSet, 1, "digit", "Digit");
151
- /**
152
- * Zero or more hexadecimal digits, `[0-9a-fA-F]*`.
153
- *
154
- * @since 0.1.0
155
- * @category character classes
156
- */
157
- export const hexDigit0 = cls(hexSet, 0, "hexadecimal digit", "HexDigit");
158
- /**
159
- * One or more hexadecimal digits, `[0-9a-fA-F]+`.
160
- *
161
- * @since 0.1.0
162
- * @category character classes
163
- */
164
- export const hexDigit1 = cls(hexSet, 1, "hexadecimal digit", "HexDigit");
165
- /**
166
- * Zero or more octal digits, `[0-7]*`.
167
- *
168
- * @since 0.1.0
169
- * @category character classes
170
- */
171
- export const octDigit0 = cls(octSet, 0, "octal digit", "OctDigit");
172
- /**
173
- * One or more octal digits, `[0-7]+`.
174
- *
175
- * @since 0.1.0
176
- * @category character classes
177
- */
178
- export const octDigit1 = cls(octSet, 1, "octal digit", "OctDigit");
179
- /**
180
- * Zero or more ASCII letters or digits, `[0-9a-zA-Z]*`.
181
- *
182
- * @since 0.1.0
183
- * @category character classes
184
- */
185
- export const alphanumeric0 = cls(alnumSet, 0, "letter or digit", "AlphaNumeric");
186
- /**
187
- * One or more ASCII letters or digits, `[0-9a-zA-Z]+`.
188
- *
189
- * @since 0.1.0
190
- * @category character classes
191
- */
192
- export const alphanumeric1 = cls(alnumSet, 1, "letter or digit", "AlphaNumeric");
193
- /**
194
- * Zero or more spaces and tabs, `[ \t]*`.
195
- *
196
- * @since 0.1.0
197
- * @category character classes
198
- */
199
- export const space0 = cls(spaceSet, 0, "space", "Space", false);
200
- /**
201
- * One or more spaces and tabs, `[ \t]+`.
202
- *
203
- * @since 0.1.0
204
- * @category character classes
205
- */
206
- export const space1 = cls(spaceSet, 1, "space", "Space", false);
207
- /**
208
- * Zero or more spaces, tabs, carriage returns and line feeds,
209
- * `[ \t\r\n]*`.
210
- *
211
- * @since 0.1.0
212
- * @category character classes
213
- */
214
- export const multispace0 = cls(multispaceSet, 0, "whitespace", "MultiSpace", false);
215
- /**
216
- * One or more spaces, tabs, carriage returns and line feeds,
217
- * `[ \t\r\n]+`.
218
- *
219
- * @since 0.1.0
220
- * @category character classes
221
- */
222
- export const multispace1 = cls(multispaceSet, 1, "whitespace", "MultiSpace", false);
223
- // -----------------------------------------------------------------------------
224
- // Line endings
225
- // -----------------------------------------------------------------------------
226
- /**
227
- * A carriage return followed by a line feed, `\r\n`.
228
- *
229
- * @since 0.1.0
230
- * @category line endings
231
- */
232
- export const crlf = Token.literal("\r\n");
233
- /**
234
- * A line feed, `\n` (nom's `newline`).
235
- *
236
- * @since 0.1.0
237
- * @category line endings
238
- */
239
- export const newline = Token.literal("\n");
240
- /**
241
- * A tab, `\t`.
242
- *
243
- * @since 0.1.0
244
- * @category line endings
245
- */
246
- export const tab = Token.literal("\t");
247
- /**
248
- * A line ending: `\n` or `\r\n`.
249
- *
250
- * @since 0.1.0
251
- * @category line endings
252
- */
253
- export const lineEnding = P.alt(newline, crlf).pipe(P.expected("line ending"));
137
+ /**
138
+ * Zero or more ASCII letters, `[a-zA-Z]*`.
139
+ *
140
+ * @since 0.1.0
141
+ * @category character classes
142
+ */
143
+ const alpha0 = /*#__PURE__*/ cls(alphaSet, 0, "letter", "Alpha");
144
+ /**
145
+ * One or more ASCII letters, `[a-zA-Z]+`.
146
+ *
147
+ * @since 0.1.0
148
+ * @category character classes
149
+ */
150
+ const alpha1 = /*#__PURE__*/ cls(alphaSet, 1, "letter", "Alpha");
151
+ /**
152
+ * Zero or more ASCII digits, `[0-9]*`.
153
+ *
154
+ * @since 0.1.0
155
+ * @category character classes
156
+ */
157
+ const digit0 = /*#__PURE__*/ cls(digitSet, 0, "digit", "Digit");
158
+ /**
159
+ * One or more ASCII digits, `[0-9]+`.
160
+ *
161
+ * @since 0.1.0
162
+ * @category character classes
163
+ */
164
+ const digit1 = /*#__PURE__*/ cls(digitSet, 1, "digit", "Digit");
165
+ /**
166
+ * Zero or more hexadecimal digits, `[0-9a-fA-F]*`.
167
+ *
168
+ * @since 0.1.0
169
+ * @category character classes
170
+ */
171
+ const hexDigit0 = /*#__PURE__*/ cls(hexSet, 0, "hexadecimal digit", "HexDigit");
172
+ /**
173
+ * One or more hexadecimal digits, `[0-9a-fA-F]+`.
174
+ *
175
+ * @since 0.1.0
176
+ * @category character classes
177
+ */
178
+ const hexDigit1 = /*#__PURE__*/ cls(hexSet, 1, "hexadecimal digit", "HexDigit");
179
+ /**
180
+ * Zero or more octal digits, `[0-7]*`.
181
+ *
182
+ * @since 0.1.0
183
+ * @category character classes
184
+ */
185
+ const octDigit0 = /*#__PURE__*/ cls(octSet, 0, "octal digit", "OctDigit");
186
+ /**
187
+ * One or more octal digits, `[0-7]+`.
188
+ *
189
+ * @since 0.1.0
190
+ * @category character classes
191
+ */
192
+ const octDigit1 = /*#__PURE__*/ cls(octSet, 1, "octal digit", "OctDigit");
193
+ /**
194
+ * Zero or more ASCII letters or digits, `[0-9a-zA-Z]*`.
195
+ *
196
+ * @since 0.1.0
197
+ * @category character classes
198
+ */
199
+ const alphanumeric0 = /*#__PURE__*/ cls(alnumSet, 0, "letter or digit", "AlphaNumeric");
200
+ /**
201
+ * One or more ASCII letters or digits, `[0-9a-zA-Z]+`.
202
+ *
203
+ * @since 0.1.0
204
+ * @category character classes
205
+ */
206
+ const alphanumeric1 = /*#__PURE__*/ cls(alnumSet, 1, "letter or digit", "AlphaNumeric");
207
+ /**
208
+ * Zero or more spaces and tabs, `[ \t]*`.
209
+ *
210
+ * @since 0.1.0
211
+ * @category character classes
212
+ */
213
+ const space0 = /*#__PURE__*/ cls(spaceSet, 0, "space", "Space", false);
214
+ /**
215
+ * One or more spaces and tabs, `[ \t]+`.
216
+ *
217
+ * @since 0.1.0
218
+ * @category character classes
219
+ */
220
+ const space1 = /*#__PURE__*/ cls(spaceSet, 1, "space", "Space", false);
221
+ /**
222
+ * Zero or more spaces, tabs, carriage returns and line feeds,
223
+ * `[ \t\r\n]*`.
224
+ *
225
+ * @since 0.1.0
226
+ * @category character classes
227
+ */
228
+ const multispace0 = /*#__PURE__*/ cls(multispaceSet, 0, "whitespace", "MultiSpace", false);
229
+ /**
230
+ * One or more spaces, tabs, carriage returns and line feeds,
231
+ * `[ \t\r\n]+`.
232
+ *
233
+ * @since 0.1.0
234
+ * @category character classes
235
+ */
236
+ const multispace1 = /*#__PURE__*/ cls(multispaceSet, 1, "whitespace", "MultiSpace", false);
237
+ /**
238
+ * A carriage return followed by a line feed, `\r\n`.
239
+ *
240
+ * @since 0.1.0
241
+ * @category line endings
242
+ */
243
+ const crlf = /*#__PURE__*/ Token$1.literal("\r\n");
244
+ /**
245
+ * A line feed, `\n` (nom's `newline`).
246
+ *
247
+ * @since 0.1.0
248
+ * @category line endings
249
+ */
250
+ const newline = /*#__PURE__*/ Token$1.literal("\n");
251
+ /**
252
+ * A tab, `\t`.
253
+ *
254
+ * @since 0.1.0
255
+ * @category line endings
256
+ */
257
+ const tab = /*#__PURE__*/ Token$1.literal(" ");
258
+ /**
259
+ * A line ending: `\n` or `\r\n`.
260
+ *
261
+ * @since 0.1.0
262
+ * @category line endings
263
+ */
264
+ const lineEnding = /*#__PURE__*/ P.alt(newline, crlf).pipe(/*#__PURE__*/ P.expected("line ending"));
254
265
  const expectedLineEnding = ["line ending"];
255
266
  /**
256
- * Everything up to (not including) a line ending, `[^\r\n]*` (winnow's
257
- * `till_line_ending`, nom's `not_line_ending`). A carriage return that is
258
- * not followed by a line feed is an error.
259
- *
260
- * @since 0.1.0
261
- * @category line endings
262
- */
263
- export const tillLineEnding = P.described((state) => {
264
- const start = state.pos;
265
- const input = state.input;
266
- const isString = state.inputKind === 0;
267
- let i = start;
268
- while (i < state.end) {
269
- const c = isString ? input.charCodeAt(i) : input[i];
270
- if (c === 10)
271
- break;
272
- if (c === 13) {
273
- if (i + 1 >= state.end) {
274
- if (state.partial)
275
- return state.incomplete(1, expectedLineEnding);
276
- return state.backtrack("LineEnding", expectedLineEnding, i);
277
- }
278
- const d = isString ? input.charCodeAt(i + 1) : input[i + 1];
279
- if (d === 10)
280
- break;
281
- return state.backtrack("LineEnding", expectedLineEnding, i);
282
- }
283
- i++;
284
- }
285
- if (i >= state.end && state.partial)
286
- return state.incomplete(1, expectedLineEnding);
287
- state.pos = i;
288
- return state.slice(start, i);
289
- }, "tillLineEnding", { _tag: "TillLineEnding", encoding: undefined });
290
- // -----------------------------------------------------------------------------
291
- // Numbers
292
- // -----------------------------------------------------------------------------
293
- const toText = (s) => typeof s === "string" ? s : s instanceof Uint8Array ? latin1.text(s, 0, s.length) : s.join("");
267
+ * Everything up to (not including) a line ending, `[^\r\n]*` (winnow's
268
+ * `till_line_ending`, nom's `not_line_ending`). A carriage return that is
269
+ * not followed by a line feed is an error.
270
+ *
271
+ * @since 0.1.0
272
+ * @category line endings
273
+ */
274
+ const tillLineEnding = /*#__PURE__*/ P.described((state) => {
275
+ const start = state.pos;
276
+ const input = state.input;
277
+ const isString = state.inputKind === 0;
278
+ let i = start;
279
+ while (i < state.end) {
280
+ const c = isString ? input.charCodeAt(i) : input[i];
281
+ if (c === 10) break;
282
+ if (c === 13) {
283
+ state.syntax?.read(i + 2);
284
+ if (i + 1 >= state.end) {
285
+ if (state.partial) return state.incomplete(1, expectedLineEnding);
286
+ return state.backtrack("LineEnding", expectedLineEnding, i);
287
+ }
288
+ if ((isString ? input.charCodeAt(i + 1) : input[i + 1]) === 10) break;
289
+ return state.backtrack("LineEnding", expectedLineEnding, i);
290
+ }
291
+ i++;
292
+ }
293
+ if (i >= state.end && state.partial) return state.incomplete(1, expectedLineEnding);
294
+ state.pos = i;
295
+ return state.slice(start, i);
296
+ }, "tillLineEnding", {
297
+ _tag: "TillLineEnding",
298
+ encoding: void 0
299
+ });
294
300
  /** @internal */
295
- export const overflow = (value) => Number.isSafeInteger(value) ? Result.succeed(value) : Result.fail("integer overflow");
296
- /**
297
- * An unsigned decimal integer: one or more digits (winnow's `dec_uint`,
298
- * nom's `u32`/`u64`). Fails if the value is not a safe integer.
299
- *
300
- * @since 0.1.0
301
- * @category numbers
302
- */
303
- export const decUint = digit1.pipe(P.tryMap((s) => overflow(Number(toText(s)))), P.named("decUint"));
304
- /**
305
- * A signed decimal integer: an optional `+` or `-` followed by one or more
306
- * digits (winnow's `dec_int`, nom's `i32`/`i64`). Fails if the value is not
307
- * a safe integer.
308
- *
309
- * @since 0.1.0
310
- * @category numbers
311
- */
312
- export const decInt = P.taken(P.seq(P.opt(Token.oneOf("+-")), digit1)).pipe(P.tryMap((s) => overflow(Number(toText(s)))), P.named("decInt"));
313
- /**
314
- * An unsigned decimal integer as a `bigint`, of any size.
315
- *
316
- * @since 0.1.0
317
- * @category numbers
318
- */
319
- export const decBigUint = digit1.pipe(P.map((s) => BigInt(toText(s))));
320
- /**
321
- * A signed decimal integer as a `bigint`, of any size.
322
- *
323
- * @since 0.1.0
324
- * @category numbers
325
- */
326
- export const decBigInt = P.taken(P.seq(P.opt(Token.oneOf("+-")), digit1)).pipe(P.map((s) => {
327
- const t = toText(s);
328
- return BigInt(t.startsWith("+") ? t.slice(1) : t);
301
+ const overflow = (value) => Number.isSafeInteger(value) ? Result.succeed(value) : Result.fail("integer overflow");
302
+ /**
303
+ * An unsigned decimal integer: one or more digits (winnow's `dec_uint`,
304
+ * nom's `u32`/`u64`). Fails if the value is not a safe integer.
305
+ *
306
+ * @since 0.1.0
307
+ * @category numbers
308
+ */
309
+ const decUint = /*#__PURE__*/ digit1.pipe(/*#__PURE__*/ P.tryMap((s) => overflow(Number(numbers.toText(s)))), /*#__PURE__*/ P.named("decUint"));
310
+ /**
311
+ * A signed decimal integer: an optional `+` or `-` followed by one or more
312
+ * digits (winnow's `dec_int`, nom's `i32`/`i64`). Fails if the value is not
313
+ * a safe integer.
314
+ *
315
+ * @since 0.1.0
316
+ * @category numbers
317
+ */
318
+ const decInt = /*#__PURE__*/ P.taken(/*#__PURE__*/ P.seq(/*#__PURE__*/ P.opt(/*#__PURE__*/ Token$1.oneOf("+-")), digit1)).pipe(/*#__PURE__*/ P.tryMap((s) => overflow(Number(numbers.toText(s)))), /*#__PURE__*/ P.named("decInt"));
319
+ /**
320
+ * An unsigned decimal integer as a `bigint`, of any size.
321
+ *
322
+ * @since 0.1.0
323
+ * @category numbers
324
+ */
325
+ const decBigUint = /*#__PURE__*/ digit1.pipe(/*#__PURE__*/ P.map((s) => BigInt(numbers.toText(s))));
326
+ /**
327
+ * A signed decimal integer as a `bigint`, of any size.
328
+ *
329
+ * @since 0.1.0
330
+ * @category numbers
331
+ */
332
+ const decBigInt = /*#__PURE__*/ P.taken(/*#__PURE__*/ P.seq(/*#__PURE__*/ P.opt(/*#__PURE__*/ Token$1.oneOf("+-")), digit1)).pipe(/*#__PURE__*/ P.map((s) => {
333
+ const t = numbers.toText(s);
334
+ return BigInt(t.startsWith("+") ? t.slice(1) : t);
329
335
  }));
330
336
  /**
331
- * A hexadecimal unsigned integer, without prefix (winnow's `hex_uint`, nom's
332
- * `hex_u32`). Fails if the value is not a safe integer.
333
- *
334
- * @since 0.1.0
335
- * @category numbers
336
- */
337
- export const hexUint = hexDigit1.pipe(P.tryMap((s) => overflow(parseInt(toText(s), 16))), P.named("hexUint"));
338
- const sign = P.opt(Token.oneOf("+-"));
339
- const exponent = P.opt(P.seq(Token.oneOf("eE"), sign, digit1));
340
- const unsignedFloat = P.alt(P.seq(literalImpl("inf", true), P.opt(literalImpl("inity", true))), P.seq(Token.literal("."), digit1, exponent), P.seq(digit1, P.opt(P.seq(Token.literal("."), P.opt(digit1))), exponent));
341
- const floatText = numbers.floatText(P.taken(P.alt(literalImpl("nan", true), P.seq(sign, unsignedFloat))).pipe(P.expected("number")));
337
+ * A hexadecimal unsigned integer, without prefix (winnow's `hex_uint`, nom's
338
+ * `hex_u32`). Fails if the value is not a safe integer.
339
+ *
340
+ * @since 0.1.0
341
+ * @category numbers
342
+ */
343
+ const hexUint = /*#__PURE__*/ hexDigit1.pipe(/*#__PURE__*/ P.tryMap((s) => overflow(parseInt(numbers.toText(s), 16))), /*#__PURE__*/ P.named("hexUint"));
344
+ const sign = /*#__PURE__*/ P.opt(/*#__PURE__*/ Token$1.oneOf("+-"));
345
+ const exponent = /*#__PURE__*/ P.opt(/*#__PURE__*/ P.seq(/*#__PURE__*/ Token$1.oneOf("eE"), sign, digit1));
346
+ const unsignedFloat = /*#__PURE__*/ P.alt(/*#__PURE__*/ P.seq(/*#__PURE__*/ literalImpl("inf", true), /*#__PURE__*/ P.opt(/*#__PURE__*/ literalImpl("inity", true))), /*#__PURE__*/ P.seq(/*#__PURE__*/ Token$1.literal("."), digit1, exponent), /*#__PURE__*/ P.seq(digit1, /*#__PURE__*/ P.opt(/*#__PURE__*/ P.seq(/*#__PURE__*/ Token$1.literal("."), /*#__PURE__*/ P.opt(digit1))), exponent));
347
+ const floatText$1 = /*#__PURE__*/ numbers.floatText(/*#__PURE__*/ P.taken(/*#__PURE__*/ P.alt(/*#__PURE__*/ literalImpl("nan", true), /*#__PURE__*/ P.seq(sign, unsignedFloat))).pipe(/*#__PURE__*/ P.expected("number")));
342
348
  /** @internal */
343
- export const toFloat = numbers.toFloat;
344
- /**
345
- * A floating point number in decimal or scientific notation, including
346
- * `inf`, `infinity` and `nan` (case insensitive), as accepted by winnow's
347
- * `float` and nom's `double`.
348
- *
349
- * @example
350
- * ```ts
351
- * import { Ascii, Parser } from "@thomasfosterau/effect-parse"
352
- *
353
- * Parser.parse(Ascii.float, "-1.5e3") // Result.succeed(-1500)
354
- * ```
355
- *
356
- * @since 0.1.0
357
- * @category numbers
358
- */
359
- export const float = floatText.pipe(P.map(toFloat), P.named("float"));
360
- // -----------------------------------------------------------------------------
361
- // Literals
362
- // -----------------------------------------------------------------------------
363
- /**
364
- * Matches a literal ignoring ASCII case (winnow's `Caseless`, nom's
365
- * `tag_no_case`). Returns the input as written.
366
- *
367
- * @since 0.1.0
368
- * @category literals
369
- */
370
- export const caseless = (lit) => literalImpl(lit, true);
371
- // -----------------------------------------------------------------------------
372
- // Escapes
373
- // -----------------------------------------------------------------------------
374
- const controlCode = (c) => typeof c === "number" ? c : c.charCodeAt(0);
349
+ const toFloat = numbers.toFloat;
350
+ /**
351
+ * A floating point number in decimal or scientific notation, including
352
+ * `inf`, `infinity` and `nan` (case insensitive), as accepted by winnow's
353
+ * `float` and nom's `double`.
354
+ *
355
+ * @example
356
+ * ```ts
357
+ * import { Ascii, Parser } from "@thomasfosterau/effect-parse"
358
+ *
359
+ * Parser.parse(Ascii.float, "-1.5e3") // Result.succeed(-1500)
360
+ * ```
361
+ *
362
+ * @since 0.1.0
363
+ * @category numbers
364
+ */
365
+ const float = /*#__PURE__*/ floatText$1.pipe(/*#__PURE__*/ P.map(toFloat), /*#__PURE__*/ P.named("float"));
366
+ /**
367
+ * Matches a literal ignoring ASCII case (winnow's `Caseless`, nom's
368
+ * `tag_no_case`). Returns the input as written.
369
+ *
370
+ * @since 0.1.0
371
+ * @category literals
372
+ */
373
+ const caseless = (lit) => literalImpl(lit, true);
374
+ const controlCode = (c) => Predicate.isNumber(c) ? c : c.charCodeAt(0);
375
375
  const atControl = (state, control) => {
376
- if (state.pos >= state.end)
377
- return false;
378
- const input = state.input;
379
- const c = state.inputKind === 0 ? input.charCodeAt(state.pos) : input[state.pos];
380
- return c === control;
376
+ if (state.pos >= state.end) return false;
377
+ const input = state.input;
378
+ return (state.inputKind === 0 ? input.charCodeAt(state.pos) : input[state.pos]) === control;
381
379
  };
382
380
  /**
383
- * Recognizes a string containing escape sequences, returning the raw slice
384
- * (winnow's `take_escaped`, nom's `escaped`).
385
- *
386
- * - `normal` matches runs of ordinary characters (it must consume input)
387
- * - `control` is the escape character, e.g. `"\\"`
388
- * - `escapable` matches what may follow the control character
389
- *
390
- * @example
391
- * ```ts
392
- * import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
393
- *
394
- * const raw = Ascii.takeEscaped(Ascii.alpha1, "\\", Token.oneOf("\"n\\"))
395
- * Parser.parse(raw, "ab\\\"cd") // Result.succeed("ab\\\"cd")
396
- * ```
397
- *
398
- * @since 0.1.0
399
- * @category escapes
400
- */
401
- export const takeEscaped = (normal, control, escapable) => {
402
- const ctrl = controlCode(control);
403
- return takeEscapedImpl(normal, (state) => {
404
- if (!atControl(state, ctrl))
405
- return false;
406
- state.pos++;
407
- return true;
408
- }, escapable, (state, start) => state.slice(start, state.pos), ctrl, undefined);
381
+ * Recognizes a string containing escape sequences, returning the raw slice
382
+ * (winnow's `take_escaped`, nom's `escaped`).
383
+ *
384
+ * - `normal` matches runs of ordinary characters (it must consume input)
385
+ * - `control` is the escape character, e.g. `"\\"`
386
+ * - `escapable` matches what may follow the control character
387
+ *
388
+ * @example
389
+ * ```ts
390
+ * import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
391
+ *
392
+ * const raw = Ascii.takeEscaped(Ascii.alpha1, "\\", Token.oneOf("\"n\\"))
393
+ * Parser.parse(raw, "ab\\\"cd") // Result.succeed("ab\\\"cd")
394
+ * ```
395
+ *
396
+ * @since 0.1.0
397
+ * @category escapes
398
+ */
399
+ const takeEscaped = (normal, control, escapable) => {
400
+ const ctrl = controlCode(control);
401
+ return takeEscapedImpl(normal, (state) => {
402
+ if (!atControl(state, ctrl)) return false;
403
+ state.pos++;
404
+ return true;
405
+ }, escapable, (state, start) => state.slice(start, state.pos), ctrl, void 0);
409
406
  };
410
407
  const isIncomplete = (state) => state.mode === "Incomplete";
411
408
  /**
412
- * Fails with the current (`Incomplete`) failure, recording a checkpoint
413
- * first in a streaming parse.
414
- */
409
+ * Fails with the current (`Incomplete`) failure, recording a checkpoint
410
+ * first in a streaming parse.
411
+ */
415
412
  const suspendAt = (state, key, start, checkpoint) => {
416
- if (state.resume !== undefined)
417
- Resume.save(state, key, start, checkpoint);
418
- return Fail;
413
+ if (state.resume !== void 0) Resume.save(state, key, start, checkpoint);
414
+ return Fail;
419
415
  };
420
416
  /** @internal */
421
- export const takeEscapedImpl = (normal, matchControl, escapable, slice, control, encoding) => {
422
- const normalStep = normal.step;
423
- const escStep = escapable.step;
424
- const key = {};
425
- return P.described((state) => {
426
- const start = state.pos;
427
- let resumed = false;
428
- if (state.resume !== undefined) {
429
- const checkpoint = Resume.take(state, key, start);
430
- if (checkpoint instanceof Resume.Done) {
431
- state.pos = checkpoint.pos;
432
- return checkpoint.value;
433
- }
434
- if (checkpoint !== undefined) {
435
- state.pos = checkpoint;
436
- resumed = true;
437
- }
438
- }
439
- while (state.pos < state.end) {
440
- const before = state.pos;
441
- const a = normalStep(state);
442
- if (a !== Fail) {
443
- if (state.pos === before)
444
- return state.failMessage("Cut", "Assert", "`takeEscaped` parsers must always consume");
445
- continue;
446
- }
447
- if (state.mode === "Incomplete")
448
- return suspendAt(state, key, start, before);
449
- if (state.mode !== "Backtrack")
450
- return Fail;
451
- state.pos = before;
452
- if (matchControl(state)) {
453
- if (escStep(state) === Fail)
454
- return isIncomplete(state) ? suspendAt(state, key, start, before) : Fail;
455
- }
456
- else {
457
- return Resume.done(state, key, start, resumed, slice(state, start));
458
- }
459
- }
460
- if (state.partial) {
461
- state.incomplete(0);
462
- return suspendAt(state, key, start, state.pos);
463
- }
464
- return Resume.done(state, key, start, resumed, slice(state, start));
465
- }, "takeEscaped", { _tag: "Escaped", normal, control, escape: escapable, raw: true, encoding });
417
+ const takeEscapedImpl = (normal, matchControl, escapable, slice, control, encoding) => {
418
+ const normalStep = normal.step;
419
+ const escStep = escapable.step;
420
+ const key = {};
421
+ return P.described((state) => {
422
+ const start = state.pos;
423
+ let resumed = false;
424
+ if (state.resume !== void 0) {
425
+ const checkpoint = Resume.take(state, key, start);
426
+ if (checkpoint instanceof Resume.Done) {
427
+ state.pos = checkpoint.pos;
428
+ return checkpoint.value;
429
+ }
430
+ if (checkpoint !== void 0) {
431
+ state.pos = checkpoint;
432
+ resumed = true;
433
+ }
434
+ }
435
+ while (state.pos < state.end) {
436
+ const before = state.pos;
437
+ if (normalStep(state) !== Fail) {
438
+ if (state.pos === before) return state.failMessage("Cut", "Assert", "`takeEscaped` parsers must always consume");
439
+ continue;
440
+ }
441
+ if (state.mode === "Incomplete") return suspendAt(state, key, start, before);
442
+ if (state.mode !== "Backtrack") return Fail;
443
+ state.pos = before;
444
+ if (matchControl(state)) {
445
+ if (escStep(state) === Fail) return isIncomplete(state) ? suspendAt(state, key, start, before) : Fail;
446
+ } else return Resume.done(state, key, start, resumed, slice(state, start));
447
+ }
448
+ if (state.partial) {
449
+ state.incomplete(0);
450
+ return suspendAt(state, key, start, state.pos);
451
+ }
452
+ return Resume.done(state, key, start, resumed, slice(state, start));
453
+ }, "takeEscaped", {
454
+ _tag: "Escaped",
455
+ normal,
456
+ control,
457
+ escape: escapable,
458
+ raw: true,
459
+ encoding
460
+ });
466
461
  };
467
462
  /**
468
- * Parses a string containing escape sequences, returning the *unescaped*
469
- * string (winnow's `escaped`, nom's `escaped_transform`).
470
- *
471
- * - `normal` matches runs of ordinary characters, returning them
472
- * - `control` is the escape character, e.g. `"\\"`
473
- * - `escape` parses what follows the control character, returning its
474
- * replacement
475
- *
476
- * @example
477
- * ```ts
478
- * import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
479
- *
480
- * const unescaped = Ascii.escaped(
481
- * Token.takeTill("\\\""),
482
- * "\\",
483
- * Parser.alt(
484
- * Token.literal("n").pipe(Parser.as("\n")),
485
- * Token.literal("\\"),
486
- * Token.literal("\"")
487
- * )
488
- * )
489
- * Parser.parse(unescaped, "a\\nb") // Result.succeed("a\nb")
490
- * ```
491
- *
492
- * @since 0.1.0
493
- * @category escapes
494
- */
495
- export const escaped = (normal, control, escape) => {
496
- const ctrl = controlCode(control);
497
- return escapedImpl(normal, (state) => {
498
- if (!atControl(state, ctrl))
499
- return false;
500
- state.pos++;
501
- return true;
502
- }, escape, ctrl, undefined);
463
+ * Parses a string containing escape sequences, returning the *unescaped*
464
+ * string (winnow's `escaped`, nom's `escaped_transform`).
465
+ *
466
+ * - `normal` matches runs of ordinary characters, returning them
467
+ * - `control` is the escape character, e.g. `"\\"`
468
+ * - `escape` parses what follows the control character, returning its
469
+ * replacement
470
+ *
471
+ * @example
472
+ * ```ts
473
+ * import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
474
+ *
475
+ * const unescaped = Ascii.escaped(
476
+ * Token.takeTill("\\\""),
477
+ * "\\",
478
+ * Parser.alt(
479
+ * Token.literal("n").pipe(Parser.as("\n")),
480
+ * Token.literal("\\"),
481
+ * Token.literal("\"")
482
+ * )
483
+ * )
484
+ * Parser.parse(unescaped, "a\\nb") // Result.succeed("a\nb")
485
+ * ```
486
+ *
487
+ * @since 0.1.0
488
+ * @category escapes
489
+ */
490
+ const escaped = (normal, control, escape) => {
491
+ const ctrl = controlCode(control);
492
+ return escapedImpl(normal, (state) => {
493
+ if (!atControl(state, ctrl)) return false;
494
+ state.pos++;
495
+ return true;
496
+ }, escape, ctrl, void 0);
503
497
  };
504
498
  /** @internal */
505
- export const escapedImpl = (normal, matchControl, escape, control, encoding) => {
506
- const normalStep = normal.step;
507
- const escStep = escape.step;
508
- const key = {};
509
- return P.described((state) => {
510
- const start = state.pos;
511
- let out = "";
512
- let resumed = false;
513
- if (state.resume !== undefined) {
514
- const checkpoint = Resume.take(state, key, start);
515
- if (checkpoint instanceof Resume.Done) {
516
- state.pos = checkpoint.pos;
517
- return checkpoint.value;
518
- }
519
- if (checkpoint !== undefined) {
520
- out = checkpoint.out;
521
- state.pos = checkpoint.pos;
522
- resumed = true;
523
- }
524
- }
525
- while (state.pos < state.end) {
526
- const before = state.pos;
527
- const a = normalStep(state);
528
- if (a !== Fail) {
529
- if (state.pos !== before) {
530
- out += a;
531
- continue;
532
- }
533
- // `normal` matched nothing: fall through to the control character
534
- }
535
- else {
536
- if (state.mode === "Incomplete")
537
- return suspendAt(state, key, start, { out, pos: before });
538
- if (state.mode !== "Backtrack")
539
- return Fail;
540
- state.pos = before;
541
- }
542
- if (matchControl(state)) {
543
- const b = escStep(state);
544
- if (b === Fail)
545
- return isIncomplete(state) ? suspendAt(state, key, start, { out, pos: before }) : Fail;
546
- out += b;
547
- }
548
- else {
549
- return Resume.done(state, key, start, resumed, out);
550
- }
551
- }
552
- if (state.partial) {
553
- state.incomplete(0);
554
- return suspendAt(state, key, start, { out, pos: state.pos });
555
- }
556
- return Resume.done(state, key, start, resumed, out);
557
- }, "escaped", { _tag: "Escaped", normal, control, escape, raw: false, encoding });
499
+ const escapedImpl = (normal, matchControl, escape, control, encoding) => {
500
+ const normalStep = normal.step;
501
+ const escStep = escape.step;
502
+ const key = {};
503
+ return P.described((state) => {
504
+ const start = state.pos;
505
+ let out = "";
506
+ let resumed = false;
507
+ if (state.resume !== void 0) {
508
+ const checkpoint = Resume.take(state, key, start);
509
+ if (checkpoint instanceof Resume.Done) {
510
+ state.pos = checkpoint.pos;
511
+ return checkpoint.value;
512
+ }
513
+ if (checkpoint !== void 0) {
514
+ out = checkpoint.out;
515
+ state.pos = checkpoint.pos;
516
+ resumed = true;
517
+ }
518
+ }
519
+ while (state.pos < state.end) {
520
+ const before = state.pos;
521
+ const a = normalStep(state);
522
+ if (a !== Fail) {
523
+ if (state.pos !== before) {
524
+ out += a;
525
+ continue;
526
+ }
527
+ } else {
528
+ if (state.mode === "Incomplete") return suspendAt(state, key, start, {
529
+ out,
530
+ pos: before
531
+ });
532
+ if (state.mode !== "Backtrack") return Fail;
533
+ state.pos = before;
534
+ }
535
+ if (matchControl(state)) {
536
+ const b = escStep(state);
537
+ if (b === Fail) return isIncomplete(state) ? suspendAt(state, key, start, {
538
+ out,
539
+ pos: before
540
+ }) : Fail;
541
+ out += b;
542
+ } else return Resume.done(state, key, start, resumed, out);
543
+ }
544
+ if (state.partial) {
545
+ state.incomplete(0);
546
+ return suspendAt(state, key, start, {
547
+ out,
548
+ pos: state.pos
549
+ });
550
+ }
551
+ return Resume.done(state, key, start, resumed, out);
552
+ }, "escaped", {
553
+ _tag: "Escaped",
554
+ normal,
555
+ control,
556
+ escape,
557
+ raw: false,
558
+ encoding
559
+ });
558
560
  };
559
561
  /**
560
- * The parsers of this module, typed for `Uint8Array` input. Slices are
561
- * returned as `Uint8Array`s.
562
- *
563
- * @example
564
- * ```ts
565
- * import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
566
- *
567
- * const encode = (s: string) => new TextEncoder().encode(s)
568
- * const header = Parser.separatedPair(
569
- * Ascii.bytes.alpha1,
570
- * Token.literal(encode(": ")),
571
- * Ascii.bytes.tillLineEnding
572
- * )
573
- * ```
574
- *
575
- * @since 0.1.0
576
- * @category byte views
577
- */
578
- export const bytes = (() => {
579
- const lit = (s) => Token.literal(new TextEncoder().encode(s));
580
- const crlfB = lit("\r\n");
581
- const newlineB = lit("\n");
582
- return {
583
- alpha0,
584
- alpha1,
585
- digit0,
586
- digit1,
587
- hexDigit0,
588
- hexDigit1,
589
- octDigit0,
590
- octDigit1,
591
- alphanumeric0,
592
- alphanumeric1,
593
- space0,
594
- space1,
595
- multispace0,
596
- multispace1,
597
- crlf: crlfB,
598
- newline: newlineB,
599
- tab: lit("\t"),
600
- lineEnding: P.alt(newlineB, crlfB).pipe(P.expected("line ending")),
601
- tillLineEnding,
602
- decUint,
603
- decInt,
604
- decBigUint,
605
- decBigInt,
606
- hexUint,
607
- float
608
- };
562
+ * The parsers of this module, typed for `Uint8Array` input. Slices are
563
+ * returned as `Uint8Array`s.
564
+ *
565
+ * @example
566
+ * ```ts
567
+ * import { Ascii, Parser, Token } from "@thomasfosterau/effect-parse"
568
+ *
569
+ * const encode = (s: string) => new TextEncoder().encode(s)
570
+ * const header = Parser.separatedPair(
571
+ * Ascii.bytes.alpha1,
572
+ * Token.literal(encode(": ")),
573
+ * Ascii.bytes.tillLineEnding
574
+ * )
575
+ * ```
576
+ *
577
+ * @since 0.1.0
578
+ * @category byte views
579
+ */
580
+ const bytes = /*#__PURE__*/ (() => {
581
+ const lit = (s) => Token$1.literal(new TextEncoder().encode(s));
582
+ const crlfB = lit("\r\n");
583
+ const newlineB = lit("\n");
584
+ return {
585
+ alpha0,
586
+ alpha1,
587
+ digit0,
588
+ digit1,
589
+ hexDigit0,
590
+ hexDigit1,
591
+ octDigit0,
592
+ octDigit1,
593
+ alphanumeric0,
594
+ alphanumeric1,
595
+ space0,
596
+ space1,
597
+ multispace0,
598
+ multispace1,
599
+ crlf: crlfB,
600
+ newline: newlineB,
601
+ tab: lit(" "),
602
+ lineEnding: P.alt(newlineB, crlfB).pipe(P.expected("line ending")),
603
+ tillLineEnding,
604
+ decUint,
605
+ decInt,
606
+ decBigUint,
607
+ decBigInt,
608
+ hexUint,
609
+ float
610
+ };
609
611
  })();
612
+ //#endregion
613
+ export { alpha0, alpha1, alphanumeric0, alphanumeric1, bytes, caseless, crlf, decBigInt, decBigUint, decInt, decUint, digit0, digit1, escaped, escapedImpl, float, hexDigit0, hexDigit1, hexUint, isAlpha, isAlphanumeric, isDigit, isHexDigit, isMultispace, isNewline, isOctDigit, isSpace, lineEnding, multispace0, multispace1, newline, octDigit0, octDigit1, overflow, space0, space1, tab, takeEscaped, takeEscapedImpl, tillLineEnding, toFloat };
614
+
610
615
  //# sourceMappingURL=Ascii.js.map