@thomasfosterau/effect-parse 0.2.0 → 0.4.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 (144) hide show
  1. package/README.md +44 -1
  2. package/dist/Ascii.d.ts +0 -2
  3. package/dist/Ascii.d.ts.map +1 -1
  4. package/dist/Ascii.js +6 -6
  5. package/dist/Ascii.js.map +1 -1
  6. package/dist/Binary.d.ts +0 -2
  7. package/dist/Binary.d.ts.map +1 -1
  8. package/dist/Binary.js +1 -2
  9. package/dist/Bits.d.ts +0 -2
  10. package/dist/Bits.d.ts.map +1 -1
  11. package/dist/Bits.js +2 -3
  12. package/dist/Bits.js.map +1 -1
  13. package/dist/Compiler.d.ts +0 -2
  14. package/dist/Compiler.d.ts.map +1 -1
  15. package/dist/Compiler.js +1 -2
  16. package/dist/Encoding.d.ts +0 -2
  17. package/dist/Encoding.d.ts.map +1 -1
  18. package/dist/Encoding.js +1 -2
  19. package/dist/Expression.d.ts +0 -2
  20. package/dist/Expression.d.ts.map +1 -1
  21. package/dist/Expression.js +61 -18
  22. package/dist/Expression.js.map +1 -1
  23. package/dist/Input.d.ts +80 -7
  24. package/dist/Input.d.ts.map +1 -1
  25. package/dist/Input.js +149 -18
  26. package/dist/Input.js.map +1 -1
  27. package/dist/Nom.d.ts +1 -3
  28. package/dist/Nom.d.ts.map +1 -1
  29. package/dist/Nom.js +1 -2
  30. package/dist/ParseError.d.ts +0 -2
  31. package/dist/ParseError.d.ts.map +1 -1
  32. package/dist/ParseError.js +6 -10
  33. package/dist/ParseError.js.map +1 -1
  34. package/dist/Parser.d.ts +2 -2
  35. package/dist/Parser.d.ts.map +1 -1
  36. package/dist/Parser.js +58 -32
  37. package/dist/Parser.js.map +1 -1
  38. package/dist/ParserSchema.d.ts +198 -2
  39. package/dist/ParserSchema.d.ts.map +1 -1
  40. package/dist/ParserSchema.js +646 -18
  41. package/dist/ParserSchema.js.map +1 -1
  42. package/dist/ParserStream.d.ts +0 -2
  43. package/dist/ParserStream.d.ts.map +1 -1
  44. package/dist/ParserStream.js +15 -9
  45. package/dist/ParserStream.js.map +1 -1
  46. package/dist/Syntax.d.ts +0 -2
  47. package/dist/Syntax.d.ts.map +1 -1
  48. package/dist/Syntax.js +13 -11
  49. package/dist/Syntax.js.map +1 -1
  50. package/dist/Text.d.ts +0 -2
  51. package/dist/Text.d.ts.map +1 -1
  52. package/dist/Text.js +1 -2
  53. package/dist/Token.d.ts +0 -2
  54. package/dist/Token.d.ts.map +1 -1
  55. package/dist/Token.js +1 -2
  56. package/dist/internal/compiler/closure.d.ts +5 -2
  57. package/dist/internal/compiler/closure.d.ts.map +1 -1
  58. package/dist/internal/compiler/closure.js +160 -92
  59. package/dist/internal/compiler/closure.js.map +1 -1
  60. package/dist/internal/compiler/entries.d.ts +0 -2
  61. package/dist/internal/compiler/entries.d.ts.map +1 -1
  62. package/dist/internal/compiler/entries.js +6 -7
  63. package/dist/internal/compiler/entries.js.map +1 -1
  64. package/dist/internal/compiler/first.d.ts +0 -2
  65. package/dist/internal/compiler/first.d.ts.map +1 -1
  66. package/dist/internal/compiler/first.js +10 -10
  67. package/dist/internal/compiler/first.js.map +1 -1
  68. package/dist/internal/compiler/jit.d.ts +0 -2
  69. package/dist/internal/compiler/jit.d.ts.map +1 -1
  70. package/dist/internal/compiler/jit.js +52 -51
  71. package/dist/internal/compiler/jit.js.map +1 -1
  72. package/dist/internal/compiler/registry.d.ts +0 -2
  73. package/dist/internal/compiler/registry.d.ts.map +1 -1
  74. package/dist/internal/compiler/registry.js +1 -2
  75. package/dist/internal/compiler/sets.d.ts +2 -2
  76. package/dist/internal/compiler/sets.d.ts.map +1 -1
  77. package/dist/internal/compiler/sets.js +8 -3
  78. package/dist/internal/compiler/sets.js.map +1 -1
  79. package/dist/internal/entries.d.ts +0 -2
  80. package/dist/internal/entries.d.ts.map +1 -1
  81. package/dist/internal/entries.js +1 -2
  82. package/dist/internal/key.d.ts +10 -0
  83. package/dist/internal/key.d.ts.map +1 -0
  84. package/dist/internal/key.js +11 -0
  85. package/dist/internal/key.js.map +1 -0
  86. package/dist/internal/node.d.ts +11 -4
  87. package/dist/internal/node.d.ts.map +1 -1
  88. package/dist/internal/node.js +15 -3
  89. package/dist/internal/node.js.map +1 -1
  90. package/dist/internal/numbers.d.ts +0 -2
  91. package/dist/internal/numbers.d.ts.map +1 -1
  92. package/dist/internal/numbers.js +1 -2
  93. package/dist/internal/resume.d.ts +5 -6
  94. package/dist/internal/resume.d.ts.map +1 -1
  95. package/dist/internal/resume.js +1 -2
  96. package/dist/internal/resume.js.map +1 -1
  97. package/dist/internal/run.d.ts +0 -2
  98. package/dist/internal/run.d.ts.map +1 -1
  99. package/dist/internal/run.js +2 -3
  100. package/dist/internal/run.js.map +1 -1
  101. package/dist/internal/stack.d.ts +0 -2
  102. package/dist/internal/stack.d.ts.map +1 -1
  103. package/dist/internal/stack.js +12 -3
  104. package/dist/internal/stack.js.map +1 -1
  105. package/dist/internal/syntax.d.ts +30 -19
  106. package/dist/internal/syntax.d.ts.map +1 -1
  107. package/dist/internal/syntax.js +74 -63
  108. package/dist/internal/syntax.js.map +1 -1
  109. package/dist/internal/text.d.ts +5 -2
  110. package/dist/internal/text.d.ts.map +1 -1
  111. package/dist/internal/text.js +14 -5
  112. package/dist/internal/text.js.map +1 -1
  113. package/dist/internal/ties.d.ts +28 -0
  114. package/dist/internal/ties.d.ts.map +1 -0
  115. package/dist/internal/ties.js +66 -0
  116. package/dist/internal/ties.js.map +1 -0
  117. package/dist/internal/tokens.d.ts +10 -9
  118. package/dist/internal/tokens.d.ts.map +1 -1
  119. package/dist/internal/tokens.js +4 -8
  120. package/dist/internal/tokens.js.map +1 -1
  121. package/package.json +6 -6
  122. package/src/Ascii.ts +6 -5
  123. package/src/Bits.ts +1 -1
  124. package/src/Expression.ts +27 -23
  125. package/src/Input.ts +157 -21
  126. package/src/ParseError.ts +10 -8
  127. package/src/Parser.ts +67 -32
  128. package/src/ParserSchema.ts +982 -23
  129. package/src/ParserStream.ts +20 -8
  130. package/src/Syntax.ts +12 -9
  131. package/src/internal/compiler/closure.ts +202 -90
  132. package/src/internal/compiler/entries.ts +14 -11
  133. package/src/internal/compiler/first.ts +9 -8
  134. package/src/internal/compiler/jit.ts +95 -74
  135. package/src/internal/compiler/sets.ts +7 -0
  136. package/src/internal/key.ts +11 -0
  137. package/src/internal/node.ts +19 -2
  138. package/src/internal/resume.ts +5 -4
  139. package/src/internal/run.ts +1 -1
  140. package/src/internal/stack.ts +6 -1
  141. package/src/internal/syntax.ts +80 -84
  142. package/src/internal/text.ts +24 -4
  143. package/src/internal/ties.ts +83 -0
  144. package/src/internal/tokens.ts +20 -13
@@ -1,6 +1,7 @@
1
1
  import * as Predicate from "effect/Predicate";
2
- import { Fail, Failure, State } from "../Input.js";
3
- //#region src/internal/syntax.ts
2
+ import { Fail, Failure } from "../Input.js";
3
+ import * as Arr from "effect/Array";
4
+ // src/internal/syntax.ts
4
5
  /**
5
6
  * The tree builder behind the `Syntax` module (see `docs/DESIGN.md`,
6
7
  * "Syntax trees").
@@ -17,14 +18,22 @@ import { Fail, Failure, State } from "../Input.js";
17
18
  * completes and adopts them. Nodes built by an attempt that is later
18
19
  * abandoned must not end up in the tree. Every combinator that abandons an
19
20
  * attempt moves the cursor back to (or before) where the attempt started,
20
- * and every node has a positive width, so the nodes of an abandoned attempt
21
- * are exactly those that end after the position the cursor moves back to:
22
- * the `pos` setter of {@link SyntaxState} drops them. This also covers
23
- * lookahead (`peek`, `not`) and custom parsers written with `Parser.make`.
21
+ * with `State.rewind`, and every node has a positive width, so the nodes of
22
+ * an abandoned attempt are exactly those that end after the position the
23
+ * cursor moves back to: {@link SyntaxBuilder} drops them when told of the rewind. This also
24
+ * covers lookahead (`peek`, `not`) and custom parsers written with
25
+ * `Parser.make`, which rewind the same way.
26
+ *
27
+ * `pos` stays a plain field, not an accessor that would watch every move: a
28
+ * `pos` accessor on this subclass made every parser's cursor accesses
29
+ * polymorphic, slowing ordinary parses by about a fifth in any program that
30
+ * also built a syntax tree, and the syntax parse itself about twofold.
24
31
  *
25
32
  * For incremental parsing, every node records how far its parse looked: the
26
33
  * furthest position the cursor reached and the furthest failure recorded
27
- * while it was being parsed (its *lookahead*). A node from the previous tree
34
+ * while it was being parsed (its *lookahead*). The cursor only moves forward
35
+ * between rewinds, so the furthest position is where it was at a rewind, or
36
+ * where it is now. A node from the previous tree
28
37
  * is reused at a position when it was built by the same `Syntax.node`, and
29
38
  * the input it looked at, plus a margin for the tokens that read a little
30
39
  * past where they stop, is unchanged.
@@ -94,46 +103,49 @@ const build = (kind, named, key, start, end, lookahead, entries, value, error, d
94
103
  }
95
104
  return new Green(kind, named, key, end - start, Math.max(lookahead, end) - start, children, offsets, fields, value, error, hasError, diagnostics);
96
105
  };
97
- /** The parse state of a `Syntax` parse. */
98
- var SyntaxState = class extends State {
99
- static {
100
- Object.defineProperty(this.prototype, "pos", {
101
- get() {
102
- return this.cursor;
103
- },
104
- set(p) {
105
- if (p < this.cursor) {
106
- const stack = this.stack;
107
- while (stack.length > 0 && stack[stack.length - 1].end > p) stack.pop();
108
- }
109
- if (p > this.highWater) this.highWater = p;
110
- this.cursor = p;
111
- },
112
- configurable: true,
113
- enumerable: true
114
- });
115
- }
116
- constructor(source, options, previous) {
117
- super(source, { context: options.context });
118
- this.highWater = this.cursor;
119
- this.stack = [];
106
+ /**
107
+ * The tree builder of a `Syntax` parse, reached through `state.syntax`. It
108
+ * is not a `State` subclass: one class of state keeps every parser's cursor
109
+ * and failure accesses monomorphic, whether or not the program also builds
110
+ * syntax trees. `State` calls {@link reach} and {@link rewound} itself.
111
+ */
112
+ var SyntaxBuilder = class {
113
+ state;
114
+ previous;
115
+ /**
116
+ * The furthest position the cursor reached before a rewind, or failure
117
+ * recorded, since the innermost open node started; {@link looked} adds
118
+ * where the cursor is now.
119
+ */
120
+ highWater;
121
+ /** Completed nodes waiting for their parent, in input order. */
122
+ stack = [];
123
+ /** How many nodes were reused from the previous tree. */
124
+ reused = 0;
125
+ /** Where {@link find} found the last node it found. */
126
+ lastParent = void 0;
127
+ lastParentStart = 0;
128
+ constructor(state, previous) {
129
+ this.state = state;
120
130
  this.previous = previous;
121
- this.reused = 0;
122
- this.lastParent = void 0;
123
- this.lastParentStart = 0;
124
- this.syntax = this;
125
- this.recovered = [];
126
- }
127
- failWith(mode, failure) {
128
- if (failure.offset > this.highWater) this.highWater = failure.offset;
129
- return super.failWith(mode, failure);
131
+ this.highWater = state.pos;
132
+ state.syntax = this;
133
+ state.recovered = [];
130
134
  }
131
- setHint(offset, expected) {
135
+ reach(offset) {
132
136
  if (offset > this.highWater) this.highWater = offset;
133
- super.setHint(offset, expected);
137
+ }
138
+ rewound(from, to) {
139
+ if (from > this.highWater) this.highWater = from;
140
+ const stack = this.stack;
141
+ while (Arr.isArrayNonEmpty(stack) && Arr.lastNonEmpty(stack).end > to) stack.pop();
142
+ }
143
+ /** How far the parse looked: {@link highWater}, or the cursor if it is further. */
144
+ looked() {
145
+ return this.state.pos > this.highWater ? this.state.pos : this.highWater;
134
146
  }
135
147
  node(state, step, key, kind, named) {
136
- const start = this.cursor;
148
+ const start = this.state.pos;
137
149
  const stack = this.stack;
138
150
  if (this.previous !== void 0) {
139
151
  const green = this.reusable(this.previous, key, start);
@@ -146,7 +158,7 @@ var SyntaxState = class extends State {
146
158
  const d = green.diagnostics;
147
159
  if (d !== void 0) {
148
160
  if (d.deepest !== void 0) this.deepen(start === d.base ? d.deepest : rebase(d.deepest, d.base - start));
149
- if (d.hintExpected !== void 0) this.setHint(start + d.hintOffset, d.hintExpected);
161
+ if (d.hintExpected !== void 0) this.state.setHint(start + d.hintOffset, d.hintExpected);
150
162
  }
151
163
  stack.push(new Child(green, start, end, void 0));
152
164
  return green.value;
@@ -154,29 +166,29 @@ var SyntaxState = class extends State {
154
166
  }
155
167
  const mark = stack.length;
156
168
  const outer = this.highWater;
157
- const outerDeepest = this.deepest;
158
- const hintOffset = this.hintOffset;
159
- const hintExpected = this.hintExpected;
169
+ const outerDeepest = this.state.deepest;
170
+ const hintOffset = this.state.hintOffset;
171
+ const hintExpected = this.state.hintExpected;
160
172
  this.highWater = start;
161
- this.deepest = void 0;
173
+ this.state.deepest = void 0;
162
174
  const a = step(state);
163
- const looked = this.highWater;
164
- if (outer > looked) this.highWater = outer;
165
- const deepest = this.deepest;
166
- this.deepest = outerDeepest;
175
+ const looked = this.looked();
176
+ this.highWater = outer > looked ? outer : looked;
177
+ const deepest = this.state.deepest;
178
+ this.state.deepest = outerDeepest;
167
179
  if (deepest !== void 0) this.deepen(deepest);
168
180
  if (a === Fail) {
169
181
  if (stack.length > mark) stack.length = mark;
170
182
  return a;
171
183
  }
172
- const end = this.cursor;
184
+ const end = this.state.pos;
173
185
  if (end === start) return a;
174
- const hinted = this.hintOffset !== hintOffset || this.hintExpected !== hintExpected;
186
+ const hinted = this.state.hintOffset !== hintOffset || this.state.hintExpected !== hintExpected;
175
187
  const diagnostics = deepest === void 0 && !hinted ? void 0 : {
176
188
  deepest,
177
189
  base: start,
178
- hintOffset: this.hintOffset - start,
179
- hintExpected: hinted ? this.hintExpected : void 0
190
+ hintOffset: this.state.hintOffset - start,
191
+ hintExpected: hinted ? this.state.hintExpected : void 0
180
192
  };
181
193
  const entries = stack.splice(mark);
182
194
  stack.push(new Child(build(kind, named, key, start, end, looked, entries, a, void 0, diagnostics), start, end, void 0));
@@ -187,7 +199,7 @@ var SyntaxState = class extends State {
187
199
  }
188
200
  /** Records `failure` as the furthest failure if it is, as `failWith` does. */
189
201
  deepen(failure) {
190
- if (this.deepest === void 0 || failure.offset >= this.deepest.offset) this.deepest = failure;
202
+ if (this.state.deepest === void 0 || failure.offset >= this.state.deepest.offset) this.state.deepest = failure;
191
203
  }
192
204
  field(state, step, name) {
193
205
  const stack = this.stack;
@@ -200,8 +212,8 @@ var SyntaxState = class extends State {
200
212
  const stack = this.stack;
201
213
  let i = stack.length;
202
214
  while (i > 0 && stack[i - 1].start >= start && stack[i - 1].end > start) i--;
203
- const end = this.cursor;
204
- const green = build(errorKind, true, void 0, start, end, this.highWater, stack.splice(i), void 0, {
215
+ const end = this.state.pos;
216
+ const green = build(errorKind, true, void 0, start, end, this.looked(), stack.splice(i), void 0, {
205
217
  failure: rebase(failure, start),
206
218
  mode
207
219
  });
@@ -214,9 +226,9 @@ var SyntaxState = class extends State {
214
226
  */
215
227
  finish(kind, value, fatal, errorStart) {
216
228
  const entries = this.stack.splice(0);
217
- const end = this.end;
229
+ const end = this.state.end;
218
230
  if (fatal !== void 0) {
219
- const last = entries.length > 0 ? entries[entries.length - 1].end : 0;
231
+ const last = Arr.isArrayNonEmpty(entries) ? Arr.lastNonEmpty(entries).end : 0;
220
232
  const start = Math.max(Math.min(errorStart, end), last);
221
233
  const error = build(errorKind, true, void 0, start, end, end, [], void 0, {
222
234
  failure: rebase(fatal.failure, start),
@@ -224,7 +236,7 @@ var SyntaxState = class extends State {
224
236
  });
225
237
  entries.push(new Child(error, start, end, void 0));
226
238
  }
227
- return build(kind, true, void 0, 0, end, Math.max(end, this.highWater), entries, value, void 0);
239
+ return build(kind, true, void 0, 0, end, Math.max(end, this.looked()), entries, value, void 0);
228
240
  }
229
241
  /**
230
242
  * The outermost node of the previous tree built by `key` that starts at
@@ -299,7 +311,6 @@ const tokenWidth = (input, offset) => {
299
311
  }
300
312
  return input instanceof Uint8Array ? 4 : 1;
301
313
  };
302
- //#endregion
303
- export { Green, SyntaxState, absolute, errorKind };
314
+ export { Green, SyntaxBuilder, absolute, errorKind };
304
315
 
305
316
  //# sourceMappingURL=syntax.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"syntax.js","names":[],"sources":["../../src/internal/syntax.ts"],"sourcesContent":["/**\n * The tree builder behind the `Syntax` module (see `docs/DESIGN.md`,\n * \"Syntax trees\").\n *\n * Trees are stored as *green* nodes, as in Roslyn and rust-analyzer: a green\n * node knows its kind, its width and its children's offsets relative to its\n * own start, but not where it is in the input or who its parent is. A subtree\n * that an edit doesn't touch can therefore be shared, unchanged, by the tree\n * before the edit and the tree after it. `Syntax.SyntaxNode` is the *red*\n * view: a green node, its absolute start and its parent, built lazily while\n * navigating.\n *\n * While parsing, completed nodes wait on a stack until the node around them\n * completes and adopts them. Nodes built by an attempt that is later\n * abandoned must not end up in the tree. Every combinator that abandons an\n * attempt moves the cursor back to (or before) where the attempt started,\n * and every node has a positive width, so the nodes of an abandoned attempt\n * are exactly those that end after the position the cursor moves back to:\n * the `pos` setter of {@link SyntaxState} drops them. This also covers\n * lookahead (`peek`, `not`) and custom parsers written with `Parser.make`.\n *\n * For incremental parsing, every node records how far its parse looked: the\n * furthest position the cursor reached and the furthest failure recorded\n * while it was being parsed (its *lookahead*). A node from the previous tree\n * is reused at a position when it was built by the same `Syntax.node`, and\n * the input it looked at, plus a margin for the tokens that read a little\n * past where they stop, is unchanged.\n */\nimport * as Predicate from \"effect/Predicate\"\nimport type * as Context from \"effect/Context\"\nimport type { Encoding } from \"../Encoding.js\"\nimport type { ErrMode, Input, Source } from \"../Input.js\"\nimport { Fail, Failure, State } from \"../Input.js\"\n\n/** What a failure inside an `ERROR` node was. Offsets are relative to the node. */\nexport interface ErrorInfo {\n readonly failure: Failure\n readonly mode: ErrMode\n}\n\n/** A position-independent syntax tree node. */\nexport class Green {\n constructor(\n readonly kind: string,\n readonly named: boolean,\n /** The `Syntax.node` that built it; `undefined` for roots and errors, which are never reused alone. */\n readonly key: object | undefined,\n readonly width: number,\n /** How far its parse looked, relative to its start (at least `width`). */\n readonly lookahead: number,\n readonly children: ReadonlyArray<Green>,\n /** The children's starts, relative to this node's start. */\n readonly offsets: ReadonlyArray<number>,\n /** The children's field names, when any child has one. */\n readonly fields: ReadonlyArray<string | undefined> | undefined,\n readonly value: unknown,\n /** Set on `ERROR` nodes. */\n readonly error: ErrorInfo | undefined,\n /** Whether this node or a descendant is an `ERROR` node. */\n readonly hasError: boolean,\n /** What its parse left behind for error reporting, replayed when it is reused. */\n readonly diagnostics: Diagnostics | undefined\n ) {}\n}\n\n/**\n * The error-reporting state a node's parse leaves behind (see\n * `State.deepest` and `State.setHint`). A reused node replays it, so that\n * a reparse reports the errors a fresh parse does.\n */\nexport interface Diagnostics {\n /** The furthest failure, at its offset in the parse that built the node... */\n readonly deepest: Failure | undefined\n /** ...which started the node at `base`. */\n readonly base: number\n /** Relative to the node's start. */\n readonly hintOffset: number\n readonly hintExpected: ReadonlyArray<string> | undefined\n}\n\n/** A completed node waiting for its parent, at an absolute position. */\nclass Child {\n constructor(\n readonly green: Green,\n readonly start: number,\n readonly end: number,\n public field: string | undefined\n ) {}\n}\n\nexport const errorKind = \"ERROR\"\n\nconst rebase = (f: Failure, start: number): Failure =>\n new Failure(f.offset - start, f.kind, f.expected, f.context, f.hasCause, f.cause, f.message, f.needed)\n\n/** Moves a failure stored relative to a node back to absolute offsets. */\nexport const absolute = (f: Failure, start: number): Failure => rebase(f, -start)\n\n/**\n * Builds a green node over `[start, end)` from the children waiting on the\n * stack.\n */\nconst build = (\n kind: string,\n named: boolean,\n key: object | undefined,\n start: number,\n end: number,\n lookahead: number,\n entries: ReadonlyArray<Child>,\n value: unknown,\n error: ErrorInfo | undefined,\n diagnostics?: Diagnostics\n): Green => {\n const n = entries.length\n const children = new Array<Green>(n)\n const offsets = new Array<number>(n)\n let fields: Array<string | undefined> | undefined\n let hasError = error !== undefined\n for (let i = 0; i < n; i++) {\n const e = entries[i]\n children[i] = e.green\n offsets[i] = e.start - start\n if (e.green.hasError) hasError = true\n if (e.field !== undefined) (fields ??= new Array(n).fill(undefined))[i] = e.field\n }\n const width = end - start\n const looked = Math.max(lookahead, end) - start\n return new Green(kind, named, key, width, looked, children, offsets, fields, value, error, hasError, diagnostics)\n}\n\n/**\n * A stretch of the new input copied unchanged from the previous one:\n * `[newStart, newStart + length)` is `[oldStart, oldStart + length)`.\n */\nexport interface Segment {\n readonly newStart: number\n readonly oldStart: number\n readonly length: number\n}\n\n/** What a reparse may reuse. */\nexport interface Previous {\n readonly root: Green\n readonly oldLength: number\n readonly newLength: number\n readonly segments: ReadonlyArray<Segment>\n readonly input: Input\n /** How far past its lookahead a parser may have read, besides a token at the lookahead. */\n readonly extra: number\n readonly encoding: Encoding<any> | undefined\n}\n\n/** The hooks that `Syntax` combinators and `Parser.resumeAfter`/`retryAfter` call. */\nexport interface Builder {\n node(state: State<any>, step: (state: State<any>) => unknown, key: object, kind: string, named: boolean): unknown\n field(state: State<any>, step: (state: State<any>) => unknown, name: string): unknown\n /** After error recovery: `[start, pos)` was skipped after `failure`. */\n skipped(start: number, failure: Failure, mode: ErrMode): void\n /**\n * Called by token parsers that read input up to `end` (exclusive) beyond\n * where they leave the cursor or record a failure.\n */\n read(end: number): void\n}\n\n/** The parse state of a `Syntax` parse. */\nexport class SyntaxState<I extends Input = Input> extends State<I> implements Builder {\n // Declared, not defined: `State`'s constructor sets `pos` through the\n // accessor below before these could be initialized\n declare cursor: number\n /** The furthest position the cursor reached, or failure recorded, since the innermost open node started. */\n declare highWater: number\n /** Completed nodes waiting for their parent, in input order. */\n declare stack: Array<Child>\n declare previous: Previous | undefined\n /** How many nodes were reused from the previous tree. */\n declare reused: number\n /** Where {@link find} found the last node it found. */\n declare lastParent: Green | undefined\n declare lastParentStart: number\n\n static {\n Object.defineProperty(this.prototype, \"pos\", {\n get(this: SyntaxState) {\n return this.cursor\n },\n set(this: SyntaxState, p: number) {\n if (p < this.cursor) {\n // An attempt was abandoned (or a lookahead finished): drop its nodes\n const stack = this.stack\n while (stack.length > 0 && stack[stack.length - 1].end > p) stack.pop()\n }\n if (p > this.highWater) this.highWater = p\n this.cursor = p\n },\n configurable: true,\n enumerable: true\n })\n }\n\n constructor(\n source: I | Source<I>,\n options: {\n readonly context?: Context.Context<never> | undefined\n },\n previous: Previous | undefined\n ) {\n super(source, { context: options.context })\n this.highWater = this.cursor\n this.stack = []\n this.previous = previous\n this.reused = 0\n this.lastParent = undefined\n this.lastParentStart = 0\n this.syntax = this\n // Error recovery is always on: like Tree-sitter, a syntax parse always produces a tree\n this.recovered = []\n }\n\n override failWith(mode: ErrMode, failure: Failure): Fail {\n if (failure.offset > this.highWater) this.highWater = failure.offset\n return super.failWith(mode, failure)\n }\n\n override setHint(offset: number, expected: ReadonlyArray<string>): void {\n if (offset > this.highWater) this.highWater = offset\n super.setHint(offset, expected)\n }\n\n node(state: State<any>, step: (state: State<any>) => unknown, key: object, kind: string, named: boolean): unknown {\n const start = this.cursor\n const stack = this.stack\n if (this.previous !== undefined) {\n const green = this.reusable(this.previous, key, start)\n if (green !== undefined) {\n this.reused++\n const end = start + green.width\n state.pos = end\n const looked = start + green.lookahead\n if (looked > this.highWater) this.highWater = looked\n const d = green.diagnostics\n if (d !== undefined) {\n if (d.deepest !== undefined) this.deepen(start === d.base ? d.deepest : rebase(d.deepest, d.base - start))\n if (d.hintExpected !== undefined) this.setHint(start + d.hintOffset, d.hintExpected)\n }\n stack.push(new Child(green, start, end, undefined))\n return green.value\n }\n }\n const mark = stack.length\n const outer = this.highWater\n const outerDeepest = this.deepest\n const hintOffset = this.hintOffset\n const hintExpected = this.hintExpected\n this.highWater = start\n // Collect the furthest failure of this node alone, then merge it as `failWith` would have\n this.deepest = undefined\n const a = step(state)\n const looked = this.highWater\n if (outer > looked) this.highWater = outer\n const deepest = this.deepest as Failure | undefined\n this.deepest = outerDeepest\n if (deepest !== undefined) this.deepen(deepest)\n if (a === Fail) {\n if (stack.length > mark) stack.length = mark\n return a\n }\n const end = this.cursor\n // Like Tree-sitter's rules, nodes are never empty: an empty match adds nothing to the tree\n if (end === start) return a\n const hinted = this.hintOffset !== hintOffset || this.hintExpected !== hintExpected\n const diagnostics: Diagnostics | undefined =\n deepest === undefined && !hinted\n ? undefined\n : {\n deepest,\n base: start,\n hintOffset: this.hintOffset - start,\n hintExpected: hinted ? this.hintExpected : undefined\n }\n const entries = stack.splice(mark)\n stack.push(\n new Child(build(kind, named, key, start, end, looked, entries, a, undefined, diagnostics), start, end, undefined)\n )\n return a\n }\n\n read(end: number): void {\n // `highWater` is the last position looked at, `end` is exclusive\n if (end - 1 > this.highWater) this.highWater = end - 1\n }\n\n /** Records `failure` as the furthest failure if it is, as `failWith` does. */\n private deepen(failure: Failure): void {\n if (this.deepest === undefined || failure.offset >= this.deepest.offset) this.deepest = failure\n }\n\n field(state: State<any>, step: (state: State<any>) => unknown, name: string): unknown {\n const stack = this.stack\n const mark = stack.length\n const a = step(state)\n if (a !== Fail) for (let i = mark; i < stack.length; i++) stack[i].field = name\n return a\n }\n\n skipped(start: number, failure: Failure, mode: ErrMode): void {\n const stack = this.stack\n let i = stack.length\n while (i > 0 && stack[i - 1].start >= start && stack[i - 1].end > start) i--\n const end = this.cursor\n const green = build(errorKind, true, undefined, start, end, this.highWater, stack.splice(i), undefined, {\n failure: rebase(failure, start),\n mode\n })\n stack.push(new Child(green, start, end, undefined))\n }\n\n /**\n * Builds the root over the whole input from the nodes left on the stack.\n * When the parse failed, or stopped before the end, the rest of the input\n * becomes an `ERROR` node.\n */\n finish(kind: string, value: unknown, fatal: ErrorInfo | undefined, errorStart: number): Green {\n const entries = this.stack.splice(0)\n const end = this.end\n if (fatal !== undefined) {\n const last = entries.length > 0 ? entries[entries.length - 1].end : 0\n const start = Math.max(Math.min(errorStart, end), last)\n const error = build(errorKind, true, undefined, start, end, end, [], undefined, {\n failure: rebase(fatal.failure, start),\n mode: fatal.mode\n })\n entries.push(new Child(error, start, end, undefined))\n }\n return build(kind, true, undefined, 0, end, Math.max(end, this.highWater), entries, value, undefined)\n }\n\n /**\n * The outermost node of the previous tree built by `key` that starts at\n * `offset`. Reused nodes are mostly siblings, found one after the other,\n * so the search starts from the parent of the last one found when\n * `offset` lies inside it: no ancestor of that parent can start there.\n */\n private find(root: Green, offset: number, key: object): Green | undefined {\n let node = root\n let start = 0\n const last = this.lastParent\n if (last !== undefined && offset > this.lastParentStart && offset < this.lastParentStart + last.width) {\n node = last\n start = this.lastParentStart\n }\n while (true) {\n const offsets = node.offsets\n // The last child starting at or before `offset`\n let lo = 0\n let hi = offsets.length - 1\n let found = -1\n while (lo <= hi) {\n const mid = (lo + hi) >> 1\n if (start + offsets[mid] <= offset) {\n found = mid\n lo = mid + 1\n } else {\n hi = mid - 1\n }\n }\n if (found < 0) return undefined\n const child = node.children[found]\n const childStart = start + offsets[found]\n if (offset >= childStart + child.width) return undefined\n if (childStart === offset && child.key === key) {\n this.lastParent = node\n this.lastParentStart = start\n return child\n }\n node = child\n start = childStart\n }\n }\n\n /** The node of the previous tree built by `key` at `pos` (in the new input), if it can be reused. */\n private reusable(previous: Previous, key: object, pos: number): Green | undefined {\n const segments = previous.segments\n // The segment containing `pos`\n let lo = 0\n let hi = segments.length - 1\n while (lo <= hi) {\n const mid = (lo + hi) >> 1\n const seg = segments[mid]\n if (pos < seg.newStart) hi = mid - 1\n else if (pos >= seg.newStart + seg.length) lo = mid + 1\n else {\n const old = seg.oldStart + (pos - seg.newStart)\n const green = this.find(previous.root, old, key)\n if (green === undefined) return undefined\n const segEnd = seg.oldStart + seg.length\n // The input it looked at must be unchanged; past the end of both inputs counts as unchanged\n if (old + green.lookahead + tokenWidth(previous.input, old + green.lookahead) + previous.extra <= segEnd) {\n return green\n }\n if (segEnd === previous.oldLength && seg.newStart + seg.length === previous.newLength) return green\n return undefined\n }\n }\n return undefined\n }\n}\n\n/**\n * How many units a token parser may read at `offset`, where a parse\n * stopped looking: one code point. Of a string, that is two units at a high\n * surrogate. Of bytes in an unknown encoding, up to four.\n */\nconst tokenWidth = (input: Input, offset: number): number => {\n if (Predicate.isString(input)) {\n const c = input.charCodeAt(offset)\n return c >= 0xd800 && c <= 0xdbff ? 2 : 1\n }\n return input instanceof Uint8Array ? 4 : 1\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"syntax.js","names":[],"sources":["../../src/internal/syntax.ts"],"sourcesContent":["/**\n * The tree builder behind the `Syntax` module (see `docs/DESIGN.md`,\n * \"Syntax trees\").\n *\n * Trees are stored as *green* nodes, as in Roslyn and rust-analyzer: a green\n * node knows its kind, its width and its children's offsets relative to its\n * own start, but not where it is in the input or who its parent is. A subtree\n * that an edit doesn't touch can therefore be shared, unchanged, by the tree\n * before the edit and the tree after it. `Syntax.SyntaxNode` is the *red*\n * view: a green node, its absolute start and its parent, built lazily while\n * navigating.\n *\n * While parsing, completed nodes wait on a stack until the node around them\n * completes and adopts them. Nodes built by an attempt that is later\n * abandoned must not end up in the tree. Every combinator that abandons an\n * attempt moves the cursor back to (or before) where the attempt started,\n * with `State.rewind`, and every node has a positive width, so the nodes of\n * an abandoned attempt are exactly those that end after the position the\n * cursor moves back to: {@link SyntaxBuilder} drops them when told of the rewind. This also\n * covers lookahead (`peek`, `not`) and custom parsers written with\n * `Parser.make`, which rewind the same way.\n *\n * `pos` stays a plain field, not an accessor that would watch every move: a\n * `pos` accessor on this subclass made every parser's cursor accesses\n * polymorphic, slowing ordinary parses by about a fifth in any program that\n * also built a syntax tree, and the syntax parse itself about twofold.\n *\n * For incremental parsing, every node records how far its parse looked: the\n * furthest position the cursor reached and the furthest failure recorded\n * while it was being parsed (its *lookahead*). The cursor only moves forward\n * between rewinds, so the furthest position is where it was at a rewind, or\n * where it is now. A node from the previous tree\n * is reused at a position when it was built by the same `Syntax.node`, and\n * the input it looked at, plus a margin for the tokens that read a little\n * past where they stop, is unchanged.\n */\nimport * as Arr from \"effect/Array\"\nimport * as Predicate from \"effect/Predicate\"\nimport type { Encoding } from \"../Encoding.js\"\nimport type { ErrMode, Input } from \"../Input.js\"\nimport { Fail, Failure, State } from \"../Input.js\"\nimport type { Key } from \"./key.js\"\n\n/** What a failure inside an `ERROR` node was. Offsets are relative to the node. */\nexport interface ErrorInfo {\n readonly failure: Failure\n readonly mode: ErrMode\n}\n\n/** A position-independent syntax tree node. */\nexport class Green {\n constructor(\n readonly kind: string,\n readonly named: boolean,\n /** The `Syntax.node` that built it; `undefined` for roots and errors, which are never reused alone. */\n readonly key: Key | undefined,\n readonly width: number,\n /** How far its parse looked, relative to its start (at least `width`). */\n readonly lookahead: number,\n readonly children: ReadonlyArray<Green>,\n /** The children's starts, relative to this node's start. */\n readonly offsets: ReadonlyArray<number>,\n /** The children's field names, when any child has one. */\n readonly fields: ReadonlyArray<string | undefined> | undefined,\n readonly value: unknown,\n /** Set on `ERROR` nodes. */\n readonly error: ErrorInfo | undefined,\n /** Whether this node or a descendant is an `ERROR` node. */\n readonly hasError: boolean,\n /** What its parse left behind for error reporting, replayed when it is reused. */\n readonly diagnostics: Diagnostics | undefined\n ) {}\n}\n\n/**\n * The error-reporting state a node's parse leaves behind (see\n * `State.deepest` and `State.setHint`). A reused node replays it, so that\n * a reparse reports the errors a fresh parse does.\n */\nexport interface Diagnostics {\n /** The furthest failure, at its offset in the parse that built the node... */\n readonly deepest: Failure | undefined\n /** ...which started the node at `base`. */\n readonly base: number\n /** Relative to the node's start. */\n readonly hintOffset: number\n readonly hintExpected: ReadonlyArray<string> | undefined\n}\n\n/** A completed node waiting for its parent, at an absolute position. */\nclass Child {\n constructor(\n readonly green: Green,\n readonly start: number,\n readonly end: number,\n public field: string | undefined\n ) {}\n}\n\nexport const errorKind = \"ERROR\"\n\nconst rebase = (f: Failure, start: number): Failure =>\n new Failure(f.offset - start, f.kind, f.expected, f.context, f.hasCause, f.cause, f.message, f.needed)\n\n/** Moves a failure stored relative to a node back to absolute offsets. */\nexport const absolute = (f: Failure, start: number): Failure => rebase(f, -start)\n\n/**\n * Builds a green node over `[start, end)` from the children waiting on the\n * stack.\n */\nconst build = (\n kind: string,\n named: boolean,\n key: Key | undefined,\n start: number,\n end: number,\n lookahead: number,\n entries: ReadonlyArray<Child>,\n value: unknown,\n error: ErrorInfo | undefined,\n diagnostics?: Diagnostics\n): Green => {\n const n = entries.length\n const children = new Array<Green>(n)\n const offsets = new Array<number>(n)\n let fields: Array<string | undefined> | undefined\n let hasError = error !== undefined\n for (let i = 0; i < n; i++) {\n const e = entries[i]\n children[i] = e.green\n offsets[i] = e.start - start\n if (e.green.hasError) hasError = true\n if (e.field !== undefined) (fields ??= new Array(n).fill(undefined))[i] = e.field\n }\n const width = end - start\n const looked = Math.max(lookahead, end) - start\n return new Green(kind, named, key, width, looked, children, offsets, fields, value, error, hasError, diagnostics)\n}\n\n/**\n * A stretch of the new input copied unchanged from the previous one:\n * `[newStart, newStart + length)` is `[oldStart, oldStart + length)`.\n */\nexport interface Segment {\n readonly newStart: number\n readonly oldStart: number\n readonly length: number\n}\n\n/** What a reparse may reuse. */\nexport interface Previous {\n readonly root: Green\n readonly oldLength: number\n readonly newLength: number\n readonly segments: ReadonlyArray<Segment>\n readonly input: Input\n /** How far past its lookahead a parser may have read, besides a token at the lookahead. */\n readonly extra: number\n readonly encoding: Encoding<any> | undefined\n}\n\n/** The hooks that `Syntax` combinators and `Parser.resumeAfter`/`retryAfter` call. */\nexport interface Builder {\n node(state: State<any>, step: (state: State<any>) => unknown, key: Key, kind: string, named: boolean): unknown\n field(state: State<any>, step: (state: State<any>) => unknown, name: string): unknown\n /** After error recovery: `[start, pos)` was skipped after `failure`. */\n skipped(start: number, failure: Failure, mode: ErrMode): void\n /**\n * Called by token parsers that read input up to `end` (exclusive) beyond\n * where they leave the cursor or record a failure.\n */\n read(end: number): void\n /** A failure or hint was recorded at `offset`. */\n reach(offset: number): void\n /** The cursor moved back from `from` to `to` (see `State.rewind`). */\n rewound(from: number, to: number): void\n}\n\n/**\n * The tree builder of a `Syntax` parse, reached through `state.syntax`. It\n * is not a `State` subclass: one class of state keeps every parser's cursor\n * and failure accesses monomorphic, whether or not the program also builds\n * syntax trees. `State` calls {@link reach} and {@link rewound} itself.\n */\nexport class SyntaxBuilder implements Builder {\n /**\n * The furthest position the cursor reached before a rewind, or failure\n * recorded, since the innermost open node started; {@link looked} adds\n * where the cursor is now.\n */\n highWater: number\n /** Completed nodes waiting for their parent, in input order. */\n readonly stack: Array<Child> = []\n /** How many nodes were reused from the previous tree. */\n reused = 0\n /** Where {@link find} found the last node it found. */\n lastParent: Green | undefined = undefined\n lastParentStart = 0\n\n constructor(\n readonly state: State<any>,\n readonly previous: Previous | undefined\n ) {\n this.highWater = state.pos\n state.syntax = this\n // Error recovery is always on: like Tree-sitter, a syntax parse always produces a tree\n state.recovered = []\n }\n\n reach(offset: number): void {\n if (offset > this.highWater) this.highWater = offset\n }\n\n rewound(from: number, to: number): void {\n if (from > this.highWater) this.highWater = from\n // An attempt was abandoned (or a lookahead finished): drop its nodes\n const stack = this.stack\n while (Arr.isArrayNonEmpty(stack) && Arr.lastNonEmpty(stack).end > to) stack.pop()\n }\n\n /** How far the parse looked: {@link highWater}, or the cursor if it is further. */\n private looked(): number {\n return this.state.pos > this.highWater ? this.state.pos : this.highWater\n }\n\n node(state: State<any>, step: (state: State<any>) => unknown, key: Key, kind: string, named: boolean): unknown {\n const start = this.state.pos\n const stack = this.stack\n if (this.previous !== undefined) {\n const green = this.reusable(this.previous, key, start)\n if (green !== undefined) {\n this.reused++\n const end = start + green.width\n state.pos = end\n const looked = start + green.lookahead\n if (looked > this.highWater) this.highWater = looked\n const d = green.diagnostics\n if (d !== undefined) {\n if (d.deepest !== undefined) this.deepen(start === d.base ? d.deepest : rebase(d.deepest, d.base - start))\n if (d.hintExpected !== undefined) this.state.setHint(start + d.hintOffset, d.hintExpected)\n }\n stack.push(new Child(green, start, end, undefined))\n return green.value\n }\n }\n const mark = stack.length\n const outer = this.highWater\n const outerDeepest = this.state.deepest\n const hintOffset = this.state.hintOffset\n const hintExpected = this.state.hintExpected\n this.highWater = start\n // Collect the furthest failure of this node alone, then merge it as `failWith` would have\n this.state.deepest = undefined\n const a = step(state)\n const looked = this.looked()\n this.highWater = outer > looked ? outer : looked\n const deepest = this.state.deepest as Failure | undefined\n this.state.deepest = outerDeepest\n if (deepest !== undefined) this.deepen(deepest)\n if (a === Fail) {\n if (stack.length > mark) stack.length = mark\n return a\n }\n const end = this.state.pos\n // Like Tree-sitter's rules, nodes are never empty: an empty match adds nothing to the tree\n if (end === start) return a\n const hinted = this.state.hintOffset !== hintOffset || this.state.hintExpected !== hintExpected\n const diagnostics: Diagnostics | undefined =\n deepest === undefined && !hinted\n ? undefined\n : {\n deepest,\n base: start,\n hintOffset: this.state.hintOffset - start,\n hintExpected: hinted ? this.state.hintExpected : undefined\n }\n const entries = stack.splice(mark)\n stack.push(\n new Child(build(kind, named, key, start, end, looked, entries, a, undefined, diagnostics), start, end, undefined)\n )\n return a\n }\n\n read(end: number): void {\n // `highWater` is the last position looked at, `end` is exclusive\n if (end - 1 > this.highWater) this.highWater = end - 1\n }\n\n /** Records `failure` as the furthest failure if it is, as `failWith` does. */\n private deepen(failure: Failure): void {\n if (this.state.deepest === undefined || failure.offset >= this.state.deepest.offset) this.state.deepest = failure\n }\n\n field(state: State<any>, step: (state: State<any>) => unknown, name: string): unknown {\n const stack = this.stack\n const mark = stack.length\n const a = step(state)\n if (a !== Fail) for (let i = mark; i < stack.length; i++) stack[i].field = name\n return a\n }\n\n skipped(start: number, failure: Failure, mode: ErrMode): void {\n const stack = this.stack\n let i = stack.length\n while (i > 0 && stack[i - 1].start >= start && stack[i - 1].end > start) i--\n const end = this.state.pos\n const green = build(errorKind, true, undefined, start, end, this.looked(), stack.splice(i), undefined, {\n failure: rebase(failure, start),\n mode\n })\n stack.push(new Child(green, start, end, undefined))\n }\n\n /**\n * Builds the root over the whole input from the nodes left on the stack.\n * When the parse failed, or stopped before the end, the rest of the input\n * becomes an `ERROR` node.\n */\n finish(kind: string, value: unknown, fatal: ErrorInfo | undefined, errorStart: number): Green {\n const entries = this.stack.splice(0)\n const end = this.state.end\n if (fatal !== undefined) {\n const last = Arr.isArrayNonEmpty(entries) ? Arr.lastNonEmpty(entries).end : 0\n const start = Math.max(Math.min(errorStart, end), last)\n const error = build(errorKind, true, undefined, start, end, end, [], undefined, {\n failure: rebase(fatal.failure, start),\n mode: fatal.mode\n })\n entries.push(new Child(error, start, end, undefined))\n }\n return build(kind, true, undefined, 0, end, Math.max(end, this.looked()), entries, value, undefined)\n }\n\n /**\n * The outermost node of the previous tree built by `key` that starts at\n * `offset`. Reused nodes are mostly siblings, found one after the other,\n * so the search starts from the parent of the last one found when\n * `offset` lies inside it: no ancestor of that parent can start there.\n */\n private find(root: Green, offset: number, key: Key): Green | undefined {\n let node = root\n let start = 0\n const last = this.lastParent\n if (last !== undefined && offset > this.lastParentStart && offset < this.lastParentStart + last.width) {\n node = last\n start = this.lastParentStart\n }\n while (true) {\n const offsets = node.offsets\n // The last child starting at or before `offset`\n let lo = 0\n let hi = offsets.length - 1\n let found = -1\n while (lo <= hi) {\n const mid = (lo + hi) >> 1\n if (start + offsets[mid] <= offset) {\n found = mid\n lo = mid + 1\n } else {\n hi = mid - 1\n }\n }\n if (found < 0) return undefined\n const child = node.children[found]\n const childStart = start + offsets[found]\n if (offset >= childStart + child.width) return undefined\n if (childStart === offset && child.key === key) {\n this.lastParent = node\n this.lastParentStart = start\n return child\n }\n node = child\n start = childStart\n }\n }\n\n /** The node of the previous tree built by `key` at `pos` (in the new input), if it can be reused. */\n private reusable(previous: Previous, key: Key, pos: number): Green | undefined {\n const segments = previous.segments\n // The segment containing `pos`\n let lo = 0\n let hi = segments.length - 1\n while (lo <= hi) {\n const mid = (lo + hi) >> 1\n const seg = segments[mid]\n if (pos < seg.newStart) hi = mid - 1\n else if (pos >= seg.newStart + seg.length) lo = mid + 1\n else {\n const old = seg.oldStart + (pos - seg.newStart)\n const green = this.find(previous.root, old, key)\n if (green === undefined) return undefined\n const segEnd = seg.oldStart + seg.length\n // The input it looked at must be unchanged; past the end of both inputs counts as unchanged\n if (old + green.lookahead + tokenWidth(previous.input, old + green.lookahead) + previous.extra <= segEnd) {\n return green\n }\n if (segEnd === previous.oldLength && seg.newStart + seg.length === previous.newLength) return green\n return undefined\n }\n }\n return undefined\n }\n}\n\n/**\n * How many units a token parser may read at `offset`, where a parse\n * stopped looking: one code point. Of a string, that is two units at a high\n * surrogate. Of bytes in an unknown encoding, up to four.\n */\nconst tokenWidth = (input: Input, offset: number): number => {\n if (Predicate.isString(input)) {\n const c = input.charCodeAt(offset)\n return c >= 0xd800 && c <= 0xdbff ? 2 : 1\n }\n return input instanceof Uint8Array ? 4 : 1\n}\n"],"mappings":"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"}
@@ -1,12 +1,16 @@
1
1
  import { Fail, State } from "../Input.js";
2
2
  import { Encoding } from "../Encoding.js";
3
- //#region src/internal/text.d.ts
4
3
  /** `Encoding.decode`: the input is malformed. */
5
4
  export declare const Invalid = -1;
6
5
  /** `Encoding.decode`: the input ends inside a sequence. */
7
6
  export declare const Truncated = -2;
8
7
  /** `next`: the input has ended. */
9
8
  export declare const End = -3;
9
+ /**
10
+ * Whether an input, a literal or a chunk has no units (characters, bytes or
11
+ * tokens).
12
+ */
13
+ export declare const isEmptyUnits: (units: string | Uint8Array | ReadonlyArray<unknown>) => boolean;
10
14
  /** @internal */
11
15
  export declare const fastLimit: (enc: Encoding<any>) => number;
12
16
  /**
@@ -76,5 +80,4 @@ export declare const fold: (cp: number) => number;
76
80
  export declare const walk: (enc: Encoding<any>, input: string | Uint8Array, start: number, end: number, f: (cp: number, offset: number, width: number) => boolean | void) => void;
77
81
  /** Decodes `[start, end)`, replacing malformed sequences with U+FFFD. */
78
82
  export declare const lenientText: (enc: Encoding<any>, input: string | Uint8Array, start: number, end: number) => string;
79
- //#endregion
80
83
  //# sourceMappingURL=text.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"text.d.ts","names":[],"sources":["../../src/internal/text.ts"],"mappings":";;;;qBAQa;;qBAEA;;qBAEA;;qBAaA,YAAa,KAAK;;;;;;qBAUlB,iBAAkB;;qBAGlB,SAAU;;;;;qBAkBV,QAAQ;;qBA6DR,MAAM,SAAS;;qBAkEf,SAAS,SAAS;;qBAGlB,SAAS,SAAS;;qBAGlB,QAAQ,SAAS;;mBA8BnB;;;;;;;qBAQE,OAAQ,KAAK,eAAe,OAAO,YAAY;;;;;qBAe/C,SACX,OAAO,YACP,YACA,MAAM,WAAW,wBACjB,UAAU,uBACV,oBACC;;mBAQQ;;mBAEA;;;;;mBAKA;;;;;qBAME,OACX,KAAK,eACL,OAAO,YACP,OAAO,wBACP,iBACA,aACA,cACA;;;;;qBA+DW,WAAY,KAAK,eAAe,OAAO,YAAY,eAAe;;;;;;qBA2BlE,OAAQ;;;;;qBAsBR,OACX,KAAK,eACL,gBAAgB,YAChB,eACA,aACA,IAAI,YAAY,gBAAgB;;qBAkBrB,cAAe,KAAK,eAAe,gBAAgB,YAAY,eAAe"}
1
+ {"version":3,"file":"text.d.ts","names":[],"sources":["../../src/internal/text.ts"],"mappings":";;;qBAWa;;qBAEA;;qBAEA;;;;;qBAgBA,eAAgB,gBAAgB,aAAa;;qBAQ7C,YAAa,KAAK;;;;;;qBAUlB,iBAAkB;;qBAGlB,SAAU;;;;;qBAkBV,QAAQ;;qBA8DR,MAAM,SAAS;;qBAuEf,SAAS,SAAS;;qBAGlB,SAAS,SAAS;;qBAGlB,QAAQ,SAAS;;mBA8BnB;;;;;;;qBAQE,OAAQ,KAAK,eAAe,OAAO,YAAY;;;;;qBAe/C,SACX,OAAO,YACP,YACA,MAAM,WAAW,wBACjB,UAAU,uBACV,oBACC;;mBAQQ;;mBAEA;;;;;mBAKA;;;;;qBAME,OACX,KAAK,eACL,OAAO,YACP,OAAO,wBACP,iBACA,aACA,cACA;;;;;qBA+DW,WAAY,KAAK,eAAe,OAAO,YAAY,eAAe;;;;;;qBA2BlE,OAAQ;;;;;qBAsBR,OACX,KAAK,eACL,gBAAgB,YAChB,eACA,aACA,IAAI,YAAY,gBAAgB;;qBAkBrB,cAAe,KAAK,eAAe,gBAAgB,YAAY,eAAe"}
@@ -1,4 +1,7 @@
1
- //#region src/internal/text.ts
1
+ import * as Predicate from "effect/Predicate";
2
+ import * as Arr from "effect/Array";
3
+ import * as Str from "effect/String";
4
+ // src/internal/text.ts
2
5
  /** `Encoding.decode`: the input is malformed. */
3
6
  const Invalid = -1;
4
7
  /** `Encoding.decode`: the input ends inside a sequence. */
@@ -10,6 +13,11 @@ const End = -3;
10
13
  * skip `decode`. Defaults to 0x80 for ASCII compatible encodings.
11
14
  */
12
15
  const FastLimit = /*#__PURE__*/ Symbol.for("effect-parse/Encoding/FastLimit");
16
+ /**
17
+ * Whether an input, a literal or a chunk has no units (characters, bytes or
18
+ * tokens).
19
+ */
20
+ const isEmptyUnits = (units) => Predicate.isString(units) ? Str.isEmpty(units) : units instanceof Uint8Array ? units.byteLength === 0 : Arr.isReadonlyArrayEmpty(units);
13
21
  /** @internal */
14
22
  const fastLimit = (enc) => enc[FastLimit] ?? (enc.asciiCompatible && enc.unit === 1 ? 128 : 0);
15
23
  const asciiChars = /*#__PURE__*/ Array.from({ length: 128 }, (_, i) => String.fromCharCode(i));
@@ -109,7 +117,8 @@ const utf8 = {
109
117
  }
110
118
  }
111
119
  return out;
112
- }
120
+ },
121
+ [FastLimit]: 128
113
122
  };
114
123
  const makeUtf16 = (littleEndian) => {
115
124
  const lo = littleEndian ? 0 : 1;
@@ -146,7 +155,8 @@ const makeUtf16 = (littleEndian) => {
146
155
  }
147
156
  decoder ??= new TextDecoder(littleEndian ? "utf-16le" : "utf-16be", { ignoreBOM: true });
148
157
  return decodeRange(decoder, b, start, end);
149
- }
158
+ },
159
+ [FastLimit]: 0
150
160
  };
151
161
  };
152
162
  /** UTF-16 bytes, little endian. */
@@ -335,7 +345,6 @@ const lenientText = (enc, input, start, end) => {
335
345
  });
336
346
  return out;
337
347
  };
338
- //#endregion
339
- export { End, Invalid, Truncated, charOf, failAt, fastLimit, firstCodePoint, fold, latin1, lenientText, next, scan, scanCount, scanOffset, scanStop, string, utf16be, utf16le, utf8, validate, walk, width };
348
+ export { End, Invalid, Truncated, charOf, failAt, fastLimit, firstCodePoint, fold, isEmptyUnits, latin1, lenientText, next, scan, scanCount, scanOffset, scanStop, string, utf16be, utf16le, utf8, validate, walk, width };
340
349
 
341
350
  //# sourceMappingURL=text.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"text.js","names":[],"sources":["../../src/internal/text.ts"],"sourcesContent":["import type { Encoding } from \"../Encoding.js\"\nimport type { Fail, State } from \"../Input.js\"\n\n// -----------------------------------------------------------------------------\n// Decoding results\n// -----------------------------------------------------------------------------\n\n/** `Encoding.decode`: the input is malformed. */\nexport const Invalid = -1\n/** `Encoding.decode`: the input ends inside a sequence. */\nexport const Truncated = -2\n/** `next`: the input has ended. */\nexport const End = -3\n\n// -----------------------------------------------------------------------------\n// Encodings\n// -----------------------------------------------------------------------------\n\n/**\n * Units below this value decode to themselves with width 1, so hot loops can\n * skip `decode`. Defaults to 0x80 for ASCII compatible encodings.\n */\nconst FastLimit: unique symbol = /*#__PURE__*/ Symbol.for(\"effect-parse/Encoding/FastLimit\")\n\n/** @internal */\nexport const fastLimit = (enc: Encoding<any>): number =>\n (enc as any)[FastLimit] ?? (enc.asciiCompatible && enc.unit === 1 ? 0x80 : 0)\n\nconst asciiChars: ReadonlyArray<string> = /*#__PURE__*/ Array.from({ length: 128 }, (_, i) => String.fromCharCode(i))\n\n/**\n * The code point that starts `s`: for a string known to hold one, such as\n * one element of `Array.from(string)`. On an empty string it is `NaN`, which,\n * like the `undefined` of `codePointAt(0)`, matches no code point.\n */\nexport const firstCodePoint = (s: string): number => s.codePointAt(0) ?? Number.NaN\n\n/** `String.fromCodePoint`, with the ASCII characters cached. */\nexport const charOf = (cp: number): string =>\n cp < 128 ? asciiChars[cp] : cp < 0x10000 ? String.fromCharCode(cp) : String.fromCodePoint(cp)\n\nconst decodeString = (s: string, i: number, end: number): number => {\n const c = s.charCodeAt(i)\n if ((c & 0xf800) !== 0xd800) return c\n if (c <= 0xdbff) {\n if (i + 1 >= end) return Truncated\n const d = s.charCodeAt(i + 1)\n if ((d & 0xfc00) === 0xdc00) return ((c - 0xd800) << 10) + (d - 0xdc00) + 0x10000\n }\n return Invalid\n}\n\n/**\n * JavaScript strings: UTF-16 code units. Offsets are code-unit indices and\n * slices are `String.prototype.slice`s, so no decoding is needed.\n */\nexport const string: Encoding<string> = {\n name: \"UTF-16\",\n unit: 1,\n asciiCompatible: true,\n decode: decodeString,\n width: (cp) => (cp > 0xffff ? 2 : 1),\n encode: (text) => text,\n text: (s, start, end) => s.slice(start, end),\n [FastLimit]: 0xd800\n} as Encoding<string>\n\nconst decodeUtf8 = (b: Uint8Array, i: number, end: number): number => {\n const c = b[i]\n if (c < 0x80) return c\n if (c < 0xc2) return Invalid\n if (c < 0xe0) {\n if (i + 1 >= end) return Truncated\n const d = b[i + 1]\n return (d & 0xc0) === 0x80 ? ((c & 0x1f) << 6) | (d & 0x3f) : Invalid\n }\n if (c < 0xf0) {\n if (i + 1 >= end) return Truncated\n const d = b[i + 1]\n // Reject overlong encodings (E0 80..9F) and surrogates (ED A0..BF)\n if (c === 0xe0 ? d < 0xa0 || d > 0xbf : c === 0xed ? d < 0x80 || d > 0x9f : (d & 0xc0) !== 0x80) return Invalid\n if (i + 2 >= end) return Truncated\n const e = b[i + 2]\n return (e & 0xc0) === 0x80 ? ((c & 0x0f) << 12) | ((d & 0x3f) << 6) | (e & 0x3f) : Invalid\n }\n if (c < 0xf5) {\n if (i + 1 >= end) return Truncated\n const d = b[i + 1]\n // Reject overlong encodings (F0 80..8F) and code points above U+10FFFF (F4 90..BF)\n if (c === 0xf0 ? d < 0x90 || d > 0xbf : c === 0xf4 ? d < 0x80 || d > 0x8f : (d & 0xc0) !== 0x80) return Invalid\n if (i + 2 >= end) return Truncated\n const e = b[i + 2]\n if ((e & 0xc0) !== 0x80) return Invalid\n if (i + 3 >= end) return Truncated\n const f = b[i + 3]\n return (f & 0xc0) === 0x80 ? ((c & 0x07) << 18) | ((d & 0x3f) << 12) | ((e & 0x3f) << 6) | (f & 0x3f) : Invalid\n }\n return Invalid\n}\n\n// Building short strings by hand is several times faster than a\n// `TextDecoder` call, which has a high fixed cost.\nconst SHORT = 24\n\nconst utf8Decoder = /*#__PURE__*/ new TextDecoder(\"utf-8\", { ignoreBOM: true })\n\n/**\n * Decodes `b[start, end)`. Some platforms' `TextDecoder` rejects views of a\n * `SharedArrayBuffer`, so those are copied first.\n */\nconst decodeRange = (decoder: TextDecoder, b: Uint8Array, start: number, end: number): string => {\n const view = b.subarray(start, end)\n return decoder.decode(b.buffer instanceof ArrayBuffer ? view : view.slice())\n}\nconst utf8Encoder = /*#__PURE__*/ new TextEncoder()\n\n/** UTF-8 bytes. */\nexport const utf8: Encoding<Uint8Array> = {\n name: \"UTF-8\",\n unit: 1,\n asciiCompatible: true,\n decode: decodeUtf8,\n width: (cp) => (cp < 0x80 ? 1 : cp < 0x800 ? 2 : cp < 0x10000 ? 3 : 4),\n encode: (text) => utf8Encoder.encode(text),\n text: (b, start, end) => {\n if (end - start > SHORT) return decodeRange(utf8Decoder, b, start, end)\n let out = \"\"\n for (let i = start; i < end;) {\n const c = b[i]\n if (c < 0x80) {\n out += asciiChars[c]\n i++\n } else {\n const cp = decodeUtf8(b, i, end)\n out += cp < 0x10000 ? String.fromCharCode(cp) : String.fromCodePoint(cp)\n i += cp < 0x800 ? 2 : cp < 0x10000 ? 3 : 4\n }\n }\n return out\n }\n}\n\nconst makeUtf16 = (littleEndian: boolean): Encoding<Uint8Array> => {\n const lo = littleEndian ? 0 : 1\n const hi = 1 - lo\n let decoder: TextDecoder | undefined\n return {\n name: littleEndian ? \"UTF-16LE\" : \"UTF-16BE\",\n unit: 2,\n asciiCompatible: false,\n decode: (b, i, end) => {\n if (i + 1 >= end) return Truncated\n const c = b[i + lo] | (b[i + hi] << 8)\n if ((c & 0xf800) !== 0xd800) return c\n if (c > 0xdbff) return Invalid\n if (i + 3 >= end) return Truncated\n const d = b[i + 2 + lo] | (b[i + 2 + hi] << 8)\n return (d & 0xfc00) === 0xdc00 ? ((c - 0xd800) << 10) + (d - 0xdc00) + 0x10000 : Invalid\n },\n width: (cp) => (cp > 0xffff ? 4 : 2),\n encode: (text) => {\n const out = new Uint8Array(text.length * 2)\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i)\n out[2 * i + lo] = c & 0xff\n out[2 * i + hi] = c >> 8\n }\n return out\n },\n text: (b, start, end) => {\n if (end - start <= SHORT * 2) {\n // The range is well formed, so surrogate pairs can be copied unit by unit\n let out = \"\"\n for (let i = start; i < end; i += 2) out += String.fromCharCode(b[i + lo] | (b[i + hi] << 8))\n return out\n }\n decoder ??= new TextDecoder(littleEndian ? \"utf-16le\" : \"utf-16be\", { ignoreBOM: true })\n return decodeRange(decoder, b, start, end)\n }\n }\n}\n\n/** UTF-16 bytes, little endian. */\nexport const utf16le: Encoding<Uint8Array> = /*#__PURE__*/ makeUtf16(true)\n\n/** UTF-16 bytes, big endian. */\nexport const utf16be: Encoding<Uint8Array> = /*#__PURE__*/ makeUtf16(false)\n\n/** ISO-8859-1: every byte is the code point of the same value. */\nexport const latin1: Encoding<Uint8Array> = {\n name: \"ISO-8859-1\",\n unit: 1,\n asciiCompatible: true,\n decode: (b, i) => b[i],\n width: () => 1,\n encode: (text) => {\n const out = new Uint8Array(text.length)\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i)\n if (c > 0xff) throw new RangeError(`${JSON.stringify(text[i])} can't be encoded as ISO-8859-1`)\n out[i] = c\n }\n return out\n },\n text: (b, start, end) => {\n let out = \"\"\n for (let i = start; i < end; i += 8192) {\n out += String.fromCharCode.apply(null, b.subarray(i, Math.min(end, i + 8192)) as unknown as Array<number>)\n }\n return out\n },\n [FastLimit]: 0x100\n} as Encoding<Uint8Array>\n\n// -----------------------------------------------------------------------------\n// Reading code points from a State\n// -----------------------------------------------------------------------------\n\n/** The width of the code point returned by the latest {@link next}. */\nexport let width = 0\n\n/**\n * Decodes the code point at the cursor without consuming it. Returns the\n * code point (setting {@link width}), {@link End}, {@link Invalid}, or\n * {@link Truncated} (only for partial input; on complete input a truncated\n * sequence is {@link Invalid}).\n */\nexport const next = (enc: Encoding<any>, state: State<any>, pos: number = state.pos): number => {\n const end = state.end\n if (pos >= end) return End\n const cp = enc.decode(state.input, pos, end)\n if (cp >= 0) {\n width = enc.width(cp)\n return cp\n }\n return cp === Truncated && !state.partial ? Invalid : cp\n}\n\n/**\n * Fails a parser that expected a code point but found `cp` (one of the\n * negative results of {@link next}, or a code point that did not match).\n */\nexport const failAt = (\n state: State<any>,\n cp: number,\n kind: Parameters<State[\"backtrack\"]>[0],\n expected: ReadonlyArray<string>,\n offset: number = state.pos\n): Fail => {\n if (cp === End) return state.eoi(kind, expected, 1)\n if (cp === Truncated) return state.incomplete(1, expected)\n return state.backtrack(kind, expected, offset)\n}\n\n// Results of `scan`, kept in module variables to avoid allocating\n/** Offset reached by the latest {@link scan}. */\nexport let scanOffset = 0\n/** Number of code points matched by the latest {@link scan}. */\nexport let scanCount = 0\n/**\n * Why the latest {@link scan} stopped: 0 = a non-matching code point or the\n * maximum count, or one of {@link End}, {@link Invalid}, {@link Truncated}.\n */\nexport let scanStop = 0\n\n/**\n * Scans code points from `pos` while `test(cp) !== negate`, up to `max`\n * code points. `fast` is `fastLimit(enc)`, which callers can precompute.\n */\nexport const scan = (\n enc: Encoding<any>,\n state: State<any>,\n test: (cp: number) => boolean,\n negate: boolean,\n max: number,\n pos: number = state.pos,\n fast: number = fastLimit(enc)\n): void => {\n const end = state.end\n const decode = enc.decode\n let i = pos\n let count = 0\n let stop = 0\n if (state.inputKind === 0) {\n const s = state.input as string\n while (count < max) {\n if (i >= end) {\n stop = End\n break\n }\n const c = s.charCodeAt(i)\n if (c < fast) {\n if (test(c) === negate) break\n i++\n } else {\n const cp = decode(s, i, end)\n if (cp < 0) {\n stop = cp === Truncated && state.partial ? Truncated : Invalid\n break\n }\n if (test(cp) === negate) break\n i += enc.width(cp)\n }\n count++\n }\n } else {\n const b = state.input as Uint8Array\n while (count < max) {\n if (i >= end) {\n stop = End\n break\n }\n const c = b[i]\n if (c < fast) {\n if (test(c) === negate) break\n i++\n } else {\n const cp = decode(b, i, end)\n if (cp < 0) {\n stop = cp === Truncated && state.partial ? Truncated : Invalid\n break\n }\n if (test(cp) === negate) break\n i += enc.width(cp)\n }\n count++\n }\n }\n scanOffset = i\n scanCount = count\n scanStop = stop\n}\n\nconst always = () => true\n\n/**\n * Checks that `[start, end)` is well formed, counting its code points.\n * Returns the count, or `-1 - offset` of the first malformed sequence.\n */\nexport const validate = (enc: Encoding<any>, state: State<any>, start: number, end: number): number => {\n const savedEnd = state.end\n const savedPartial = state.partial\n state.end = end\n state.partial = false\n scan(enc, state, always, false, Infinity, start)\n state.end = savedEnd\n state.partial = savedPartial\n return scanStop === Invalid ? -1 - scanOffset : scanCount\n}\n\n// -----------------------------------------------------------------------------\n// Case folding\n// -----------------------------------------------------------------------------\n\nconst foldCache = /*#__PURE__*/ new Map<number, number>()\n\nconst single = (s: string): number => {\n const cp = firstCodePoint(s)\n return s.length === (cp > 0xffff ? 2 : 1) ? cp : -1\n}\n\n/**\n * Simple case folding of a code point: the lowercase of its uppercase, when\n * both map to a single code point (so `\"K\"` (Kelvin) and `\"ſ\"` fold to `\"k\"`\n * and `\"s\"`), otherwise the code point itself.\n */\nexport const fold = (cp: number): number => {\n if (cp < 128) return cp >= 65 && cp <= 90 ? cp + 32 : cp\n let f = foldCache.get(cp)\n if (f === undefined) {\n const c = String.fromCodePoint(cp)\n const upper = c.toUpperCase()\n const viaUpper = single(upper) >= 0 ? single(upper.toLowerCase()) : -1\n f = viaUpper >= 0 ? viaUpper : single(c.toLowerCase())\n if (f < 0) f = cp\n foldCache.set(cp, f)\n }\n return f\n}\n\n// -----------------------------------------------------------------------------\n// Error rendering\n// -----------------------------------------------------------------------------\n\n/**\n * Walks the code points of `[start, end)` leniently: malformed sequences\n * are reported as `-1` and skipped one code unit at a time.\n */\nexport const walk = (\n enc: Encoding<any>,\n input: string | Uint8Array,\n start: number,\n end: number,\n f: (cp: number, offset: number, width: number) => boolean | void\n): void => {\n let i = start\n while (i < end) {\n let cp = enc.decode(input, i, end)\n let w: number\n if (cp >= 0) {\n w = enc.width(cp)\n } else {\n cp = -1\n w = Math.min(enc.unit, end - i)\n }\n if (f(cp, i, w) === false) return\n i += w\n }\n}\n\n/** Decodes `[start, end)`, replacing malformed sequences with U+FFFD. */\nexport const lenientText = (enc: Encoding<any>, input: string | Uint8Array, start: number, end: number): string => {\n let out = \"\"\n walk(enc, input, start, end, (cp) => {\n out += cp < 0 ? \"�\" : charOf(cp)\n })\n return out\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"text.js","names":[],"sources":["../../src/internal/text.ts"],"sourcesContent":["import * as Arr from \"effect/Array\"\nimport * as Predicate from \"effect/Predicate\"\nimport * as Str from \"effect/String\"\nimport type { Encoding } from \"../Encoding.js\"\nimport type { Fail, State } from \"../Input.js\"\n\n// -----------------------------------------------------------------------------\n// Decoding results\n// -----------------------------------------------------------------------------\n\n/** `Encoding.decode`: the input is malformed. */\nexport const Invalid = -1\n/** `Encoding.decode`: the input ends inside a sequence. */\nexport const Truncated = -2\n/** `next`: the input has ended. */\nexport const End = -3\n\n// -----------------------------------------------------------------------------\n// Encodings\n// -----------------------------------------------------------------------------\n\n/**\n * Units below this value decode to themselves with width 1, so hot loops can\n * skip `decode`. Defaults to 0x80 for ASCII compatible encodings.\n */\nconst FastLimit: unique symbol = /*#__PURE__*/ Symbol.for(\"effect-parse/Encoding/FastLimit\")\n\n/**\n * Whether an input, a literal or a chunk has no units (characters, bytes or\n * tokens).\n */\nexport const isEmptyUnits = (units: string | Uint8Array | ReadonlyArray<unknown>): boolean =>\n Predicate.isString(units)\n ? Str.isEmpty(units)\n : units instanceof Uint8Array\n ? units.byteLength === 0\n : Arr.isReadonlyArrayEmpty(units)\n\n/** @internal */\nexport const fastLimit = (enc: Encoding<any>): number =>\n (enc as any)[FastLimit] ?? (enc.asciiCompatible && enc.unit === 1 ? 0x80 : 0)\n\nconst asciiChars: ReadonlyArray<string> = /*#__PURE__*/ Array.from({ length: 128 }, (_, i) => String.fromCharCode(i))\n\n/**\n * The code point that starts `s`: for a string known to hold one, such as\n * one element of `Array.from(string)`. On an empty string it is `NaN`, which,\n * like the `undefined` of `codePointAt(0)`, matches no code point.\n */\nexport const firstCodePoint = (s: string): number => s.codePointAt(0) ?? Number.NaN\n\n/** `String.fromCodePoint`, with the ASCII characters cached. */\nexport const charOf = (cp: number): string =>\n cp < 128 ? asciiChars[cp] : cp < 0x10000 ? String.fromCharCode(cp) : String.fromCodePoint(cp)\n\nconst decodeString = (s: string, i: number, end: number): number => {\n const c = s.charCodeAt(i)\n if ((c & 0xf800) !== 0xd800) return c\n if (c <= 0xdbff) {\n if (i + 1 >= end) return Truncated\n const d = s.charCodeAt(i + 1)\n if ((d & 0xfc00) === 0xdc00) return ((c - 0xd800) << 10) + (d - 0xdc00) + 0x10000\n }\n return Invalid\n}\n\n/**\n * JavaScript strings: UTF-16 code units. Offsets are code-unit indices and\n * slices are `String.prototype.slice`s, so no decoding is needed.\n */\nexport const string: Encoding<string> = {\n name: \"UTF-16\",\n unit: 1,\n asciiCompatible: true,\n decode: decodeString,\n width: (cp) => (cp > 0xffff ? 2 : 1),\n encode: (text) => text,\n text: (s, start, end) => s.slice(start, end),\n [FastLimit]: 0xd800\n} as Encoding<string>\n\nconst decodeUtf8 = (b: Uint8Array, i: number, end: number): number => {\n const c = b[i]\n if (c < 0x80) return c\n if (c < 0xc2) return Invalid\n if (c < 0xe0) {\n if (i + 1 >= end) return Truncated\n const d = b[i + 1]\n return (d & 0xc0) === 0x80 ? ((c & 0x1f) << 6) | (d & 0x3f) : Invalid\n }\n if (c < 0xf0) {\n if (i + 1 >= end) return Truncated\n const d = b[i + 1]\n // Reject overlong encodings (E0 80..9F) and surrogates (ED A0..BF)\n if (c === 0xe0 ? d < 0xa0 || d > 0xbf : c === 0xed ? d < 0x80 || d > 0x9f : (d & 0xc0) !== 0x80) return Invalid\n if (i + 2 >= end) return Truncated\n const e = b[i + 2]\n return (e & 0xc0) === 0x80 ? ((c & 0x0f) << 12) | ((d & 0x3f) << 6) | (e & 0x3f) : Invalid\n }\n if (c < 0xf5) {\n if (i + 1 >= end) return Truncated\n const d = b[i + 1]\n // Reject overlong encodings (F0 80..8F) and code points above U+10FFFF (F4 90..BF)\n if (c === 0xf0 ? d < 0x90 || d > 0xbf : c === 0xf4 ? d < 0x80 || d > 0x8f : (d & 0xc0) !== 0x80) return Invalid\n if (i + 2 >= end) return Truncated\n const e = b[i + 2]\n if ((e & 0xc0) !== 0x80) return Invalid\n if (i + 3 >= end) return Truncated\n const f = b[i + 3]\n return (f & 0xc0) === 0x80 ? ((c & 0x07) << 18) | ((d & 0x3f) << 12) | ((e & 0x3f) << 6) | (f & 0x3f) : Invalid\n }\n return Invalid\n}\n\n// Building short strings by hand is several times faster than a\n// `TextDecoder` call, which has a high fixed cost.\nconst SHORT = 24\n\nconst utf8Decoder = /*#__PURE__*/ new TextDecoder(\"utf-8\", { ignoreBOM: true })\n\n/**\n * Decodes `b[start, end)`. Some platforms' `TextDecoder` rejects views of a\n * `SharedArrayBuffer`, so those are copied first.\n */\nconst decodeRange = (decoder: TextDecoder, b: Uint8Array, start: number, end: number): string => {\n const view = b.subarray(start, end)\n return decoder.decode(b.buffer instanceof ArrayBuffer ? view : view.slice())\n}\nconst utf8Encoder = /*#__PURE__*/ new TextEncoder()\n\n/** UTF-8 bytes. */\n// SAFETY: an `Encoding` with the internal `FastLimit` key, which its type doesn't declare\nexport const utf8: Encoding<Uint8Array> = {\n name: \"UTF-8\",\n unit: 1,\n asciiCompatible: true,\n decode: decodeUtf8,\n width: (cp) => (cp < 0x80 ? 1 : cp < 0x800 ? 2 : cp < 0x10000 ? 3 : 4),\n encode: (text) => utf8Encoder.encode(text),\n text: (b, start, end) => {\n if (end - start > SHORT) return decodeRange(utf8Decoder, b, start, end)\n let out = \"\"\n for (let i = start; i < end;) {\n const c = b[i]\n if (c < 0x80) {\n out += asciiChars[c]\n i++\n } else {\n const cp = decodeUtf8(b, i, end)\n out += cp < 0x10000 ? String.fromCharCode(cp) : String.fromCodePoint(cp)\n i += cp < 0x800 ? 2 : cp < 0x10000 ? 3 : 4\n }\n }\n return out\n },\n // Every built-in encoding has the same keys in the same order, so code\n // reading them sees one object shape\n [FastLimit]: 0x80\n} as Encoding<Uint8Array>\n\nconst makeUtf16 = (littleEndian: boolean): Encoding<Uint8Array> => {\n const lo = littleEndian ? 0 : 1\n const hi = 1 - lo\n let decoder: TextDecoder | undefined\n // SAFETY: an `Encoding` with the internal `FastLimit` key, which its type doesn't declare\n return {\n name: littleEndian ? \"UTF-16LE\" : \"UTF-16BE\",\n unit: 2,\n asciiCompatible: false,\n decode: (b, i, end) => {\n if (i + 1 >= end) return Truncated\n const c = b[i + lo] | (b[i + hi] << 8)\n if ((c & 0xf800) !== 0xd800) return c\n if (c > 0xdbff) return Invalid\n if (i + 3 >= end) return Truncated\n const d = b[i + 2 + lo] | (b[i + 2 + hi] << 8)\n return (d & 0xfc00) === 0xdc00 ? ((c - 0xd800) << 10) + (d - 0xdc00) + 0x10000 : Invalid\n },\n width: (cp) => (cp > 0xffff ? 4 : 2),\n encode: (text) => {\n const out = new Uint8Array(text.length * 2)\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i)\n out[2 * i + lo] = c & 0xff\n out[2 * i + hi] = c >> 8\n }\n return out\n },\n text: (b, start, end) => {\n if (end - start <= SHORT * 2) {\n // The range is well formed, so surrogate pairs can be copied unit by unit\n let out = \"\"\n for (let i = start; i < end; i += 2) out += String.fromCharCode(b[i + lo] | (b[i + hi] << 8))\n return out\n }\n decoder ??= new TextDecoder(littleEndian ? \"utf-16le\" : \"utf-16be\", { ignoreBOM: true })\n return decodeRange(decoder, b, start, end)\n },\n [FastLimit]: 0\n } as Encoding<Uint8Array>\n}\n\n/** UTF-16 bytes, little endian. */\nexport const utf16le: Encoding<Uint8Array> = /*#__PURE__*/ makeUtf16(true)\n\n/** UTF-16 bytes, big endian. */\nexport const utf16be: Encoding<Uint8Array> = /*#__PURE__*/ makeUtf16(false)\n\n/** ISO-8859-1: every byte is the code point of the same value. */\nexport const latin1: Encoding<Uint8Array> = {\n name: \"ISO-8859-1\",\n unit: 1,\n asciiCompatible: true,\n decode: (b, i) => b[i],\n width: () => 1,\n encode: (text) => {\n const out = new Uint8Array(text.length)\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i)\n if (c > 0xff) throw new RangeError(`${JSON.stringify(text[i])} can't be encoded as ISO-8859-1`)\n out[i] = c\n }\n return out\n },\n text: (b, start, end) => {\n let out = \"\"\n for (let i = start; i < end; i += 8192) {\n out += String.fromCharCode.apply(null, b.subarray(i, Math.min(end, i + 8192)) as unknown as Array<number>)\n }\n return out\n },\n [FastLimit]: 0x100\n} as Encoding<Uint8Array>\n\n// -----------------------------------------------------------------------------\n// Reading code points from a State\n// -----------------------------------------------------------------------------\n\n/** The width of the code point returned by the latest {@link next}. */\nexport let width = 0\n\n/**\n * Decodes the code point at the cursor without consuming it. Returns the\n * code point (setting {@link width}), {@link End}, {@link Invalid}, or\n * {@link Truncated} (only for partial input; on complete input a truncated\n * sequence is {@link Invalid}).\n */\nexport const next = (enc: Encoding<any>, state: State<any>, pos: number = state.pos): number => {\n const end = state.end\n if (pos >= end) return End\n const cp = enc.decode(state.input, pos, end)\n if (cp >= 0) {\n width = enc.width(cp)\n return cp\n }\n return cp === Truncated && !state.partial ? Invalid : cp\n}\n\n/**\n * Fails a parser that expected a code point but found `cp` (one of the\n * negative results of {@link next}, or a code point that did not match).\n */\nexport const failAt = (\n state: State<any>,\n cp: number,\n kind: Parameters<State[\"backtrack\"]>[0],\n expected: ReadonlyArray<string>,\n offset: number = state.pos\n): Fail => {\n if (cp === End) return state.eoi(kind, expected, 1)\n if (cp === Truncated) return state.incomplete(1, expected)\n return state.backtrack(kind, expected, offset)\n}\n\n// Results of `scan`, kept in module variables to avoid allocating\n/** Offset reached by the latest {@link scan}. */\nexport let scanOffset = 0\n/** Number of code points matched by the latest {@link scan}. */\nexport let scanCount = 0\n/**\n * Why the latest {@link scan} stopped: 0 = a non-matching code point or the\n * maximum count, or one of {@link End}, {@link Invalid}, {@link Truncated}.\n */\nexport let scanStop = 0\n\n/**\n * Scans code points from `pos` while `test(cp) !== negate`, up to `max`\n * code points. `fast` is `fastLimit(enc)`, which callers can precompute.\n */\nexport const scan = (\n enc: Encoding<any>,\n state: State<any>,\n test: (cp: number) => boolean,\n negate: boolean,\n max: number,\n pos: number = state.pos,\n fast: number = fastLimit(enc)\n): void => {\n const end = state.end\n const decode = enc.decode\n let i = pos\n let count = 0\n let stop = 0\n if (state.inputKind === 0) {\n const s = state.input as string\n while (count < max) {\n if (i >= end) {\n stop = End\n break\n }\n const c = s.charCodeAt(i)\n if (c < fast) {\n if (test(c) === negate) break\n i++\n } else {\n const cp = decode(s, i, end)\n if (cp < 0) {\n stop = cp === Truncated && state.partial ? Truncated : Invalid\n break\n }\n if (test(cp) === negate) break\n i += enc.width(cp)\n }\n count++\n }\n } else {\n const b = state.input as Uint8Array\n while (count < max) {\n if (i >= end) {\n stop = End\n break\n }\n const c = b[i]\n if (c < fast) {\n if (test(c) === negate) break\n i++\n } else {\n const cp = decode(b, i, end)\n if (cp < 0) {\n stop = cp === Truncated && state.partial ? Truncated : Invalid\n break\n }\n if (test(cp) === negate) break\n i += enc.width(cp)\n }\n count++\n }\n }\n scanOffset = i\n scanCount = count\n scanStop = stop\n}\n\nconst always = () => true\n\n/**\n * Checks that `[start, end)` is well formed, counting its code points.\n * Returns the count, or `-1 - offset` of the first malformed sequence.\n */\nexport const validate = (enc: Encoding<any>, state: State<any>, start: number, end: number): number => {\n const savedEnd = state.end\n const savedPartial = state.partial\n state.end = end\n state.partial = false\n scan(enc, state, always, false, Infinity, start)\n state.end = savedEnd\n state.partial = savedPartial\n return scanStop === Invalid ? -1 - scanOffset : scanCount\n}\n\n// -----------------------------------------------------------------------------\n// Case folding\n// -----------------------------------------------------------------------------\n\nconst foldCache = /*#__PURE__*/ new Map<number, number>()\n\nconst single = (s: string): number => {\n const cp = firstCodePoint(s)\n return s.length === (cp > 0xffff ? 2 : 1) ? cp : -1\n}\n\n/**\n * Simple case folding of a code point: the lowercase of its uppercase, when\n * both map to a single code point (so `\"K\"` (Kelvin) and `\"ſ\"` fold to `\"k\"`\n * and `\"s\"`), otherwise the code point itself.\n */\nexport const fold = (cp: number): number => {\n if (cp < 128) return cp >= 65 && cp <= 90 ? cp + 32 : cp\n let f = foldCache.get(cp)\n if (f === undefined) {\n const c = String.fromCodePoint(cp)\n const upper = c.toUpperCase()\n const viaUpper = single(upper) >= 0 ? single(upper.toLowerCase()) : -1\n f = viaUpper >= 0 ? viaUpper : single(c.toLowerCase())\n if (f < 0) f = cp\n foldCache.set(cp, f)\n }\n return f\n}\n\n// -----------------------------------------------------------------------------\n// Error rendering\n// -----------------------------------------------------------------------------\n\n/**\n * Walks the code points of `[start, end)` leniently: malformed sequences\n * are reported as `-1` and skipped one code unit at a time.\n */\nexport const walk = (\n enc: Encoding<any>,\n input: string | Uint8Array,\n start: number,\n end: number,\n f: (cp: number, offset: number, width: number) => boolean | void\n): void => {\n let i = start\n while (i < end) {\n let cp = enc.decode(input, i, end)\n let w: number\n if (cp >= 0) {\n w = enc.width(cp)\n } else {\n cp = -1\n w = Math.min(enc.unit, end - i)\n }\n if (f(cp, i, w) === false) return\n i += w\n }\n}\n\n/** Decodes `[start, end)`, replacing malformed sequences with U+FFFD. */\nexport const lenientText = (enc: Encoding<any>, input: string | Uint8Array, start: number, end: number): string => {\n let out = \"\"\n walk(enc, input, start, end, (cp) => {\n out += cp < 0 ? \"�\" : charOf(cp)\n })\n return out\n}\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { Fail, Failure, Input, State } from "../Input.js";
2
+ /** The failures of a round of attempts, folded lazily. */
3
+ export declare class TiedFailures {
4
+ /** The running failure, before the pending ties are merged into it. */
5
+ failure: Failure | undefined;
6
+ /** The oldest pending tie, at `failure`'s offset. */
7
+ tie1: Failure | undefined;
8
+ /** The newest pending tie, at `failure`'s offset. */
9
+ tie2: Failure | undefined;
10
+ /** Forgets every failure, for a new round. */
11
+ clear(): void;
12
+ /**
13
+ * Folds in the failure the latest attempt left on `state`, taking over
14
+ * its own unmerged ties when it is the furthest.
15
+ */
16
+ add<I extends Input>(state: State<I>): void;
17
+ /**
18
+ * Fails `state` with the folded failure (recoverably), or with its
19
+ * current failure when nothing was folded.
20
+ */
21
+ fail<I extends Input>(state: State<I>): Fail;
22
+ /**
23
+ * Records the folded expectations as a hint when the folded failure lies
24
+ * where `state` stopped (an attempt that fails without consuming input).
25
+ */
26
+ hint<I extends Input>(state: State<I>): void;
27
+ }
28
+ //# sourceMappingURL=ties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ties.d.ts","names":[],"sources":["../../src/internal/ties.ts"],"mappings":";;qBAkBa;;EAEX,SAAS;;EAET,MAAM;;EAEN,MAAM;;EAGN;;;;;EAUA,IAAI,UAAU,OAAO,OAAO,MAAM;;;;;EA0BlC,KAAK,UAAU,OAAO,OAAO,MAAM,KAAK;;;;;EAWxC,KAAK,UAAU,OAAO,OAAO,MAAM"}
@@ -0,0 +1,66 @@
1
+ import { mergeExpected, mergeTiedFailures } from "../Input.js";
2
+ // src/internal/ties.ts
3
+ /** The failures of a round of attempts, folded lazily. */
4
+ var TiedFailures = class {
5
+ /** The running failure, before the pending ties are merged into it. */
6
+ failure = void 0;
7
+ /** The oldest pending tie, at `failure`'s offset. */
8
+ tie1 = void 0;
9
+ /** The newest pending tie, at `failure`'s offset. */
10
+ tie2 = void 0;
11
+ /** Forgets every failure, for a new round. */
12
+ clear() {
13
+ this.failure = void 0;
14
+ this.tie1 = void 0;
15
+ this.tie2 = void 0;
16
+ }
17
+ /**
18
+ * Folds in the failure the latest attempt left on `state`, taking over
19
+ * its own unmerged ties when it is the furthest.
20
+ */
21
+ add(state) {
22
+ const head = state.failureHead;
23
+ const running = this.failure;
24
+ if (running === void 0 || head.offset > running.offset) {
25
+ this.failure = head;
26
+ this.tie1 = state.failureTie1;
27
+ this.tie2 = state.failureTie2;
28
+ return;
29
+ }
30
+ if (head.offset < running.offset) return;
31
+ const failure = state.failure;
32
+ const tie1 = this.tie1;
33
+ if (tie1 === void 0) this.tie1 = failure;
34
+ else if (this.tie2 === void 0) this.tie2 = failure;
35
+ else {
36
+ this.failure = mergeTiedFailures(running, tie1, mergeExpected(running.expected, tie1.expected));
37
+ this.tie1 = this.tie2;
38
+ this.tie2 = failure;
39
+ }
40
+ }
41
+ /**
42
+ * Fails `state` with the folded failure (recoverably), or with its
43
+ * current failure when nothing was folded.
44
+ */
45
+ fail(state) {
46
+ const failure = this.failure;
47
+ if (failure === void 0) return state.failWith("Backtrack", state.failure);
48
+ const tie1 = this.tie1;
49
+ return tie1 === void 0 ? state.failWith("Backtrack", failure) : state.failTies(failure, tie1, this.tie2);
50
+ }
51
+ /**
52
+ * Records the folded expectations as a hint when the folded failure lies
53
+ * where `state` stopped (an attempt that fails without consuming input).
54
+ */
55
+ hint(state) {
56
+ const failure = this.failure;
57
+ if (failure === void 0 || failure.offset !== state.pos) return;
58
+ let expected = failure.expected;
59
+ if (this.tie1 !== void 0) expected = mergeExpected(expected, this.tie1.expected);
60
+ if (this.tie2 !== void 0) expected = mergeExpected(expected, this.tie2.expected);
61
+ state.setHint(failure.offset, expected);
62
+ }
63
+ };
64
+ export { TiedFailures };
65
+
66
+ //# sourceMappingURL=ties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ties.js","names":[],"sources":["../../src/internal/ties.ts"],"sourcesContent":["/**\n * Tied failures, merged only when read.\n *\n * A combinator that tries several parsers at the same position (an\n * alternation, a permutation round, an operator table) reports the merge\n * of their failures, left to right, as `mergeFailures` would. Most of the\n * time one of the later attempts succeeds and the merge is thrown away, so\n * {@link TiedFailures} keeps the last two failures tied with the running\n * one unmerged, and {@link TiedFailures.fail} hands them to the state with\n * `State.failTies`, which merges them on first read (#38, #44).\n *\n * `Parser.alt` does the same fold in locals, since it is the hottest\n * combinator and cannot afford an accumulator per call.\n */\nimport type { Failure, Fail, Input, State } from \"../Input.js\"\nimport { mergeExpected, mergeTiedFailures } from \"../Input.js\"\n\n/** The failures of a round of attempts, folded lazily. */\nexport class TiedFailures {\n /** The running failure, before the pending ties are merged into it. */\n failure: Failure | undefined = undefined\n /** The oldest pending tie, at `failure`'s offset. */\n tie1: Failure | undefined = undefined\n /** The newest pending tie, at `failure`'s offset. */\n tie2: Failure | undefined = undefined\n\n /** Forgets every failure, for a new round. */\n clear(): void {\n this.failure = undefined\n this.tie1 = undefined\n this.tie2 = undefined\n }\n\n /**\n * Folds in the failure the latest attempt left on `state`, taking over\n * its own unmerged ties when it is the furthest.\n */\n add<I extends Input>(state: State<I>): void {\n const head = state.failureHead\n const running = this.failure\n if (running === undefined || head.offset > running.offset) {\n this.failure = head\n this.tie1 = state.failureTie1\n this.tie2 = state.failureTie2\n return\n }\n if (head.offset < running.offset) return\n const failure = state.failure\n const tie1 = this.tie1\n if (tie1 === undefined) this.tie1 = failure\n else if (this.tie2 === undefined) this.tie2 = failure\n else {\n // A third tie: fold the oldest pending one in, keeping the order\n this.failure = mergeTiedFailures(running, tie1, mergeExpected(running.expected, tie1.expected))\n this.tie1 = this.tie2\n this.tie2 = failure\n }\n }\n\n /**\n * Fails `state` with the folded failure (recoverably), or with its\n * current failure when nothing was folded.\n */\n fail<I extends Input>(state: State<I>): Fail {\n const failure = this.failure\n if (failure === undefined) return state.failWith(\"Backtrack\", state.failure)\n const tie1 = this.tie1\n return tie1 === undefined ? state.failWith(\"Backtrack\", failure) : state.failTies(failure, tie1, this.tie2)\n }\n\n /**\n * Records the folded expectations as a hint when the folded failure lies\n * where `state` stopped (an attempt that fails without consuming input).\n */\n hint<I extends Input>(state: State<I>): void {\n const failure = this.failure\n if (failure === undefined || failure.offset !== state.pos) return\n let expected = failure.expected\n if (this.tie1 !== undefined) expected = mergeExpected(expected, this.tie1.expected)\n if (this.tie2 !== undefined) expected = mergeExpected(expected, this.tie2.expected)\n state.setHint(failure.offset, expected)\n }\n}\n"],"mappings":";;;AAkBA,IAAa,eAAb,MAA0B;;CAExB,UAA+B,KAAA;;CAE/B,OAA4B,KAAA;;CAE5B,OAA4B,KAAA;;CAG5B,QAAc;EACZ,KAAK,UAAU,KAAA;EACf,KAAK,OAAO,KAAA;EACZ,KAAK,OAAO,KAAA;CACd;;;;;CAMA,IAAqB,OAAuB;EAC1C,MAAM,OAAO,MAAM;EACnB,MAAM,UAAU,KAAK;EACrB,IAAI,YAAY,KAAA,KAAa,KAAK,SAAS,QAAQ,QAAQ;GACzD,KAAK,UAAU;GACf,KAAK,OAAO,MAAM;GAClB,KAAK,OAAO,MAAM;GAClB;EACF;EACA,IAAI,KAAK,SAAS,QAAQ,QAAQ;EAClC,MAAM,UAAU,MAAM;EACtB,MAAM,OAAO,KAAK;EAClB,IAAI,SAAS,KAAA,GAAW,KAAK,OAAO;OAC/B,IAAI,KAAK,SAAS,KAAA,GAAW,KAAK,OAAO;OACzC;GAEH,KAAK,UAAU,kBAAkB,SAAS,MAAM,cAAc,QAAQ,UAAU,KAAK,QAAQ,CAAC;GAC9F,KAAK,OAAO,KAAK;GACjB,KAAK,OAAO;EACd;CACF;;;;;CAMA,KAAsB,OAAuB;EAC3C,MAAM,UAAU,KAAK;EACrB,IAAI,YAAY,KAAA,GAAW,OAAO,MAAM,SAAS,aAAa,MAAM,OAAO;EAC3E,MAAM,OAAO,KAAK;EAClB,OAAO,SAAS,KAAA,IAAY,MAAM,SAAS,aAAa,OAAO,IAAI,MAAM,SAAS,SAAS,MAAM,KAAK,IAAI;CAC5G;;;;;CAMA,KAAsB,OAAuB;EAC3C,MAAM,UAAU,KAAK;EACrB,IAAI,YAAY,KAAA,KAAa,QAAQ,WAAW,MAAM,KAAK;EAC3D,IAAI,WAAW,QAAQ;EACvB,IAAI,KAAK,SAAS,KAAA,GAAW,WAAW,cAAc,UAAU,KAAK,KAAK,QAAQ;EAClF,IAAI,KAAK,SAAS,KAAA,GAAW,WAAW,cAAc,UAAU,KAAK,KAAK,QAAQ;EAClF,MAAM,QAAQ,QAAQ,QAAQ,QAAQ;CACxC;AACF"}