@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.
- package/README.md +291 -231
- package/dist/Ascii.d.ts +32 -53
- package/dist/Ascii.d.ts.map +1 -1
- package/dist/Ascii.js +576 -571
- package/dist/Ascii.js.map +1 -1
- package/dist/Binary.d.ts +6 -29
- package/dist/Binary.d.ts.map +1 -1
- package/dist/Binary.js +129 -116
- package/dist/Binary.js.map +1 -1
- package/dist/Bits.d.ts +4 -2
- package/dist/Bits.d.ts.map +1 -1
- package/dist/Bits.js +121 -123
- package/dist/Bits.js.map +1 -1
- package/dist/Compiler.d.ts +39 -0
- package/dist/Compiler.d.ts.map +1 -0
- package/dist/Compiler.js +48 -0
- package/dist/Compiler.js.map +1 -0
- package/dist/Encoding.d.ts +29 -46
- package/dist/Encoding.d.ts.map +1 -1
- package/dist/Encoding.js +76 -75
- package/dist/Encoding.js.map +1 -1
- package/dist/Expression.d.ts +15 -49
- package/dist/Expression.d.ts.map +1 -1
- package/dist/Expression.js +151 -132
- package/dist/Expression.js.map +1 -1
- package/dist/Input.d.ts +251 -177
- package/dist/Input.d.ts.map +1 -1
- package/dist/Input.js +409 -299
- package/dist/Input.js.map +1 -1
- package/dist/Nom.d.ts +45 -85
- package/dist/Nom.d.ts.map +1 -1
- package/dist/Nom.js +423 -453
- package/dist/Nom.js.map +1 -1
- package/dist/ParseError.d.ts +54 -49
- package/dist/ParseError.d.ts.map +1 -1
- package/dist/ParseError.js +232 -275
- package/dist/ParseError.js.map +1 -1
- package/dist/Parser.d.ts +345 -313
- package/dist/Parser.d.ts.map +1 -1
- package/dist/Parser.js +2034 -1802
- package/dist/Parser.js.map +1 -1
- package/dist/ParserSchema.d.ts +206 -7
- package/dist/ParserSchema.d.ts.map +1 -1
- package/dist/ParserSchema.js +678 -49
- package/dist/ParserSchema.js.map +1 -1
- package/dist/ParserStream.d.ts +26 -20
- package/dist/ParserStream.d.ts.map +1 -1
- package/dist/ParserStream.js +267 -255
- package/dist/ParserStream.js.map +1 -1
- package/dist/Syntax.d.ts +401 -0
- package/dist/Syntax.d.ts.map +1 -0
- package/dist/Syntax.js +717 -0
- package/dist/Syntax.js.map +1 -0
- package/dist/Text.d.ts +98 -134
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +534 -496
- package/dist/Text.js.map +1 -1
- package/dist/Token.d.ts +60 -42
- package/dist/Token.d.ts.map +1 -1
- package/dist/Token.js +331 -265
- package/dist/Token.js.map +1 -1
- package/dist/index.d.ts +16 -17
- package/dist/index.js +16 -17
- package/dist/internal/compiler/closure.d.ts +14 -16
- package/dist/internal/compiler/closure.d.ts.map +1 -1
- package/dist/internal/compiler/closure.js +1458 -1637
- package/dist/internal/compiler/closure.js.map +1 -1
- package/dist/internal/compiler/entries.d.ts +11 -11
- package/dist/internal/compiler/entries.d.ts.map +1 -1
- package/dist/internal/compiler/entries.js +36 -26
- package/dist/internal/compiler/entries.js.map +1 -1
- package/dist/internal/compiler/first.d.ts +19 -19
- package/dist/internal/compiler/first.d.ts.map +1 -1
- package/dist/internal/compiler/first.js +251 -227
- package/dist/internal/compiler/first.js.map +1 -1
- package/dist/internal/compiler/jit.d.ts +6 -17
- package/dist/internal/compiler/jit.d.ts.map +1 -1
- package/dist/internal/compiler/jit.js +860 -988
- package/dist/internal/compiler/jit.js.map +1 -1
- package/dist/internal/compiler/registry.d.ts +20 -21
- package/dist/internal/compiler/registry.d.ts.map +1 -1
- package/dist/internal/compiler/registry.js +21 -41
- package/dist/internal/compiler/registry.js.map +1 -1
- package/dist/internal/compiler/sets.d.ts +9 -13
- package/dist/internal/compiler/sets.d.ts.map +1 -1
- package/dist/internal/compiler/sets.js +76 -73
- package/dist/internal/compiler/sets.js.map +1 -1
- package/dist/internal/entries.d.ts +3 -3
- package/dist/internal/entries.d.ts.map +1 -1
- package/dist/internal/entries.js +38 -30
- package/dist/internal/entries.js.map +1 -1
- package/dist/internal/node.d.ts +177 -173
- package/dist/internal/node.d.ts.map +1 -1
- package/dist/internal/node.js +77 -66
- package/dist/internal/node.js.map +1 -1
- package/dist/internal/numbers.d.ts +7 -8
- package/dist/internal/numbers.d.ts.map +1 -1
- package/dist/internal/numbers.js +246 -276
- package/dist/internal/numbers.js.map +1 -1
- package/dist/internal/resume.d.ts +6 -24
- package/dist/internal/resume.d.ts.map +1 -1
- package/dist/internal/resume.js +30 -29
- package/dist/internal/resume.js.map +1 -1
- package/dist/internal/run.d.ts +15 -0
- package/dist/internal/run.d.ts.map +1 -0
- package/dist/internal/run.js +36 -0
- package/dist/internal/run.js.map +1 -0
- package/dist/internal/stack.d.ts +16 -0
- package/dist/internal/stack.d.ts.map +1 -0
- package/dist/internal/stack.js +36 -0
- package/dist/internal/stack.js.map +1 -0
- package/dist/internal/syntax.d.ts +147 -0
- package/dist/internal/syntax.d.ts.map +1 -0
- package/dist/internal/syntax.js +309 -0
- package/dist/internal/syntax.js.map +1 -0
- package/dist/internal/text.d.ts +10 -2
- package/dist/internal/text.d.ts.map +1 -1
- package/dist/internal/text.js +295 -345
- package/dist/internal/text.js.map +1 -1
- package/dist/internal/ties.d.ts +30 -0
- package/dist/internal/ties.d.ts.map +1 -0
- package/dist/internal/ties.js +67 -0
- package/dist/internal/ties.js.map +1 -0
- package/dist/internal/tokens.d.ts +25 -30
- package/dist/internal/tokens.d.ts.map +1 -1
- package/dist/internal/tokens.js +369 -363
- package/dist/internal/tokens.js.map +1 -1
- package/package.json +42 -28
- package/src/Ascii.ts +278 -187
- package/src/Binary.ts +150 -44
- package/src/Bits.ts +6 -3
- package/src/Compiler.ts +98 -0
- package/src/Expression.ts +24 -16
- package/src/Input.ts +210 -35
- package/src/Nom.ts +4 -3
- package/src/ParseError.ts +49 -52
- package/src/Parser.ts +1199 -799
- package/src/ParserSchema.ts +982 -23
- package/src/ParserStream.ts +104 -80
- package/src/Syntax.ts +900 -0
- package/src/Text.ts +272 -187
- package/src/Token.ts +180 -87
- package/src/index.ts +2 -0
- package/src/internal/compiler/closure.ts +121 -88
- package/src/internal/compiler/entries.ts +21 -8
- package/src/internal/compiler/first.ts +17 -15
- package/src/internal/compiler/jit.ts +360 -157
- package/src/internal/compiler/registry.ts +12 -33
- package/src/internal/compiler/sets.ts +17 -11
- package/src/internal/entries.ts +4 -2
- package/src/internal/node.ts +51 -37
- package/src/internal/numbers.ts +22 -20
- package/src/internal/resume.ts +8 -4
- package/src/internal/run.ts +41 -0
- package/src/internal/stack.ts +41 -0
- package/src/internal/syntax.ts +426 -0
- package/src/internal/text.ts +32 -25
- package/src/internal/ties.ts +83 -0
- package/src/internal/tokens.ts +96 -51
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/src/Text.ts
CHANGED
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
*
|
|
37
37
|
* @since 0.1.0
|
|
38
38
|
*/
|
|
39
|
+
import * as Predicate from "effect/Predicate"
|
|
39
40
|
import type { Encoding } from "./Encoding.js"
|
|
40
41
|
import * as Encodings from "./Encoding.js"
|
|
41
42
|
import type { Input, State } from "./Input.js"
|
|
@@ -63,7 +64,7 @@ import type { StringTokenSet } from "./Token.js"
|
|
|
63
64
|
*/
|
|
64
65
|
export type CharPredicate = (char: string | number) => boolean
|
|
65
66
|
|
|
66
|
-
const toCodePoint = (c: string | number): number =>
|
|
67
|
+
const toCodePoint = (c: string | number): number => (Predicate.isNumber(c) ? c : (c.codePointAt(0) ?? -1))
|
|
67
68
|
|
|
68
69
|
const makePredicate = (name: string, re: RegExp): CharPredicate => {
|
|
69
70
|
// Results for the Basic Multilingual Plane are cached: a table lookup is
|
|
@@ -77,7 +78,7 @@ const makePredicate = (name: string, re: RegExp): CharPredicate => {
|
|
|
77
78
|
if (x < 128) table = ascii ??= new Uint8Array(128)
|
|
78
79
|
else if (x < 0x10000) table = bmp ??= new Uint8Array(0x10000)
|
|
79
80
|
else return re.test(String.fromCodePoint(x))
|
|
80
|
-
let v = table[x]
|
|
81
|
+
let v = table[x]
|
|
81
82
|
if (v === 0) table[x] = v = re.test(String.fromCharCode(x)) ? 2 : 1
|
|
82
83
|
return v === 2
|
|
83
84
|
})
|
|
@@ -108,7 +109,7 @@ export const property = (name: string): CharPredicate => makePredicate(name, new
|
|
|
108
109
|
* @since 0.1.0
|
|
109
110
|
* @category predicates
|
|
110
111
|
*/
|
|
111
|
-
export const isAlphabetic: CharPredicate = makePredicate("isAlphabetic", /^\p{Alphabetic}$/u)
|
|
112
|
+
export const isAlphabetic: CharPredicate = /*#__PURE__*/ makePredicate("isAlphabetic", /^\p{Alphabetic}$/u)
|
|
112
113
|
|
|
113
114
|
/**
|
|
114
115
|
* Letters (general category `L`).
|
|
@@ -116,7 +117,7 @@ export const isAlphabetic: CharPredicate = makePredicate("isAlphabetic", /^\p{Al
|
|
|
116
117
|
* @since 0.1.0
|
|
117
118
|
* @category predicates
|
|
118
119
|
*/
|
|
119
|
-
export const isLetter: CharPredicate = makePredicate("isLetter", /^\p{L}$/u)
|
|
120
|
+
export const isLetter: CharPredicate = /*#__PURE__*/ makePredicate("isLetter", /^\p{L}$/u)
|
|
120
121
|
|
|
121
122
|
/**
|
|
122
123
|
* Uppercase characters (the Unicode `Uppercase` property).
|
|
@@ -124,7 +125,7 @@ export const isLetter: CharPredicate = makePredicate("isLetter", /^\p{L}$/u)
|
|
|
124
125
|
* @since 0.1.0
|
|
125
126
|
* @category predicates
|
|
126
127
|
*/
|
|
127
|
-
export const isUppercase: CharPredicate = makePredicate("isUppercase", /^\p{Uppercase}$/u)
|
|
128
|
+
export const isUppercase: CharPredicate = /*#__PURE__*/ makePredicate("isUppercase", /^\p{Uppercase}$/u)
|
|
128
129
|
|
|
129
130
|
/**
|
|
130
131
|
* Lowercase characters (the Unicode `Lowercase` property).
|
|
@@ -132,7 +133,7 @@ export const isUppercase: CharPredicate = makePredicate("isUppercase", /^\p{Uppe
|
|
|
132
133
|
* @since 0.1.0
|
|
133
134
|
* @category predicates
|
|
134
135
|
*/
|
|
135
|
-
export const isLowercase: CharPredicate = makePredicate("isLowercase", /^\p{Lowercase}$/u)
|
|
136
|
+
export const isLowercase: CharPredicate = /*#__PURE__*/ makePredicate("isLowercase", /^\p{Lowercase}$/u)
|
|
136
137
|
|
|
137
138
|
/**
|
|
138
139
|
* Decimal digits of any script (general category `Nd`): `0`–`9`, `٠`–`٩`,
|
|
@@ -141,7 +142,7 @@ export const isLowercase: CharPredicate = makePredicate("isLowercase", /^\p{Lowe
|
|
|
141
142
|
* @since 0.1.0
|
|
142
143
|
* @category predicates
|
|
143
144
|
*/
|
|
144
|
-
export const isDecimalDigit: CharPredicate = makePredicate("isDecimalDigit", /^\p{Nd}$/u)
|
|
145
|
+
export const isDecimalDigit: CharPredicate = /*#__PURE__*/ makePredicate("isDecimalDigit", /^\p{Nd}$/u)
|
|
145
146
|
|
|
146
147
|
/**
|
|
147
148
|
* Numeric characters (general category `N`), including `½` and `Ⅻ` (Rust's
|
|
@@ -150,7 +151,7 @@ export const isDecimalDigit: CharPredicate = makePredicate("isDecimalDigit", /^\
|
|
|
150
151
|
* @since 0.1.0
|
|
151
152
|
* @category predicates
|
|
152
153
|
*/
|
|
153
|
-
export const isNumeric: CharPredicate = makePredicate("isNumeric", /^\p{N}$/u)
|
|
154
|
+
export const isNumeric: CharPredicate = /*#__PURE__*/ makePredicate("isNumeric", /^\p{N}$/u)
|
|
154
155
|
|
|
155
156
|
/**
|
|
156
157
|
* Alphabetic or numeric characters (Rust's `char::is_alphanumeric`).
|
|
@@ -158,7 +159,7 @@ export const isNumeric: CharPredicate = makePredicate("isNumeric", /^\p{N}$/u)
|
|
|
158
159
|
* @since 0.1.0
|
|
159
160
|
* @category predicates
|
|
160
161
|
*/
|
|
161
|
-
export const isAlphanumeric: CharPredicate = makePredicate("isAlphanumeric", /^[\p{Alphabetic}\p{N}]$/u)
|
|
162
|
+
export const isAlphanumeric: CharPredicate = /*#__PURE__*/ makePredicate("isAlphanumeric", /^[\p{Alphabetic}\p{N}]$/u)
|
|
162
163
|
|
|
163
164
|
/**
|
|
164
165
|
* Whitespace, including line breaks (the Unicode `White_Space` property,
|
|
@@ -167,7 +168,7 @@ export const isAlphanumeric: CharPredicate = makePredicate("isAlphanumeric", /^[
|
|
|
167
168
|
* @since 0.1.0
|
|
168
169
|
* @category predicates
|
|
169
170
|
*/
|
|
170
|
-
export const isWhitespace: CharPredicate = makePredicate("isWhitespace", /^\p{White_Space}$/u)
|
|
171
|
+
export const isWhitespace: CharPredicate = /*#__PURE__*/ makePredicate("isWhitespace", /^\p{White_Space}$/u)
|
|
171
172
|
|
|
172
173
|
/**
|
|
173
174
|
* Whitespace that does not break lines: `White_Space` except `\n`, `\v`,
|
|
@@ -176,7 +177,7 @@ export const isWhitespace: CharPredicate = makePredicate("isWhitespace", /^\p{Wh
|
|
|
176
177
|
* @since 0.1.0
|
|
177
178
|
* @category predicates
|
|
178
179
|
*/
|
|
179
|
-
export const isSpace: CharPredicate = makePredicate(
|
|
180
|
+
export const isSpace: CharPredicate = /*#__PURE__*/ makePredicate(
|
|
180
181
|
"isSpace",
|
|
181
182
|
/^(?![\n\v\f\r\u0085\u2028\u2029])\p{White_Space}$/u
|
|
182
183
|
)
|
|
@@ -188,7 +189,7 @@ export const isSpace: CharPredicate = makePredicate(
|
|
|
188
189
|
* @since 0.1.0
|
|
189
190
|
* @category predicates
|
|
190
191
|
*/
|
|
191
|
-
export const isIdStart: CharPredicate = makePredicate("isIdStart", /^\p{ID_Start}$/u)
|
|
192
|
+
export const isIdStart: CharPredicate = /*#__PURE__*/ makePredicate("isIdStart", /^\p{ID_Start}$/u)
|
|
192
193
|
|
|
193
194
|
/**
|
|
194
195
|
* Characters that can continue an identifier (the Unicode `ID_Continue`
|
|
@@ -197,7 +198,7 @@ export const isIdStart: CharPredicate = makePredicate("isIdStart", /^\p{ID_Start
|
|
|
197
198
|
* @since 0.1.0
|
|
198
199
|
* @category predicates
|
|
199
200
|
*/
|
|
200
|
-
export const isIdContinue: CharPredicate = makePredicate("isIdContinue", /^\p{ID_Continue}$/u)
|
|
201
|
+
export const isIdContinue: CharPredicate = /*#__PURE__*/ makePredicate("isIdContinue", /^\p{ID_Continue}$/u)
|
|
201
202
|
|
|
202
203
|
/**
|
|
203
204
|
* Punctuation (general category `P`).
|
|
@@ -205,7 +206,7 @@ export const isIdContinue: CharPredicate = makePredicate("isIdContinue", /^\p{ID
|
|
|
205
206
|
* @since 0.1.0
|
|
206
207
|
* @category predicates
|
|
207
208
|
*/
|
|
208
|
-
export const isPunctuation: CharPredicate = makePredicate("isPunctuation", /^\p{P}$/u)
|
|
209
|
+
export const isPunctuation: CharPredicate = /*#__PURE__*/ makePredicate("isPunctuation", /^\p{P}$/u)
|
|
209
210
|
|
|
210
211
|
/**
|
|
211
212
|
* Control characters (general category `Cc`).
|
|
@@ -213,7 +214,7 @@ export const isPunctuation: CharPredicate = makePredicate("isPunctuation", /^\p{
|
|
|
213
214
|
* @since 0.1.0
|
|
214
215
|
* @category predicates
|
|
215
216
|
*/
|
|
216
|
-
export const isControl: CharPredicate = makePredicate("isControl", /^\p{Cc}$/u)
|
|
217
|
+
export const isControl: CharPredicate = /*#__PURE__*/ makePredicate("isControl", /^\p{Cc}$/u)
|
|
217
218
|
|
|
218
219
|
// -----------------------------------------------------------------------------
|
|
219
220
|
// Parsers
|
|
@@ -354,15 +355,21 @@ export interface TextParsers<I extends string | Uint8Array> {
|
|
|
354
355
|
|
|
355
356
|
const normalize = (r: Range | undefined): [number, number] => {
|
|
356
357
|
if (r === undefined) return [0, Infinity]
|
|
357
|
-
if (
|
|
358
|
+
if (Predicate.isNumber(r)) return [r, r]
|
|
358
359
|
return [r.min ?? 0, r.max ?? Infinity]
|
|
359
360
|
}
|
|
360
361
|
|
|
361
|
-
const isAsciiDigit = codePointPredicate("isAsciiDigit", (c: number): boolean => c >= 48 && c <= 57, [
|
|
362
|
-
|
|
362
|
+
const isAsciiDigit = /*#__PURE__*/ codePointPredicate("isAsciiDigit", (c: number): boolean => c >= 48 && c <= 57, [
|
|
363
|
+
[48, 57]
|
|
364
|
+
])
|
|
365
|
+
const isAsciiHexDigit = /*#__PURE__*/ codePointPredicate(
|
|
363
366
|
"isAsciiHexDigit",
|
|
364
367
|
(c: number): boolean => (c >= 48 && c <= 57) || (c >= 65 && c <= 70) || (c >= 97 && c <= 102),
|
|
365
|
-
[
|
|
368
|
+
[
|
|
369
|
+
[48, 57],
|
|
370
|
+
[65, 70],
|
|
371
|
+
[97, 102]
|
|
372
|
+
]
|
|
366
373
|
)
|
|
367
374
|
const isLineBreak = (c: number): boolean => c === 10 || c === 13
|
|
368
375
|
|
|
@@ -417,29 +424,38 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
417
424
|
set: unknown = test
|
|
418
425
|
): Parser<string, never, never, I> => {
|
|
419
426
|
const [min, max] = normalize(r)
|
|
420
|
-
return P.described<string, never, never, I>(
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
427
|
+
return P.described<string, never, never, I>(
|
|
428
|
+
(state: State<any>) => {
|
|
429
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
430
|
+
const start = state.pos
|
|
431
|
+
internal.scan(enc, state, test, negate, max, state.pos, fast)
|
|
432
|
+
const offset = internal.scanOffset
|
|
433
|
+
const count = internal.scanCount
|
|
434
|
+
const stop = internal.scanStop
|
|
435
|
+
if (state.partial && (stop === internal.End || stop === internal.Truncated))
|
|
436
|
+
return state.incomplete(1, expected)
|
|
437
|
+
if (count < min) return backtrack(state, kind, expected, offset)
|
|
438
|
+
// More matching characters would have been accepted where we stopped
|
|
439
|
+
if (hint && count < max) state.setHint(offset, expected)
|
|
440
|
+
state.pos = offset
|
|
441
|
+
return enc.text(state.input, start, offset)
|
|
442
|
+
},
|
|
443
|
+
name,
|
|
444
|
+
{ _tag: "TakeWhile", set, negate, min, max, encoding: enc }
|
|
445
|
+
)
|
|
434
446
|
}
|
|
435
447
|
|
|
436
|
-
const any: Parser<string, never, never, I> = P.described<string, never, never, I>(
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
448
|
+
const any: Parser<string, never, never, I> = P.described<string, never, never, I>(
|
|
449
|
+
(state: State<any>) => {
|
|
450
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
451
|
+
const cp = internal.next(enc, state)
|
|
452
|
+
if (cp < 0) return internal.failAt(state, cp, "Token", expectedAny)
|
|
453
|
+
state.pos += internal.width
|
|
454
|
+
return internal.charOf(cp)
|
|
455
|
+
},
|
|
456
|
+
"any",
|
|
457
|
+
{ _tag: "Any", encoding: enc }
|
|
458
|
+
)
|
|
443
459
|
|
|
444
460
|
const literal = <const L extends string>(lit: L): Parser<L, never, never, I> => {
|
|
445
461
|
const encoded = enc.encode(lit)
|
|
@@ -448,50 +464,65 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
448
464
|
const node: Node = { _tag: "Literal", literal: lit, caseless: false, encoding: enc }
|
|
449
465
|
if (len === 1) {
|
|
450
466
|
// Single unit literals (punctuation, mostly) are compared directly
|
|
451
|
-
const unit =
|
|
452
|
-
return P.described<L, never, never, I>(
|
|
453
|
-
|
|
467
|
+
const unit = Predicate.isString(encoded) ? encoded.charCodeAt(0) : encoded[0]
|
|
468
|
+
return P.described<L, never, never, I>(
|
|
469
|
+
(state: State<any>) => {
|
|
470
|
+
const pos = state.pos
|
|
471
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
472
|
+
if (pos >= state.end) return state.eoi("Literal", expected, 1)
|
|
473
|
+
const input = state.input
|
|
474
|
+
if ((state.inputKind === 0 ? (input as string).charCodeAt(pos) : (input as Uint8Array)[pos]) !== unit) {
|
|
475
|
+
return backtrack(state, "Literal", expected)
|
|
476
|
+
}
|
|
477
|
+
state.pos = pos + 1
|
|
478
|
+
return lit
|
|
479
|
+
},
|
|
480
|
+
expected[0],
|
|
481
|
+
node
|
|
482
|
+
)
|
|
483
|
+
}
|
|
484
|
+
return P.described<L, never, never, I>(
|
|
485
|
+
(state: State<any>) => {
|
|
454
486
|
if (state.inputKind === 1) state.encoding = enc
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
if (
|
|
487
|
+
const r = matchLiteral(state, encoded, false)
|
|
488
|
+
if (r === -1) return backtrack(state, "Literal", expected)
|
|
489
|
+
if (r === -2) {
|
|
490
|
+
if (state.partial) return state.incomplete(len - (state.end - state.pos), expected)
|
|
458
491
|
return backtrack(state, "Literal", expected)
|
|
459
492
|
}
|
|
460
|
-
state.pos
|
|
493
|
+
state.pos += len
|
|
461
494
|
return lit
|
|
462
|
-
},
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
const r = matchLiteral(state, encoded, false)
|
|
467
|
-
if (r === -1) return backtrack(state, "Literal", expected)
|
|
468
|
-
if (r === -2) {
|
|
469
|
-
if (state.partial) return state.incomplete(len - (state.end - state.pos), expected)
|
|
470
|
-
return backtrack(state, "Literal", expected)
|
|
471
|
-
}
|
|
472
|
-
state.pos += len
|
|
473
|
-
return lit
|
|
474
|
-
}, expected[0], node)
|
|
495
|
+
},
|
|
496
|
+
expected[0],
|
|
497
|
+
node
|
|
498
|
+
)
|
|
475
499
|
}
|
|
476
500
|
|
|
477
501
|
const caseless = (lit: string): Parser<string, never, never, I> => {
|
|
478
|
-
const folded = Array.from(lit, (c) => internal.fold(
|
|
502
|
+
const folded = Array.from(lit, (c) => internal.fold(internal.firstCodePoint(c)))
|
|
479
503
|
const expected = [`${JSON.stringify(lit)} (case insensitive)`]
|
|
480
|
-
return P.described<string, never, never, I>(
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
504
|
+
return P.described<string, never, never, I>(
|
|
505
|
+
(state: State<any>) => {
|
|
506
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
507
|
+
const start = state.pos
|
|
508
|
+
let pos = start
|
|
509
|
+
for (let i = 0; i < folded.length; i++) {
|
|
510
|
+
const cp = internal.next(enc, state, pos)
|
|
511
|
+
if (cp === internal.End || cp === internal.Truncated) {
|
|
512
|
+
return state.partial ? state.incomplete(1, expected) : backtrack(state, "Literal", expected)
|
|
513
|
+
}
|
|
514
|
+
if (cp < 0 || internal.fold(cp) !== folded[i]) {
|
|
515
|
+
state.syntax?.read(pos + Math.max(internal.width, 1))
|
|
516
|
+
return backtrack(state, "Literal", expected)
|
|
517
|
+
}
|
|
518
|
+
pos += internal.width
|
|
488
519
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
520
|
+
state.pos = pos
|
|
521
|
+
return enc.text(state.input, start, pos)
|
|
522
|
+
},
|
|
523
|
+
expected[0],
|
|
524
|
+
{ _tag: "Literal", literal: lit, caseless: true, encoding: enc }
|
|
525
|
+
)
|
|
495
526
|
}
|
|
496
527
|
|
|
497
528
|
const oneOfImpl = (set: StringTokenSet, negate: boolean): Parser<string, never, never, I> => {
|
|
@@ -499,32 +530,40 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
499
530
|
const test = m.code
|
|
500
531
|
const expected = [negate ? `anything but ${m.description}` : m.description]
|
|
501
532
|
const kind: ErrorKind = negate ? "NoneOf" : "OneOf"
|
|
502
|
-
return P.described<string, never, never, I>(
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
533
|
+
return P.described<string, never, never, I>(
|
|
534
|
+
(state: State<any>) => {
|
|
535
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
536
|
+
const cp = internal.next(enc, state)
|
|
537
|
+
if (cp < 0) return internal.failAt(state, cp, kind, expected)
|
|
538
|
+
const w = internal.width
|
|
539
|
+
if (test(cp) === negate) return state.backtrack(kind, expected)
|
|
540
|
+
state.pos += w
|
|
541
|
+
return internal.charOf(cp)
|
|
542
|
+
},
|
|
543
|
+
expected[0],
|
|
544
|
+
{ _tag: "OneOf", set, negate, encoding: enc }
|
|
545
|
+
)
|
|
511
546
|
}
|
|
512
547
|
|
|
513
548
|
const take = (count: number): Parser<string, never, never, I> => {
|
|
514
549
|
const expected = [count === 1 ? "1 character" : `${count} characters`]
|
|
515
|
-
return P.described<string, never, never, I>(
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
550
|
+
return P.described<string, never, never, I>(
|
|
551
|
+
(state: State<any>) => {
|
|
552
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
553
|
+
const start = state.pos
|
|
554
|
+
let pos = start
|
|
555
|
+
for (let got = 0; got < count; got++) {
|
|
556
|
+
const cp = internal.next(enc, state, pos)
|
|
557
|
+
if (cp === internal.End) return state.eoi("Take", expected, count - got)
|
|
558
|
+
if (cp < 0) return internal.failAt(state, cp, "Take", expected, pos)
|
|
559
|
+
pos += internal.width
|
|
560
|
+
}
|
|
561
|
+
state.pos = pos
|
|
562
|
+
return enc.text(state.input, start, pos)
|
|
563
|
+
},
|
|
564
|
+
"take",
|
|
565
|
+
{ _tag: "Take", count, encoding: enc }
|
|
566
|
+
)
|
|
528
567
|
}
|
|
529
568
|
|
|
530
569
|
const takeUntil = (lit: string, r?: Range): Parser<string, never, never, I> => {
|
|
@@ -532,105 +571,142 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
532
571
|
const needle = enc.encode(lit)
|
|
533
572
|
const unit = enc.unit
|
|
534
573
|
const expected = [JSON.stringify(lit)]
|
|
535
|
-
return P.described<string, never, never, I>(
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
if (
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
574
|
+
return P.described<string, never, never, I>(
|
|
575
|
+
(state: State<any>) => {
|
|
576
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
577
|
+
const start = state.pos
|
|
578
|
+
let idx = indexOf(state, needle as Input, start)
|
|
579
|
+
// Multi-unit encodings: only accept matches on a character boundary
|
|
580
|
+
while (unit > 1 && idx >= 0 && (idx - start) % unit !== 0) idx = indexOf(state, needle as Input, idx + 1)
|
|
581
|
+
if (idx < 0) {
|
|
582
|
+
if (state.partial) return state.incomplete(0, expected)
|
|
583
|
+
return backtrack(state, "TakeUntil", expected, state.end)
|
|
584
|
+
}
|
|
585
|
+
// The literal was read but is not consumed
|
|
586
|
+
state.syntax?.read(idx + needle.length)
|
|
587
|
+
const count = internal.validate(enc, state, start, idx)
|
|
588
|
+
if (count < 0) return backtrack(state, "TakeUntil", expected, -1 - count)
|
|
589
|
+
// As in winnow, the first occurrence must lie within the range
|
|
590
|
+
if (count < min) return backtrack(state, "TakeUntil", expected, idx)
|
|
591
|
+
if (count > max) return backtrack(state, "TakeUntil", expected)
|
|
592
|
+
state.pos = idx
|
|
593
|
+
return enc.text(state.input, start, idx)
|
|
594
|
+
},
|
|
595
|
+
"takeUntil",
|
|
596
|
+
{ _tag: "TakeUntil", literal: lit, min, max, encoding: enc }
|
|
597
|
+
)
|
|
553
598
|
}
|
|
554
599
|
|
|
555
600
|
const always = () => true
|
|
556
|
-
const rest: Parser<string, never, never, I> = P.described<string, never, never, I>(
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
601
|
+
const rest: Parser<string, never, never, I> = P.described<string, never, never, I>(
|
|
602
|
+
(state: State<any>) => {
|
|
603
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
604
|
+
const start = state.pos
|
|
605
|
+
internal.scan(enc, state, always, false, Infinity, state.pos, fast)
|
|
606
|
+
const offset = internal.scanOffset
|
|
607
|
+
if (internal.scanStop === internal.Truncated) return state.incomplete(1, expectedAny)
|
|
608
|
+
if (internal.scanStop === internal.Invalid) return backtrack(state, "Token", expectedAny, offset)
|
|
609
|
+
state.pos = offset
|
|
610
|
+
return enc.text(state.input, start, offset)
|
|
611
|
+
},
|
|
612
|
+
"rest",
|
|
613
|
+
{ _tag: "Rest", encoding: enc }
|
|
614
|
+
)
|
|
566
615
|
|
|
567
616
|
const taken = <A, E, R>(self: Parser<A, E, R, I>): Parser<string, E, R, I> => {
|
|
568
617
|
const step = self.step
|
|
569
|
-
return P.described<string, E, R, I>(
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
618
|
+
return P.described<string, E, R, I>(
|
|
619
|
+
(state: State<any>) => {
|
|
620
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
621
|
+
const start = state.pos
|
|
622
|
+
if (step(state) === Fail) return Fail
|
|
623
|
+
return textOf(state, start, state.pos, "Slice", expectedAny)
|
|
624
|
+
},
|
|
625
|
+
self.name,
|
|
626
|
+
{ _tag: "Taken", self, encoding: enc }
|
|
627
|
+
)
|
|
575
628
|
}
|
|
576
629
|
|
|
577
630
|
const cls = (test: CharPredicate, min: 0 | 1, description: string, kind: ErrorKind, hint = true) =>
|
|
578
631
|
takeWhileText(test as any, { min }, false, `${kind.toLowerCase()}${min}`, [description], kind, hint)
|
|
579
632
|
|
|
580
633
|
const identifierStart = (cp: number) => cp === 95 || isIdStart(cp)
|
|
581
|
-
const identifier: Parser<string, never, never, I> = P.described<string, never, never, I>(
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
634
|
+
const identifier: Parser<string, never, never, I> = P.described<string, never, never, I>(
|
|
635
|
+
(state: State<any>) => {
|
|
636
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
637
|
+
const start = state.pos
|
|
638
|
+
const cp = internal.next(enc, state)
|
|
639
|
+
if (cp < 0) return internal.failAt(state, cp, "TakeWhile", expectedIdentifier)
|
|
640
|
+
if (!identifierStart(cp)) return state.backtrack("TakeWhile", expectedIdentifier)
|
|
641
|
+
internal.scan(enc, state, isIdContinue as any, false, Infinity, start + internal.width, fast)
|
|
642
|
+
const stop = internal.scanStop
|
|
643
|
+
if (state.partial && (stop === internal.End || stop === internal.Truncated)) {
|
|
644
|
+
return state.incomplete(1, expectedIdentifier)
|
|
645
|
+
}
|
|
646
|
+
state.pos = internal.scanOffset
|
|
647
|
+
return enc.text(state.input, start, state.pos)
|
|
648
|
+
},
|
|
649
|
+
"identifier",
|
|
650
|
+
{ _tag: "Identifier", encoding: enc }
|
|
651
|
+
)
|
|
595
652
|
|
|
596
653
|
// Decoded rather than matched as a literal, as not every encoding can encode it
|
|
597
|
-
const bom: Parser<boolean, never, never, I> = P.described<boolean, never, never, I>(
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
654
|
+
const bom: Parser<boolean, never, never, I> = P.described<boolean, never, never, I>(
|
|
655
|
+
(state: State<any>) => {
|
|
656
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
657
|
+
const cp = internal.next(enc, state)
|
|
658
|
+
if (cp === 0xfeff) {
|
|
659
|
+
state.pos += internal.width
|
|
660
|
+
return true
|
|
661
|
+
}
|
|
662
|
+
if (cp === internal.Truncated || (cp === internal.End && state.partial)) {
|
|
663
|
+
return state.incomplete(1, ["byte order mark"])
|
|
664
|
+
}
|
|
665
|
+
return false
|
|
666
|
+
},
|
|
667
|
+
"bom",
|
|
668
|
+
{ _tag: "Bom", encoding: enc }
|
|
669
|
+
)
|
|
609
670
|
|
|
610
671
|
const newline = literal("\n")
|
|
611
672
|
const crlf = literal("\r\n")
|
|
612
673
|
|
|
613
|
-
const tillLineEnding: Parser<string, never, never, I> = P.described<string, never, never, I>(
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
674
|
+
const tillLineEnding: Parser<string, never, never, I> = P.described<string, never, never, I>(
|
|
675
|
+
(state: State<any>) => {
|
|
676
|
+
if (state.inputKind === 1) state.encoding = enc
|
|
677
|
+
const start = state.pos
|
|
678
|
+
internal.scan(enc, state, isLineBreak, true, Infinity, state.pos, fast)
|
|
679
|
+
const offset = internal.scanOffset
|
|
680
|
+
const stop = internal.scanStop
|
|
681
|
+
if (stop === internal.Truncated || (stop === internal.End && state.partial)) {
|
|
682
|
+
return state.incomplete(1, expectedLineEnding)
|
|
683
|
+
}
|
|
684
|
+
if (stop === internal.Invalid) return backtrack(state, "LineEnding", expectedLineEnding, offset)
|
|
685
|
+
if (stop === 0 && internal.next(enc, state, offset) === 13) {
|
|
686
|
+
const cr = internal.width
|
|
687
|
+
// The line feed after it is read, not consumed
|
|
688
|
+
state.syntax?.read(offset + 2 * cr)
|
|
689
|
+
const after = internal.next(enc, state, offset + cr)
|
|
690
|
+
if (after === internal.End && state.partial) return state.incomplete(1, expectedLineEnding)
|
|
691
|
+
if (after !== 10) return backtrack(state, "LineEnding", expectedLineEnding, offset)
|
|
692
|
+
}
|
|
693
|
+
state.pos = offset
|
|
694
|
+
return enc.text(state.input, start, offset)
|
|
695
|
+
},
|
|
696
|
+
"tillLineEnding",
|
|
697
|
+
{ _tag: "TillLineEnding", encoding: enc }
|
|
698
|
+
)
|
|
631
699
|
|
|
632
700
|
const asciiDigits = takeWhileText(isAsciiDigit, { min: 1 }, false, "digit1", ["digit"], "Digit", true)
|
|
633
|
-
const hexDigits = takeWhileText(
|
|
701
|
+
const hexDigits = takeWhileText(
|
|
702
|
+
isAsciiHexDigit,
|
|
703
|
+
{ min: 1 },
|
|
704
|
+
false,
|
|
705
|
+
"hexDigit1",
|
|
706
|
+
["hexadecimal digit"],
|
|
707
|
+
"HexDigit",
|
|
708
|
+
true
|
|
709
|
+
)
|
|
634
710
|
const sign = P.opt(oneOfImpl("+-", false))
|
|
635
711
|
const signed = taken(P.seq(sign, asciiDigits))
|
|
636
712
|
|
|
@@ -643,7 +719,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
643
719
|
const floatText = markFloatText(taken(P.alt(caseless("nan"), P.seq(sign, unsignedFloat))).pipe(P.expected("number")))
|
|
644
720
|
|
|
645
721
|
const matchControl = (control: string) => {
|
|
646
|
-
const ctrl = control.codePointAt(0)
|
|
722
|
+
const ctrl = control.codePointAt(0)
|
|
647
723
|
return (state: State<any>): boolean => {
|
|
648
724
|
if (internal.next(enc, state) !== ctrl) return false
|
|
649
725
|
state.pos += internal.width
|
|
@@ -687,11 +763,20 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
687
763
|
tab: literal("\t"),
|
|
688
764
|
lineEnding: P.alt(newline, crlf).pipe(P.expected("line ending")),
|
|
689
765
|
tillLineEnding,
|
|
690
|
-
decUint: asciiDigits.pipe(
|
|
691
|
-
|
|
766
|
+
decUint: asciiDigits.pipe(
|
|
767
|
+
P.tryMap((s) => overflow(Number(s))),
|
|
768
|
+
P.named("decUint")
|
|
769
|
+
),
|
|
770
|
+
decInt: signed.pipe(
|
|
771
|
+
P.tryMap((s) => overflow(Number(s))),
|
|
772
|
+
P.named("decInt")
|
|
773
|
+
),
|
|
692
774
|
decBigUint: asciiDigits.pipe(P.map((s) => BigInt(s))),
|
|
693
775
|
decBigInt: signed.pipe(P.map((s) => BigInt(s.startsWith("+") ? s.slice(1) : s))),
|
|
694
|
-
hexUint: hexDigits.pipe(
|
|
776
|
+
hexUint: hexDigits.pipe(
|
|
777
|
+
P.tryMap((s) => overflow(parseInt(s, 16))),
|
|
778
|
+
P.named("hexUint")
|
|
779
|
+
),
|
|
695
780
|
float: floatText.pipe(P.map(toFloat), P.named("float")),
|
|
696
781
|
takeEscaped: (normal, control, escapable) =>
|
|
697
782
|
takeEscapedImpl(
|
|
@@ -699,11 +784,11 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
699
784
|
matchControl(control),
|
|
700
785
|
escapable,
|
|
701
786
|
(state, start) => enc.text(state.input, start, state.pos),
|
|
702
|
-
|
|
787
|
+
internal.firstCodePoint(control),
|
|
703
788
|
enc
|
|
704
789
|
),
|
|
705
790
|
escaped: (normal, control, escape) =>
|
|
706
|
-
escapedImpl(normal, matchControl(control), escape,
|
|
791
|
+
escapedImpl(normal, matchControl(control), escape, internal.firstCodePoint(control), enc)
|
|
707
792
|
}
|
|
708
793
|
}
|
|
709
794
|
|
|
@@ -713,7 +798,7 @@ export const make = <I extends string | Uint8Array>(encoding: Encoding<I>): Text
|
|
|
713
798
|
* @since 0.1.0
|
|
714
799
|
* @category instances
|
|
715
800
|
*/
|
|
716
|
-
export const string: TextParsers<string> = make(Encodings.string)
|
|
801
|
+
export const string: TextParsers<string> = /*#__PURE__*/ make(Encodings.string)
|
|
717
802
|
|
|
718
803
|
/**
|
|
719
804
|
* Text parsers for UTF-8 encoded bytes.
|
|
@@ -730,7 +815,7 @@ export const string: TextParsers<string> = make(Encodings.string)
|
|
|
730
815
|
* @since 0.1.0
|
|
731
816
|
* @category instances
|
|
732
817
|
*/
|
|
733
|
-
export const utf8: TextParsers<Uint8Array> = make(Encodings.utf8)
|
|
818
|
+
export const utf8: TextParsers<Uint8Array> = /*#__PURE__*/ make(Encodings.utf8)
|
|
734
819
|
|
|
735
820
|
/**
|
|
736
821
|
* Text parsers for UTF-16 little endian bytes.
|
|
@@ -738,7 +823,7 @@ export const utf8: TextParsers<Uint8Array> = make(Encodings.utf8)
|
|
|
738
823
|
* @since 0.1.0
|
|
739
824
|
* @category instances
|
|
740
825
|
*/
|
|
741
|
-
export const utf16le: TextParsers<Uint8Array> = make(Encodings.utf16le)
|
|
826
|
+
export const utf16le: TextParsers<Uint8Array> = /*#__PURE__*/ make(Encodings.utf16le)
|
|
742
827
|
|
|
743
828
|
/**
|
|
744
829
|
* Text parsers for UTF-16 big endian bytes.
|
|
@@ -746,7 +831,7 @@ export const utf16le: TextParsers<Uint8Array> = make(Encodings.utf16le)
|
|
|
746
831
|
* @since 0.1.0
|
|
747
832
|
* @category instances
|
|
748
833
|
*/
|
|
749
|
-
export const utf16be: TextParsers<Uint8Array> = make(Encodings.utf16be)
|
|
834
|
+
export const utf16be: TextParsers<Uint8Array> = /*#__PURE__*/ make(Encodings.utf16be)
|
|
750
835
|
|
|
751
836
|
/**
|
|
752
837
|
* Text parsers for ISO-8859-1 (Latin-1) bytes.
|
|
@@ -754,4 +839,4 @@ export const utf16be: TextParsers<Uint8Array> = make(Encodings.utf16be)
|
|
|
754
839
|
* @since 0.1.0
|
|
755
840
|
* @category instances
|
|
756
841
|
*/
|
|
757
|
-
export const latin1: TextParsers<Uint8Array> = make(Encodings.latin1)
|
|
842
|
+
export const latin1: TextParsers<Uint8Array> = /*#__PURE__*/ make(Encodings.latin1)
|