@thomasfosterau/effect-parse 0.4.1 → 0.5.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 (143) hide show
  1. package/README.md +37 -13
  2. package/dist/Ascii.d.ts +11 -4
  3. package/dist/Ascii.d.ts.map +1 -1
  4. package/dist/Ascii.js +7 -1
  5. package/dist/Ascii.js.map +1 -1
  6. package/dist/Binary.d.ts.map +1 -1
  7. package/dist/Binary.js +64 -35
  8. package/dist/Binary.js.map +1 -1
  9. package/dist/Bits.d.ts.map +1 -1
  10. package/dist/Bits.js +7 -4
  11. package/dist/Bits.js.map +1 -1
  12. package/dist/Compiler.d.ts +74 -2
  13. package/dist/Compiler.d.ts.map +1 -1
  14. package/dist/Compiler.js +78 -1
  15. package/dist/Compiler.js.map +1 -1
  16. package/dist/Expression.d.ts.map +1 -1
  17. package/dist/Expression.js +86 -74
  18. package/dist/Expression.js.map +1 -1
  19. package/dist/Input.d.ts +37 -4
  20. package/dist/Input.d.ts.map +1 -1
  21. package/dist/Input.js +42 -0
  22. package/dist/Input.js.map +1 -1
  23. package/dist/Nom.d.ts +5 -15
  24. package/dist/Nom.d.ts.map +1 -1
  25. package/dist/Nom.js.map +1 -1
  26. package/dist/ParseError.d.ts.map +1 -1
  27. package/dist/ParseError.js.map +1 -1
  28. package/dist/Parser.d.ts +366 -26
  29. package/dist/Parser.d.ts.map +1 -1
  30. package/dist/Parser.js +390 -19
  31. package/dist/Parser.js.map +1 -1
  32. package/dist/ParserSchema.js +1 -1
  33. package/dist/ParserStream.d.ts +3 -2
  34. package/dist/ParserStream.d.ts.map +1 -1
  35. package/dist/ParserStream.js +13 -9
  36. package/dist/ParserStream.js.map +1 -1
  37. package/dist/Syntax.d.ts +23 -5
  38. package/dist/Syntax.d.ts.map +1 -1
  39. package/dist/Syntax.js.map +1 -1
  40. package/dist/Text.d.ts.map +1 -1
  41. package/dist/Text.js +9 -9
  42. package/dist/Text.js.map +1 -1
  43. package/dist/Token.d.ts +55 -10
  44. package/dist/Token.d.ts.map +1 -1
  45. package/dist/Token.js +59 -21
  46. package/dist/Token.js.map +1 -1
  47. package/dist/internal/compiler/closure.d.ts.map +1 -1
  48. package/dist/internal/compiler/closure.js +257 -97
  49. package/dist/internal/compiler/closure.js.map +1 -1
  50. package/dist/internal/compiler/entries.d.ts +3 -1
  51. package/dist/internal/compiler/entries.d.ts.map +1 -1
  52. package/dist/internal/compiler/entries.js +3 -2
  53. package/dist/internal/compiler/entries.js.map +1 -1
  54. package/dist/internal/compiler/first.d.ts.map +1 -1
  55. package/dist/internal/compiler/first.js +7 -1
  56. package/dist/internal/compiler/first.js.map +1 -1
  57. package/dist/internal/compiler/graph.d.ts +17 -0
  58. package/dist/internal/compiler/graph.d.ts.map +1 -0
  59. package/dist/internal/compiler/graph.js +56 -0
  60. package/dist/internal/compiler/graph.js.map +1 -0
  61. package/dist/internal/compiler/jit.d.ts +5 -0
  62. package/dist/internal/compiler/jit.d.ts.map +1 -1
  63. package/dist/internal/compiler/jit.js +185 -96
  64. package/dist/internal/compiler/jit.js.map +1 -1
  65. package/dist/internal/compiler/registry.d.ts +10 -2
  66. package/dist/internal/compiler/registry.d.ts.map +1 -1
  67. package/dist/internal/compiler/registry.js.map +1 -1
  68. package/dist/internal/compiler/search.d.ts +32 -0
  69. package/dist/internal/compiler/search.d.ts.map +1 -0
  70. package/dist/internal/compiler/search.js +68 -0
  71. package/dist/internal/compiler/search.js.map +1 -0
  72. package/dist/internal/compiler/sets.d.ts.map +1 -1
  73. package/dist/internal/compiler/sets.js +1 -1
  74. package/dist/internal/compiler/sets.js.map +1 -1
  75. package/dist/internal/compiler/wasm.d.ts +8 -0
  76. package/dist/internal/compiler/wasm.d.ts.map +1 -0
  77. package/dist/internal/compiler/wasm.js +2769 -0
  78. package/dist/internal/compiler/wasm.js.map +1 -0
  79. package/dist/internal/compiler/wasmAsm.d.ts +199 -0
  80. package/dist/internal/compiler/wasmAsm.d.ts.map +1 -0
  81. package/dist/internal/compiler/wasmAsm.js +427 -0
  82. package/dist/internal/compiler/wasmAsm.js.map +1 -0
  83. package/dist/internal/entries.d.ts +3 -1
  84. package/dist/internal/entries.d.ts.map +1 -1
  85. package/dist/internal/entries.js.map +1 -1
  86. package/dist/internal/node.d.ts +58 -2
  87. package/dist/internal/node.d.ts.map +1 -1
  88. package/dist/internal/node.js +13 -3
  89. package/dist/internal/node.js.map +1 -1
  90. package/dist/internal/numbers.d.ts.map +1 -1
  91. package/dist/internal/numbers.js.map +1 -1
  92. package/dist/internal/run.d.ts +12 -0
  93. package/dist/internal/run.d.ts.map +1 -1
  94. package/dist/internal/run.js +51 -11
  95. package/dist/internal/run.js.map +1 -1
  96. package/dist/internal/stack.d.ts +6 -0
  97. package/dist/internal/stack.d.ts.map +1 -1
  98. package/dist/internal/stack.js +8 -2
  99. package/dist/internal/stack.js.map +1 -1
  100. package/dist/internal/syntax.d.ts +4 -4
  101. package/dist/internal/syntax.d.ts.map +1 -1
  102. package/dist/internal/syntax.js +18 -10
  103. package/dist/internal/syntax.js.map +1 -1
  104. package/dist/internal/text.d.ts +32 -0
  105. package/dist/internal/text.d.ts.map +1 -1
  106. package/dist/internal/text.js +68 -14
  107. package/dist/internal/text.js.map +1 -1
  108. package/dist/internal/tokens.d.ts +13 -0
  109. package/dist/internal/tokens.d.ts.map +1 -1
  110. package/dist/internal/tokens.js +59 -39
  111. package/dist/internal/tokens.js.map +1 -1
  112. package/package.json +5 -4
  113. package/src/Ascii.ts +42 -9
  114. package/src/Binary.ts +151 -71
  115. package/src/Bits.ts +12 -6
  116. package/src/Compiler.ts +101 -10
  117. package/src/Expression.ts +94 -81
  118. package/src/Input.ts +65 -6
  119. package/src/Nom.ts +15 -5
  120. package/src/ParseError.ts +3 -0
  121. package/src/Parser.ts +678 -127
  122. package/src/ParserStream.ts +37 -18
  123. package/src/Syntax.ts +60 -36
  124. package/src/Text.ts +16 -15
  125. package/src/Token.ts +138 -29
  126. package/src/internal/compiler/closure.ts +362 -135
  127. package/src/internal/compiler/entries.ts +4 -2
  128. package/src/internal/compiler/first.ts +10 -0
  129. package/src/internal/compiler/graph.ts +68 -0
  130. package/src/internal/compiler/jit.ts +284 -154
  131. package/src/internal/compiler/registry.ts +10 -2
  132. package/src/internal/compiler/search.ts +68 -0
  133. package/src/internal/compiler/sets.ts +7 -3
  134. package/src/internal/compiler/wasm.ts +3203 -0
  135. package/src/internal/compiler/wasmAsm.ts +484 -0
  136. package/src/internal/entries.ts +8 -2
  137. package/src/internal/node.ts +54 -4
  138. package/src/internal/numbers.ts +3 -1
  139. package/src/internal/run.ts +71 -12
  140. package/src/internal/stack.ts +8 -1
  141. package/src/internal/syntax.ts +39 -18
  142. package/src/internal/text.ts +97 -9
  143. package/src/internal/tokens.ts +96 -14
@@ -24,11 +24,13 @@ export const pairOf = (p: ParserLike): EntryPair | undefined => {
24
24
  return { parsers: node.parsers, key: output[0], value: output[1] }
25
25
  }
26
26
 
27
- const isDiagnostic = (
27
+ /** Whether a node only changes diagnostics: its parser parses as its child does. */
28
+ export const isDiagnostic = (
28
29
  node: Node
29
- ): node is NodeOf<"Context" | "Expected" | "MapError" | "OrFail" | "Trace" | "Syntax" | "RetryAfter"> =>
30
+ ): node is NodeOf<"Context" | "Expected" | "Quiet" | "MapError" | "OrFail" | "Trace" | "Syntax" | "RetryAfter"> =>
30
31
  Predicate.isTagged(node, "Context") ||
31
32
  Predicate.isTagged(node, "Expected") ||
33
+ Predicate.isTagged(node, "Quiet") ||
32
34
  Predicate.isTagged(node, "MapError") ||
33
35
  Predicate.isTagged(node, "OrFail") ||
34
36
  Predicate.isTagged(node, "Trace") ||
@@ -92,6 +92,7 @@ export class FirstSets {
92
92
  }
93
93
 
94
94
  private compute(node: Node): First {
95
+ // SAFETY: `compute` is only called from `of`, which returns before it when `kind` is 2
95
96
  const kind = this.kind as 0 | 1
96
97
  switch (node._tag) {
97
98
  case "Succeed":
@@ -111,6 +112,7 @@ export class FirstSets {
111
112
  if (node.encoding !== undefined) {
112
113
  if (kindOfEncoding(node.encoding) !== kind) return unknown
113
114
  if (node.caseless) return isEmptyUnits(lit) ? unknown : anyUnit
115
+ // SAFETY: a `Literal` with an encoding is a `Text` literal, which records the string it encodes
114
116
  const encoded = node.encoding.encode(lit as string)
115
117
  if (isEmptyUnits(encoded)) return emptyOptional
116
118
  return ofUnits([Predicate.isString(encoded) ? encoded.charCodeAt(0) : encoded[0]])
@@ -141,13 +143,18 @@ export class FirstSets {
141
143
  case "Tap":
142
144
  case "TryMap":
143
145
  case "FilterMap":
146
+ case "MapOrFail":
144
147
  case "Filter":
145
148
  case "Taken":
146
149
  case "WithTaken":
147
150
  case "Span":
148
151
  case "WithSpan":
152
+ case "MapSpan":
149
153
  case "Context":
150
154
  case "Expected":
155
+ case "Quiet":
156
+ // A fast path accepts what its grammar accepts (`Parser.withFastPath`)
157
+ case "FastPath":
151
158
  case "MapError":
152
159
  case "OrFail":
153
160
  case "Peek":
@@ -173,6 +180,7 @@ export class FirstSets {
173
180
  }
174
181
  case "Seq":
175
182
  case "Struct":
183
+ case "SeqWith":
176
184
  return this.sequence(node.parsers)
177
185
  case "ZipWith":
178
186
  return this.sequence([node.self, node.that])
@@ -198,6 +206,8 @@ export class FirstSets {
198
206
  }
199
207
  case "Suspend":
200
208
  return this.of(node.resolve())
209
+ case "Fixed":
210
+ return kind !== 1 ? unknown : node.size === 0 ? emptyOptional : anyUnit
201
211
  default:
202
212
  return unknown
203
213
  }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * The shape of a grammar, as the code-generating compilers (the JIT and the
3
+ * WebAssembly compiler) see it: which parsers are leaves, which are shared
4
+ * and which are small enough to inline everywhere.
5
+ */
6
+ import * as Predicate from "effect/Predicate"
7
+ import type { Node, ParserLike } from "../node.js"
8
+ import { children, nodeOf } from "../node.js"
9
+
10
+ /** Whether a node is a token or a constant, always generated inline. */
11
+ export const isLeaf = (node: Node): boolean =>
12
+ Predicate.isTagged(node, "Succeed") ||
13
+ Predicate.isTagged(node, "Fail") ||
14
+ Predicate.isTagged(node, "Eof") ||
15
+ Predicate.isTagged(node, "Location") ||
16
+ Predicate.isTagged(node, "RestLen") ||
17
+ Predicate.isTagged(node, "Any") ||
18
+ Predicate.isTagged(node, "Literal") ||
19
+ Predicate.isTagged(node, "OneOf") ||
20
+ Predicate.isTagged(node, "TakeWhile")
21
+
22
+ /** The number of distinct parents of each parser reachable from `root`. */
23
+ export const countRefs = (root: ParserLike): WeakMap<ParserLike, number> => {
24
+ const refs = new WeakMap<ParserLike, number>()
25
+ const seen = new WeakSet<ParserLike>()
26
+ const stack = [root]
27
+ for (let p = stack.pop(); p !== undefined; p = stack.pop()) {
28
+ if (seen.has(p)) continue
29
+ seen.add(p)
30
+ const counted = new WeakSet<ParserLike>()
31
+ for (const c of children(nodeOf(p))) {
32
+ if (counted.has(c)) continue
33
+ counted.add(c)
34
+ refs.set(c, (refs.get(c) ?? 0) + 1)
35
+ stack.push(c)
36
+ }
37
+ }
38
+ return refs
39
+ }
40
+
41
+ /** Whether a parser is small enough to inline wherever it is used. */
42
+ export const isSmall = (p: ParserLike): boolean => {
43
+ let budget = 6
44
+ const visit = (q: ParserLike): boolean => {
45
+ const node = nodeOf(q)
46
+ if (
47
+ --budget < 0 ||
48
+ Predicate.isTagged(node, "Suspend") ||
49
+ Predicate.isTagged(node, "Escaped") ||
50
+ Predicate.isTagged(node, "Dispatch")
51
+ )
52
+ return false
53
+ return children(node).every(visit)
54
+ }
55
+ return visit(p)
56
+ }
57
+
58
+ /** The node a `dispatch` selects on, and whether it is looked at with `peek`. */
59
+ export const selectorOf = (selector: ParserLike): { readonly node: Node; readonly peek: boolean } => {
60
+ const node = nodeOf(selector)
61
+ return Predicate.isTagged(node, "Peek") ? { node: nodeOf(node.self), peek: true } : { node, peek: false }
62
+ }
63
+
64
+ /** ASCII lower case. */
65
+ export const lowerAscii = (c: number): number => (c >= 65 && c <= 90 ? c + 32 : c)
66
+
67
+ /** Whether a code is an ASCII letter. */
68
+ export const isLetter = (c: number): boolean => (c >= 65 && c <= 90) || (c >= 97 && c <= 122)