@thomasfosterau/effect-parse 0.0.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/Encoding.js CHANGED
@@ -1,85 +1,86 @@
1
- /**
2
- * Text encodings for the `Text` module.
3
- *
4
- * An {@link Encoding} tells the `Text` parsers how to read Unicode code
5
- * points out of an input. JavaScript strings are read natively, without any
6
- * conversion. Byte inputs are decoded as they are parsed, so offsets stay
7
- * byte offsets, slices that are kept as bytes (`Parser.taken`) are
8
- * zero-copy views, and partial input that ends in the middle of a character
9
- * reports `Incomplete`.
10
- *
11
- * ```ts
12
- * import { Encoding, Text } from "@thomasfosterau/effect-parse"
13
- *
14
- * Text.utf8.encoding === Encoding.utf8
15
- * Text.make(Encoding.latin1) // the Text parsers for any Encoding, including your own
16
- * ```
17
- *
18
- * @since 0.1.0
19
- */
20
1
  import * as Option from "effect/Option";
21
2
  import * as internal from "./internal/text.js";
3
+ //#region src/Encoding.ts
4
+ /**
5
+ * Text encodings for the `Text` module.
6
+ *
7
+ * An {@link Encoding} tells the `Text` parsers how to read Unicode code
8
+ * points out of an input. JavaScript strings are read natively, without any
9
+ * conversion. Byte inputs are decoded as they are parsed, so offsets stay
10
+ * byte offsets, slices that are kept as bytes (`Parser.taken`) are
11
+ * zero-copy views, and partial input that ends in the middle of a character
12
+ * reports `Incomplete`.
13
+ *
14
+ * ```ts
15
+ * import { Encoding, Text } from "@thomasfosterau/effect-parse"
16
+ *
17
+ * Text.utf8.encoding === Encoding.utf8
18
+ * Text.make(Encoding.latin1) // the Text parsers for any Encoding, including your own
19
+ * ```
20
+ *
21
+ * @since 0.1.0
22
+ */
22
23
  /**
23
- * JavaScript strings, read as UTF-16 code units. Offsets are code-unit
24
- * indices and slices are plain `String.prototype.slice`s. Unpaired
25
- * surrogates are malformed.
26
- *
27
- * @since 0.1.0
28
- * @category encodings
29
- */
30
- export const string = internal.string;
24
+ * JavaScript strings, read as UTF-16 code units. Offsets are code-unit
25
+ * indices and slices are plain `String.prototype.slice`s. Unpaired
26
+ * surrogates are malformed.
27
+ *
28
+ * @since 0.1.0
29
+ * @category encodings
30
+ */
31
+ const string = internal.string;
31
32
  /**
32
- * UTF-8 bytes. Overlong encodings, surrogates and code points above
33
- * U+10FFFF are malformed.
34
- *
35
- * @since 0.1.0
36
- * @category encodings
37
- */
38
- export const utf8 = internal.utf8;
33
+ * UTF-8 bytes. Overlong encodings, surrogates and code points above
34
+ * U+10FFFF are malformed.
35
+ *
36
+ * @since 0.1.0
37
+ * @category encodings
38
+ */
39
+ const utf8 = internal.utf8;
39
40
  /**
40
- * UTF-16 bytes, little endian. Unpaired surrogates are malformed.
41
- *
42
- * @since 0.1.0
43
- * @category encodings
44
- */
45
- export const utf16le = internal.utf16le;
41
+ * UTF-16 bytes, little endian. Unpaired surrogates are malformed.
42
+ *
43
+ * @since 0.1.0
44
+ * @category encodings
45
+ */
46
+ const utf16le = internal.utf16le;
46
47
  /**
47
- * UTF-16 bytes, big endian. Unpaired surrogates are malformed.
48
- *
49
- * @since 0.1.0
50
- * @category encodings
51
- */
52
- export const utf16be = internal.utf16be;
48
+ * UTF-16 bytes, big endian. Unpaired surrogates are malformed.
49
+ *
50
+ * @since 0.1.0
51
+ * @category encodings
52
+ */
53
+ const utf16be = internal.utf16be;
53
54
  /**
54
- * ISO-8859-1 (Latin-1) bytes: each byte is the code point U+0000 to U+00FF
55
- * of the same value.
56
- *
57
- * @since 0.1.0
58
- * @category encodings
59
- */
60
- export const latin1 = internal.latin1;
55
+ * ISO-8859-1 (Latin-1) bytes: each byte is the code point U+0000 to U+00FF
56
+ * of the same value.
57
+ *
58
+ * @since 0.1.0
59
+ * @category encodings
60
+ */
61
+ const latin1 = internal.latin1;
61
62
  /**
62
- * Detects the encoding of bytes from a byte order mark: UTF-8
63
- * (`EF BB BF`), UTF-16LE (`FF FE`) or UTF-16BE (`FE FF`). The mark itself
64
- * is not skipped; parse it with `Text.bom`.
65
- *
66
- * @example
67
- * ```ts
68
- * import { Encoding } from "@thomasfosterau/effect-parse"
69
- *
70
- * Encoding.sniff(new Uint8Array([0xff, 0xfe, 0x41, 0x00])) // Option.some(Encoding.utf16le)
71
- * ```
72
- *
73
- * @since 0.1.0
74
- * @category utils
75
- */
76
- export const sniff = (bytes) => {
77
- if (bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf)
78
- return Option.some(utf8);
79
- if (bytes[0] === 0xff && bytes[1] === 0xfe)
80
- return Option.some(utf16le);
81
- if (bytes[0] === 0xfe && bytes[1] === 0xff)
82
- return Option.some(utf16be);
83
- return Option.none();
63
+ * Detects the encoding of bytes from a byte order mark: UTF-8
64
+ * (`EF BB BF`), UTF-16LE (`FF FE`) or UTF-16BE (`FE FF`). The mark itself
65
+ * is not skipped; parse it with `Text.bom`.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * import { Encoding } from "@thomasfosterau/effect-parse"
70
+ *
71
+ * Encoding.sniff(new Uint8Array([0xff, 0xfe, 0x41, 0x00])) // Option.some(Encoding.utf16le)
72
+ * ```
73
+ *
74
+ * @since 0.1.0
75
+ * @category utils
76
+ */
77
+ const sniff = (bytes) => {
78
+ if (bytes[0] === 239 && bytes[1] === 187 && bytes[2] === 191) return Option.some(utf8);
79
+ if (bytes[0] === 255 && bytes[1] === 254) return Option.some(utf16le);
80
+ if (bytes[0] === 254 && bytes[1] === 255) return Option.some(utf16be);
81
+ return Option.none();
84
82
  };
83
+ //#endregion
84
+ export { latin1, sniff, string, utf16be, utf16le, utf8 };
85
+
85
86
  //# sourceMappingURL=Encoding.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Encoding.js","sourceRoot":"","sources":["../src/Encoding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,QAAQ,MAAM,oBAAoB,CAAA;AA2C9C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,MAAM,GAAqB,QAAQ,CAAC,MAAM,CAAA;AAEvD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAAyB,QAAQ,CAAC,IAAI,CAAA;AAEvD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAyB,QAAQ,CAAC,OAAO,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAyB,QAAQ,CAAC,OAAO,CAAA;AAE7D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,MAAM,GAAyB,QAAQ,CAAC,MAAM,CAAA;AAE3D;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAiB,EAAuC,EAAE;IAC9E,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzF,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACvE,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACvE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;AACtB,CAAC,CAAA"}
1
+ {"version":3,"file":"Encoding.js","names":[],"sources":["../src/Encoding.ts"],"sourcesContent":["/**\n * Text encodings for the `Text` module.\n *\n * An {@link Encoding} tells the `Text` parsers how to read Unicode code\n * points out of an input. JavaScript strings are read natively, without any\n * conversion. Byte inputs are decoded as they are parsed, so offsets stay\n * byte offsets, slices that are kept as bytes (`Parser.taken`) are\n * zero-copy views, and partial input that ends in the middle of a character\n * reports `Incomplete`.\n *\n * ```ts\n * import { Encoding, Text } from \"@thomasfosterau/effect-parse\"\n *\n * Text.utf8.encoding === Encoding.utf8\n * Text.make(Encoding.latin1) // the Text parsers for any Encoding, including your own\n * ```\n *\n * @since 0.1.0\n */\nimport * as Option from \"effect/Option\"\nimport * as internal from \"./internal/text.js\"\n\n/**\n * A text encoding: how to read Unicode code points out of an input. The\n * `Text` module is generic over encodings, so one grammar can parse\n * JavaScript strings, UTF-8 bytes, UTF-16 bytes and so on.\n *\n * Decoding is strict: malformed sequences (invalid UTF-8, unpaired UTF-16\n * surrogates) are reported as invalid, never replaced.\n *\n * @since 0.1.0\n * @category models\n */\nexport interface Encoding<I extends string | Uint8Array = string | Uint8Array> {\n /** The name of the encoding, e.g. `\"UTF-8\"`. Used in error messages. */\n readonly name: string\n /**\n * The size of a code unit, in input units: 1 for strings, UTF-8 and\n * Latin-1, 2 for UTF-16 bytes. Code points start at multiples of it.\n */\n readonly unit: number\n /**\n * Whether every input unit below `0x80` encodes the ASCII character with\n * that value, and is never part of a longer sequence. Enables fast paths.\n */\n readonly asciiCompatible: boolean\n /**\n * Decodes the code point starting at `offset` (with `offset < end`).\n * Returns the code point, `-1` if the input is malformed there, or `-2` if\n * the input ends inside a sequence (more input could complete it).\n */\n readonly decode: (input: I, offset: number, end: number) => number\n /** The number of input units that encode a code point. */\n readonly width: (codePoint: number) => number\n /** Encodes a string. Throws if the string can't be represented. */\n readonly encode: (text: string) => I\n /**\n * Decodes the units `[start, end)` to a string. The parsers only call it\n * on ranges they have checked are well formed.\n */\n readonly text: (input: I, start: number, end: number) => string\n}\n\n/**\n * JavaScript strings, read as UTF-16 code units. Offsets are code-unit\n * indices and slices are plain `String.prototype.slice`s. Unpaired\n * surrogates are malformed.\n *\n * @since 0.1.0\n * @category encodings\n */\nexport const string: Encoding<string> = internal.string\n\n/**\n * UTF-8 bytes. Overlong encodings, surrogates and code points above\n * U+10FFFF are malformed.\n *\n * @since 0.1.0\n * @category encodings\n */\nexport const utf8: Encoding<Uint8Array> = internal.utf8\n\n/**\n * UTF-16 bytes, little endian. Unpaired surrogates are malformed.\n *\n * @since 0.1.0\n * @category encodings\n */\nexport const utf16le: Encoding<Uint8Array> = internal.utf16le\n\n/**\n * UTF-16 bytes, big endian. Unpaired surrogates are malformed.\n *\n * @since 0.1.0\n * @category encodings\n */\nexport const utf16be: Encoding<Uint8Array> = internal.utf16be\n\n/**\n * ISO-8859-1 (Latin-1) bytes: each byte is the code point U+0000 to U+00FF\n * of the same value.\n *\n * @since 0.1.0\n * @category encodings\n */\nexport const latin1: Encoding<Uint8Array> = internal.latin1\n\n/**\n * Detects the encoding of bytes from a byte order mark: UTF-8\n * (`EF BB BF`), UTF-16LE (`FF FE`) or UTF-16BE (`FE FF`). The mark itself\n * is not skipped; parse it with `Text.bom`.\n *\n * @example\n * ```ts\n * import { Encoding } from \"@thomasfosterau/effect-parse\"\n *\n * Encoding.sniff(new Uint8Array([0xff, 0xfe, 0x41, 0x00])) // Option.some(Encoding.utf16le)\n * ```\n *\n * @since 0.1.0\n * @category utils\n */\nexport const sniff = (bytes: Uint8Array): Option.Option<Encoding<Uint8Array>> => {\n if (bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf) return Option.some(utf8)\n if (bytes[0] === 0xff && bytes[1] === 0xfe) return Option.some(utf16le)\n if (bytes[0] === 0xfe && bytes[1] === 0xff) return Option.some(utf16be)\n return Option.none()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuEA,MAAa,SAA2B,SAAS;;;;;;;;AASjD,MAAa,OAA6B,SAAS;;;;;;;AAQnD,MAAa,UAAgC,SAAS;;;;;;;AAQtD,MAAa,UAAgC,SAAS;;;;;;;;AAStD,MAAa,SAA+B,SAAS;;;;;;;;;;;;;;;;AAiBrD,MAAa,SAAS,UAA2D;CAC/E,IAAI,MAAM,OAAO,OAAQ,MAAM,OAAO,OAAQ,MAAM,OAAO,KAAM,OAAO,OAAO,KAAK,IAAI;CACxF,IAAI,MAAM,OAAO,OAAQ,MAAM,OAAO,KAAM,OAAO,OAAO,KAAK,OAAO;CACtE,IAAI,MAAM,OAAO,OAAQ,MAAM,OAAO,KAAM,OAAO,OAAO,KAAK,OAAO;CACtE,OAAO,OAAO,KAAK;AACrB"}
@@ -1,41 +1,6 @@
1
- /**
2
- * Operator-precedence expression parsing with a Pratt parser (from
3
- * `nom-language`'s `precedence`, and winnow's expression parser).
4
- *
5
- * Describe the operand parser and a table of prefix, postfix and infix
6
- * operators with their precedence (higher binds tighter) and associativity.
7
- * Each operator carries a function that folds its operands into a result.
8
- *
9
- * @example
10
- * ```ts
11
- * import { Ascii, Expression, Parser, Token } from "@thomasfosterau/effect-parse"
12
- *
13
- * const op = (s: string) => Parser.delimited(Ascii.space0, Token.literal(s), Ascii.space0)
14
- *
15
- * const arithmetic: Parser.Parser<number, string> = Expression.make({
16
- * operand: Parser.alt(
17
- * Ascii.decInt,
18
- * Parser.delimited(op("("), Parser.suspend(() => arithmetic), op(")"))
19
- * ),
20
- * operators: [
21
- * Expression.prefix(op("-"), 4, (_, x) => -x),
22
- * Expression.postfix(op("!"), 5, (x) => factorial(x)),
23
- * Expression.infixRight(op("^"), 3, (l, _, r) => l ** r),
24
- * Expression.infixLeft(op("*"), 2, (l, _, r) => l * r),
25
- * Expression.infixLeft(op("/"), 2, (l, _, r) => l / r),
26
- * Expression.infixLeft(op("+"), 1, (l, _, r) => l + r),
27
- * Expression.infixLeft(op("-"), 1, (l, _, r) => l - r)
28
- * ]
29
- * })
30
- *
31
- * declare const factorial: (n: number) => number
32
- * Parser.parse(arithmetic, "1 + 2 * 3 ^ 2") // Result.succeed(19)
33
- * ```
34
- *
35
- * @since 0.1.0
36
- */
37
- import type { Input } from "./Input.js";
38
- import type { Parser } from "./Parser.js";
1
+ import { Input } from "./Input.js";
2
+ import { Parser } from "./Parser.js";
3
+ //#region src/Expression.d.ts
39
4
  /**
40
5
  * An operator in an expression grammar.
41
6
  *
@@ -44,33 +9,33 @@ import type { Parser } from "./Parser.js";
44
9
  */
45
10
  export type Operator<A, E = never, R = never, I extends Input = string> = Prefix<A, E, R, I> | Postfix<A, E, R, I> | Infix<A, E, R, I>;
46
11
  interface OperatorBase<E, R, I extends Input> {
47
- readonly parser: Parser<unknown, E, R, I>;
48
- readonly precedence: number;
12
+ readonly parser: Parser<unknown, E, R, I>;
13
+ readonly precedence: number;
49
14
  }
50
15
  /**
51
16
  * @since 0.1.0
52
17
  * @category models
53
18
  */
54
19
  export interface Prefix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {
55
- readonly _tag: "Prefix";
56
- readonly fold: (op: any, operand: A) => A;
20
+ readonly _tag: "Prefix";
21
+ readonly fold: (op: any, operand: A) => A;
57
22
  }
58
23
  /**
59
24
  * @since 0.1.0
60
25
  * @category models
61
26
  */
62
27
  export interface Postfix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {
63
- readonly _tag: "Postfix";
64
- readonly fold: (operand: A, op: any) => A;
28
+ readonly _tag: "Postfix";
29
+ readonly fold: (operand: A, op: any) => A;
65
30
  }
66
31
  /**
67
32
  * @since 0.1.0
68
33
  * @category models
69
34
  */
70
35
  export interface Infix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {
71
- readonly _tag: "Infix";
72
- readonly associativity: "left" | "right";
73
- readonly fold: (left: A, op: any, right: A) => A;
36
+ readonly _tag: "Infix";
37
+ readonly associativity: "left" | "right";
38
+ readonly fold: (left: A, op: any, right: A) => A;
74
39
  }
75
40
  /**
76
41
  * A prefix operator, e.g. unary minus.
@@ -117,8 +82,9 @@ type OpInput<Op> = [Op] extends [never] ? Input : [Op] extends [OperatorBase<inf
117
82
  * @category constructors
118
83
  */
119
84
  export declare const make: <A, E, R, I extends Input, const Ops extends ReadonlyArray<Operator<A, any, any, any>>>(options: {
120
- readonly operand: Parser<A, E, R, I>;
121
- readonly operators: Ops;
85
+ readonly operand: Parser<A, E, R, I>;
86
+ readonly operators: Ops;
122
87
  }) => Parser<A, E | OpError<Ops[number]>, R | OpServices<Ops[number]>, I & OpInput<Ops[number]>>;
88
+ //#endregion
123
89
  export {};
124
90
  //# sourceMappingURL=Expression.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Expression.d.ts","sourceRoot":"","sources":["../src/Expression.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Expression.d.ts","names":[],"sources":["../src/Expression.ts"],"mappings":";;;;;;;;;YAgDY,SAAS,GAAG,WAAW,WAAW,UAAU,kBACpD,OAAO,GAAG,GAAG,GAAG,KAChB,QAAQ,GAAG,GAAG,GAAG,KACjB,MAAM,GAAG,GAAG,GAAG;UAET,aAAa,GAAG,GAAG,UAAU;WAC5B,QAAQ,gBAAgB,GAAG,GAAG;WAC9B;;;;;;iBAOM,OAAO,GAAG,WAAW,WAAW,UAAU,wBAAwB,aAAa,GAAG,GAAG;WAC3F;WACA,OAAO,SAAS,SAAS,MAAM;;;;;;iBAOzB,QAAQ,GAAG,WAAW,WAAW,UAAU,wBAAwB,aAAa,GAAG,GAAG;WAC5F;WACA,OAAO,SAAS,GAAG,YAAY;;;;;;iBAOzB,MAAM,GAAG,WAAW,WAAW,UAAU,wBAAwB,aAAa,GAAG,GAAG;WAC1F;WACA;WACA,OAAO,MAAM,GAAG,SAAS,OAAO,MAAM;;;;;;;;qBASpC,SAAU,GAAG,GAAG,GAAG,UAAU,OAAO,GAC/C,QAAQ,OAAO,GAAG,GAAG,GAAG,IACxB,oBACA,OAAO,IAAI,GAAG,SAAS,MAAM,MAC5B,OAAO,GAAG,GAAG,GAAG;;;;;;;qBAQN,UAAW,GAAG,GAAG,GAAG,UAAU,OAAO,GAChD,QAAQ,OAAO,GAAG,GAAG,GAAG,IACxB,oBACA,OAAO,SAAS,GAAG,IAAI,MAAM,MAC5B,QAAQ,GAAG,GAAG,GAAG;;;;;;;qBAQP,YAAa,GAAG,GAAG,GAAG,UAAU,OAAO,GAClD,QAAQ,OAAO,GAAG,GAAG,GAAG,IACxB,oBACA,OAAO,MAAM,GAAG,IAAI,GAAG,OAAO,MAAM,MACnC,MAAM,GAAG,GAAG,GAAG;;;;;;;qBAQL,aAAc,GAAG,GAAG,GAAG,UAAU,OAAO,GACnD,QAAQ,OAAO,GAAG,GAAG,GAAG,IACxB,oBACA,OAAO,MAAM,GAAG,IAAI,GAAG,OAAO,MAAM,MACnC,MAAM,GAAG,GAAG,GAAG;KAEb,QAAQ,MAAM,WAAW,mBAAmB,SAAS,UAAU,MAAM;KACrE,WAAW,MAAM,WAAW,mBAAmB,UAAU,SAAS,MAAM;KACxE,QAAQ,OAAO,sBAAsB,SAAS,aAAa,mBAAmB,UAAU,UAAU,MAAM;;;;;;;;;;;;;;qBAehG,OAAQ,GAAG,GAAG,GAAG,UAAU,aAAa,YAAY,cAAc,SAAS,oBAAoB;WACjG,SAAS,OAAO,GAAG,GAAG,GAAG;WACzB,WAAW;MAClB,OAAO,GAAG,IAAI,QAAQ,cAAc,IAAI,WAAW,cAAc,IAAI,QAAQ"}
@@ -1,139 +1,151 @@
1
1
  import { Fail, mergeFailures } from "./Input.js";
2
- import { make as makeParser } from "./Parser.js";
2
+ import { make as make$1 } from "./Parser.js";
3
+ //#region src/Expression.ts
3
4
  /**
4
- * A prefix operator, e.g. unary minus.
5
- *
6
- * @since 0.1.0
7
- * @category operators
8
- */
9
- export const prefix = (parser, precedence, fold) => ({ _tag: "Prefix", parser, precedence, fold });
5
+ * A prefix operator, e.g. unary minus.
6
+ *
7
+ * @since 0.1.0
8
+ * @category operators
9
+ */
10
+ const prefix = (parser, precedence, fold) => ({
11
+ _tag: "Prefix",
12
+ parser,
13
+ precedence,
14
+ fold
15
+ });
10
16
  /**
11
- * A postfix operator, e.g. factorial or a function call suffix.
12
- *
13
- * @since 0.1.0
14
- * @category operators
15
- */
16
- export const postfix = (parser, precedence, fold) => ({ _tag: "Postfix", parser, precedence, fold });
17
+ * A postfix operator, e.g. factorial or a function call suffix.
18
+ *
19
+ * @since 0.1.0
20
+ * @category operators
21
+ */
22
+ const postfix = (parser, precedence, fold) => ({
23
+ _tag: "Postfix",
24
+ parser,
25
+ precedence,
26
+ fold
27
+ });
17
28
  /**
18
- * A left-associative infix operator: `a - b - c` is `(a - b) - c`.
19
- *
20
- * @since 0.1.0
21
- * @category operators
22
- */
23
- export const infixLeft = (parser, precedence, fold) => ({ _tag: "Infix", associativity: "left", parser, precedence, fold });
29
+ * A left-associative infix operator: `a - b - c` is `(a - b) - c`.
30
+ *
31
+ * @since 0.1.0
32
+ * @category operators
33
+ */
34
+ const infixLeft = (parser, precedence, fold) => ({
35
+ _tag: "Infix",
36
+ associativity: "left",
37
+ parser,
38
+ precedence,
39
+ fold
40
+ });
24
41
  /**
25
- * A right-associative infix operator: `a ^ b ^ c` is `a ^ (b ^ c)`.
26
- *
27
- * @since 0.1.0
28
- * @category operators
29
- */
30
- export const infixRight = (parser, precedence, fold) => ({ _tag: "Infix", associativity: "right", parser, precedence, fold });
42
+ * A right-associative infix operator: `a ^ b ^ c` is `a ^ (b ^ c)`.
43
+ *
44
+ * @since 0.1.0
45
+ * @category operators
46
+ */
47
+ const infixRight = (parser, precedence, fold) => ({
48
+ _tag: "Infix",
49
+ associativity: "right",
50
+ parser,
51
+ precedence,
52
+ fold
53
+ });
31
54
  /**
32
- * Builds an expression parser from an operand parser and an operator table.
33
- *
34
- * Precedences are compared numerically: higher binds tighter. A prefix
35
- * operator applies to everything that binds tighter than it, so with `-`
36
- * at precedence 4 and `^` at 3, `-2 ^ 2` parses as `(-2) ^ 2`.
37
- *
38
- * When several operators of the same kind match, the first one in the
39
- * table wins, so list longer operators (`<=`) before their prefixes (`<`).
40
- *
41
- * @since 0.1.0
42
- * @category constructors
43
- */
44
- export const make = (options) => {
45
- const operand = options.operand.step;
46
- const prefixes = options.operators.filter((o) => o._tag === "Prefix");
47
- const postfixes = options.operators.filter((o) => o._tag === "Postfix");
48
- const infixes = options.operators.filter((o) => o._tag === "Infix");
49
- // Attempts each operator in turn. Returns the index of the first match
50
- // (with its output in `matched`), -1 if none matched, or -2 on a fatal
51
- // failure. Expectations of failed attempts are accumulated in `failure`.
52
- let matched;
53
- let failure;
54
- const tryOps = (state, ops, mustConsume) => {
55
- const start = state.pos;
56
- for (let i = 0; i < ops.length; i++) {
57
- const out = ops[i].parser.step(state);
58
- if (out !== Fail) {
59
- // A prefix or postfix operator matching nothing would apply forever
60
- if (mustConsume && state.pos === start) {
61
- state.failMessage("Cut", "Assert", "prefix and postfix operators must always consume");
62
- return -2;
63
- }
64
- matched = out;
65
- return i;
66
- }
67
- if (state.mode !== "Backtrack")
68
- return -2;
69
- failure = failure === undefined ? state.failure : mergeFailures(failure, state.failure);
70
- state.pos = start;
71
- }
72
- return -1;
73
- };
74
- const expr = (state, minPower) => {
75
- let lhs;
76
- failure = undefined;
77
- const p = tryOps(state, prefixes, true);
78
- if (p === -2)
79
- return Fail;
80
- if (p >= 0) {
81
- const op = prefixes[p];
82
- const opOut = matched;
83
- const operandValue = expr(state, op.precedence * 2);
84
- if (operandValue === Fail)
85
- return Fail;
86
- lhs = op.fold(opOut, operandValue);
87
- }
88
- else {
89
- const prefixFailure = failure;
90
- lhs = operand(state);
91
- if (lhs === Fail) {
92
- if (prefixFailure !== undefined && state.mode === "Backtrack") {
93
- state.failWith("Backtrack", mergeFailures(prefixFailure, state.failure));
94
- }
95
- return Fail;
96
- }
97
- }
98
- while (true) {
99
- const start = state.pos;
100
- failure = undefined;
101
- const q = tryOps(state, postfixes, true);
102
- if (q === -2)
103
- return Fail;
104
- if (q >= 0) {
105
- const op = postfixes[q];
106
- if (op.precedence * 2 < minPower) {
107
- state.pos = start;
108
- break;
109
- }
110
- lhs = op.fold(lhs, matched);
111
- continue;
112
- }
113
- const postfixFailure = failure;
114
- const i = tryOps(state, infixes, false);
115
- if (i === -2)
116
- return Fail;
117
- if (i < 0) {
118
- const f = postfixFailure === undefined ? failure : failure === undefined ? postfixFailure : mergeFailures(postfixFailure, failure);
119
- if (f !== undefined && f.offset === state.pos)
120
- state.setHint(f.offset, f.expected);
121
- break;
122
- }
123
- const op = infixes[i];
124
- const leftPower = op.precedence * 2;
125
- if (leftPower < minPower) {
126
- state.pos = start;
127
- break;
128
- }
129
- const opOut = matched;
130
- const rhs = expr(state, op.associativity === "left" ? leftPower + 1 : leftPower);
131
- if (rhs === Fail)
132
- return Fail;
133
- lhs = op.fold(lhs, opOut, rhs);
134
- }
135
- return lhs;
136
- };
137
- return makeParser((state) => expr(state, 0), "expression");
55
+ * Builds an expression parser from an operand parser and an operator table.
56
+ *
57
+ * Precedences are compared numerically: higher binds tighter. A prefix
58
+ * operator applies to everything that binds tighter than it, so with `-`
59
+ * at precedence 4 and `^` at 3, `-2 ^ 2` parses as `(-2) ^ 2`.
60
+ *
61
+ * When several operators of the same kind match, the first one in the
62
+ * table wins, so list longer operators (`<=`) before their prefixes (`<`).
63
+ *
64
+ * @since 0.1.0
65
+ * @category constructors
66
+ */
67
+ const make = (options) => {
68
+ const operand = options.operand.step;
69
+ const prefixes = options.operators.filter((o) => o._tag === "Prefix");
70
+ const postfixes = options.operators.filter((o) => o._tag === "Postfix");
71
+ const infixes = options.operators.filter((o) => o._tag === "Infix");
72
+ let matched;
73
+ let failure;
74
+ const tryOps = (state, ops, mustConsume) => {
75
+ const start = state.pos;
76
+ for (let i = 0; i < ops.length; i++) {
77
+ const out = ops[i].parser.step(state);
78
+ if (out !== Fail) {
79
+ if (mustConsume && state.pos === start) {
80
+ state.failMessage("Cut", "Assert", "prefix and postfix operators must always consume");
81
+ return -2;
82
+ }
83
+ matched = out;
84
+ return i;
85
+ }
86
+ if (state.mode !== "Backtrack") return -2;
87
+ failure = failure === void 0 ? state.failure : mergeFailures(failure, state.failure);
88
+ state.pos = start;
89
+ }
90
+ return -1;
91
+ };
92
+ const expr = (state, minPower) => {
93
+ let lhs;
94
+ failure = void 0;
95
+ const p = tryOps(state, prefixes, true);
96
+ if (p === -2) return Fail;
97
+ if (p >= 0) {
98
+ const op = prefixes[p];
99
+ const opOut = matched;
100
+ const operandValue = expr(state, op.precedence * 2);
101
+ if (operandValue === Fail) return Fail;
102
+ lhs = op.fold(opOut, operandValue);
103
+ } else {
104
+ const prefixFailure = failure;
105
+ lhs = operand(state);
106
+ if (lhs === Fail) {
107
+ if (prefixFailure !== void 0 && state.mode === "Backtrack") state.failWith("Backtrack", mergeFailures(prefixFailure, state.failure));
108
+ return Fail;
109
+ }
110
+ }
111
+ while (true) {
112
+ const start = state.pos;
113
+ failure = void 0;
114
+ const q = tryOps(state, postfixes, true);
115
+ if (q === -2) return Fail;
116
+ if (q >= 0) {
117
+ const op = postfixes[q];
118
+ if (op.precedence * 2 < minPower) {
119
+ state.pos = start;
120
+ break;
121
+ }
122
+ lhs = op.fold(lhs, matched);
123
+ continue;
124
+ }
125
+ const postfixFailure = failure;
126
+ const i = tryOps(state, infixes, false);
127
+ if (i === -2) return Fail;
128
+ if (i < 0) {
129
+ const f = postfixFailure === void 0 ? failure : failure === void 0 ? postfixFailure : mergeFailures(postfixFailure, failure);
130
+ if (f !== void 0 && f.offset === state.pos) state.setHint(f.offset, f.expected);
131
+ break;
132
+ }
133
+ const op = infixes[i];
134
+ const leftPower = op.precedence * 2;
135
+ if (leftPower < minPower) {
136
+ state.pos = start;
137
+ break;
138
+ }
139
+ const opOut = matched;
140
+ const rhs = expr(state, op.associativity === "left" ? leftPower + 1 : leftPower);
141
+ if (rhs === Fail) return Fail;
142
+ lhs = op.fold(lhs, opOut, rhs);
143
+ }
144
+ return lhs;
145
+ };
146
+ return make$1((state) => expr(state, 0), "expression");
138
147
  };
148
+ //#endregion
149
+ export { infixLeft, infixRight, make, postfix, prefix };
150
+
139
151
  //# sourceMappingURL=Expression.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Expression.js","sourceRoot":"","sources":["../src/Expression.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Expression.js","names":["makeParser"],"sources":["../src/Expression.ts"],"sourcesContent":["/**\n * Operator-precedence expression parsing with a Pratt parser (from\n * `nom-language`'s `precedence`, and winnow's expression parser).\n *\n * Describe the operand parser and a table of prefix, postfix and infix\n * operators with their precedence (higher binds tighter) and associativity.\n * Each operator carries a function that folds its operands into a result.\n *\n * @example\n * ```ts\n * import { Ascii, Expression, Parser, Token } from \"@thomasfosterau/effect-parse\"\n *\n * const op = (s: string) => Parser.delimited(Ascii.space0, Token.literal(s), Ascii.space0)\n *\n * const arithmetic: Parser.Parser<number, string> = Expression.make({\n * operand: Parser.alt(\n * Ascii.decInt,\n * Parser.delimited(op(\"(\"), Parser.suspend(() => arithmetic), op(\")\"))\n * ),\n * operators: [\n * Expression.prefix(op(\"-\"), 4, (_, x) => -x),\n * Expression.postfix(op(\"!\"), 5, (x) => factorial(x)),\n * Expression.infixRight(op(\"^\"), 3, (l, _, r) => l ** r),\n * Expression.infixLeft(op(\"*\"), 2, (l, _, r) => l * r),\n * Expression.infixLeft(op(\"/\"), 2, (l, _, r) => l / r),\n * Expression.infixLeft(op(\"+\"), 1, (l, _, r) => l + r),\n * Expression.infixLeft(op(\"-\"), 1, (l, _, r) => l - r)\n * ]\n * })\n *\n * declare const factorial: (n: number) => number\n * Parser.parse(arithmetic, \"1 + 2 * 3 ^ 2\") // Result.succeed(19)\n * ```\n *\n * @since 0.1.0\n */\nimport type { Input, State } from \"./Input.js\"\nimport { Fail, mergeFailures } from \"./Input.js\"\nimport type { Failure } from \"./Input.js\"\nimport type { Parser } from \"./Parser.js\"\nimport { make as makeParser } from \"./Parser.js\"\n\n/**\n * An operator in an expression grammar.\n *\n * @since 0.1.0\n * @category models\n */\nexport type Operator<A, E = never, R = never, I extends Input = string> =\n | Prefix<A, E, R, I>\n | Postfix<A, E, R, I>\n | Infix<A, E, R, I>\n\ninterface OperatorBase<E, R, I extends Input> {\n readonly parser: Parser<unknown, E, R, I>\n readonly precedence: number\n}\n\n/**\n * @since 0.1.0\n * @category models\n */\nexport interface Prefix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {\n readonly _tag: \"Prefix\"\n readonly fold: (op: any, operand: A) => A\n}\n\n/**\n * @since 0.1.0\n * @category models\n */\nexport interface Postfix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {\n readonly _tag: \"Postfix\"\n readonly fold: (operand: A, op: any) => A\n}\n\n/**\n * @since 0.1.0\n * @category models\n */\nexport interface Infix<A, E = never, R = never, I extends Input = string> extends OperatorBase<E, R, I> {\n readonly _tag: \"Infix\"\n readonly associativity: \"left\" | \"right\"\n readonly fold: (left: A, op: any, right: A) => A\n}\n\n/**\n * A prefix operator, e.g. unary minus.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const prefix = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (op: O, operand: A) => A\n): Prefix<A, E, R, I> => ({ _tag: \"Prefix\", parser, precedence, fold })\n\n/**\n * A postfix operator, e.g. factorial or a function call suffix.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const postfix = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (operand: A, op: O) => A\n): Postfix<A, E, R, I> => ({ _tag: \"Postfix\", parser, precedence, fold })\n\n/**\n * A left-associative infix operator: `a - b - c` is `(a - b) - c`.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const infixLeft = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (left: A, op: O, right: A) => A\n): Infix<A, E, R, I> => ({ _tag: \"Infix\", associativity: \"left\", parser, precedence, fold })\n\n/**\n * A right-associative infix operator: `a ^ b ^ c` is `a ^ (b ^ c)`.\n *\n * @since 0.1.0\n * @category operators\n */\nexport const infixRight = <O, E, R, I extends Input, A>(\n parser: Parser<O, E, R, I>,\n precedence: number,\n fold: (left: A, op: O, right: A) => A\n): Infix<A, E, R, I> => ({ _tag: \"Infix\", associativity: \"right\", parser, precedence, fold })\n\ntype OpError<Op> = Op extends OperatorBase<infer E, infer _R, infer _I> ? E : never\ntype OpServices<Op> = Op extends OperatorBase<infer _E, infer R, infer _I> ? R : never\ntype OpInput<Op> = [Op] extends [never] ? Input : [Op] extends [OperatorBase<infer _E, infer _R, infer I>] ? I : never\n\n/**\n * Builds an expression parser from an operand parser and an operator table.\n *\n * Precedences are compared numerically: higher binds tighter. A prefix\n * operator applies to everything that binds tighter than it, so with `-`\n * at precedence 4 and `^` at 3, `-2 ^ 2` parses as `(-2) ^ 2`.\n *\n * When several operators of the same kind match, the first one in the\n * table wins, so list longer operators (`<=`) before their prefixes (`<`).\n *\n * @since 0.1.0\n * @category constructors\n */\nexport const make = <A, E, R, I extends Input, const Ops extends ReadonlyArray<Operator<A, any, any, any>>>(options: {\n readonly operand: Parser<A, E, R, I>\n readonly operators: Ops\n}): Parser<A, E | OpError<Ops[number]>, R | OpServices<Ops[number]>, I & OpInput<Ops[number]>> => {\n const operand = options.operand.step\n const prefixes = options.operators.filter((o): o is Prefix<A, any, any, any> => o._tag === \"Prefix\")\n const postfixes = options.operators.filter((o): o is Postfix<A, any, any, any> => o._tag === \"Postfix\")\n const infixes = options.operators.filter((o): o is Infix<A, any, any, any> => o._tag === \"Infix\")\n\n // Attempts each operator in turn. Returns the index of the first match\n // (with its output in `matched`), -1 if none matched, or -2 on a fatal\n // failure. Expectations of failed attempts are accumulated in `failure`.\n let matched: unknown\n let failure: Failure | undefined\n const tryOps = (state: State<any>, ops: ReadonlyArray<OperatorBase<any, any, any>>, mustConsume: boolean): number => {\n const start = state.pos\n for (let i = 0; i < ops.length; i++) {\n const out = ops[i].parser.step(state)\n if (out !== Fail) {\n // A prefix or postfix operator matching nothing would apply forever\n if (mustConsume && state.pos === start) {\n state.failMessage(\"Cut\", \"Assert\", \"prefix and postfix operators must always consume\")\n return -2\n }\n matched = out\n return i\n }\n if (state.mode !== \"Backtrack\") return -2\n failure = failure === undefined ? state.failure : mergeFailures(failure, state.failure)\n state.pos = start\n }\n return -1\n }\n\n const expr = (state: State<any>, minPower: number): A | Fail => {\n let lhs: A | Fail\n failure = undefined\n const p = tryOps(state, prefixes, true)\n if (p === -2) return Fail\n if (p >= 0) {\n const op = prefixes[p]\n const opOut = matched\n const operandValue = expr(state, op.precedence * 2)\n if (operandValue === Fail) return Fail\n lhs = op.fold(opOut, operandValue)\n } else {\n const prefixFailure = failure\n lhs = operand(state)\n if (lhs === Fail) {\n if (prefixFailure !== undefined && state.mode === \"Backtrack\") {\n state.failWith(\"Backtrack\", mergeFailures(prefixFailure, state.failure))\n }\n return Fail\n }\n }\n\n while (true) {\n const start = state.pos\n failure = undefined\n const q = tryOps(state, postfixes, true)\n if (q === -2) return Fail\n if (q >= 0) {\n const op = postfixes[q]\n if (op.precedence * 2 < minPower) {\n state.pos = start\n break\n }\n lhs = op.fold(lhs, matched)\n continue\n }\n const postfixFailure = failure\n const i = tryOps(state, infixes, false)\n if (i === -2) return Fail\n if (i < 0) {\n const f =\n postfixFailure === undefined\n ? failure\n : failure === undefined\n ? postfixFailure\n : mergeFailures(postfixFailure, failure)\n if (f !== undefined && f.offset === state.pos) state.setHint(f.offset, f.expected)\n break\n }\n const op = infixes[i]\n const leftPower = op.precedence * 2\n if (leftPower < minPower) {\n state.pos = start\n break\n }\n const opOut = matched\n const rhs = expr(state, op.associativity === \"left\" ? leftPower + 1 : leftPower)\n if (rhs === Fail) return Fail\n lhs = op.fold(lhs, opOut, rhs)\n }\n return lhs\n }\n\n return makeParser((state: State<any>) => expr(state, 0), \"expression\")\n}\n"],"mappings":"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"}