clarity-pattern-parser 8.4.14 → 9.0.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 (100) hide show
  1. package/TODO.md +4 -1
  2. package/dist/grammar/Grammar.d.ts +18 -10
  3. package/dist/grammar/patterns/andLiteral.d.ts +2 -0
  4. package/dist/grammar/patterns/anonymousPattern.d.ts +2 -0
  5. package/dist/grammar/patterns/inlinePattern.d.ts +1 -0
  6. package/dist/grammar/patterns/literals.d.ts +3 -0
  7. package/dist/grammar/patterns/pattern.d.ts +2 -2
  8. package/dist/grammar/patterns.d.ts +2 -0
  9. package/dist/index.browser.js +472 -185
  10. package/dist/index.browser.js.map +1 -1
  11. package/dist/index.d.ts +3 -1
  12. package/dist/index.esm.js +471 -186
  13. package/dist/index.esm.js.map +1 -1
  14. package/dist/index.js +472 -185
  15. package/dist/index.js.map +1 -1
  16. package/dist/patterns/And.d.ts +4 -1
  17. package/dist/patterns/Cursor.d.ts +5 -0
  18. package/dist/patterns/CursorHistory.d.ts +7 -0
  19. package/dist/patterns/FiniteRepeat.d.ts +4 -1
  20. package/dist/patterns/InfiniteRepeat.d.ts +5 -4
  21. package/dist/patterns/Literal.d.ts +6 -5
  22. package/dist/patterns/Not.d.ts +5 -4
  23. package/dist/patterns/Or.d.ts +5 -4
  24. package/dist/patterns/Pattern.d.ts +4 -2
  25. package/dist/patterns/Reference.d.ts +5 -4
  26. package/dist/patterns/Regex.d.ts +5 -4
  27. package/dist/patterns/Repeat.d.ts +3 -0
  28. package/dist/patterns/arePatternsEqual.d.ts +2 -0
  29. package/package.json +1 -1
  30. package/src/grammar/Grammar.test.ts +126 -72
  31. package/src/grammar/Grammar.ts +241 -158
  32. package/src/grammar/patterns/anonymousPattern.ts +23 -0
  33. package/src/grammar/patterns/body.ts +9 -6
  34. package/src/grammar/patterns/comment.ts +3 -2
  35. package/src/grammar/patterns/grammar.ts +15 -12
  36. package/src/grammar/patterns/import.ts +18 -12
  37. package/src/grammar/patterns/literal.ts +2 -3
  38. package/src/grammar/patterns/literals.ts +20 -0
  39. package/src/grammar/patterns/optionsLiteral.ts +19 -0
  40. package/src/grammar/patterns/pattern.ts +23 -9
  41. package/src/grammar/patterns/regexLiteral.ts +1 -0
  42. package/src/grammar/patterns/repeatLiteral.ts +30 -25
  43. package/src/grammar/patterns/sequenceLiteral.ts +24 -0
  44. package/src/grammar/patterns/spaces.ts +8 -6
  45. package/src/grammar/patterns/statement.ts +8 -20
  46. package/src/grammar/patterns.test.ts +38 -0
  47. package/src/grammar/patterns.ts +24 -0
  48. package/src/grammar/spec.md +4 -12
  49. package/src/index.ts +11 -5
  50. package/src/intellisense/AutoComplete.test.ts +41 -40
  51. package/src/intellisense/css/method.ts +2 -2
  52. package/src/intellisense/css/unit.ts +2 -2
  53. package/src/intellisense/css/value.ts +1 -1
  54. package/src/intellisense/javascript/Javascript.test.ts +31 -32
  55. package/src/intellisense/javascript/arrayLiteral.ts +7 -6
  56. package/src/intellisense/javascript/assignment.ts +6 -6
  57. package/src/intellisense/javascript/deleteStatement.ts +2 -2
  58. package/src/intellisense/javascript/escapedCharacter.ts +6 -6
  59. package/src/intellisense/javascript/exponent.ts +6 -6
  60. package/src/intellisense/javascript/expression.ts +18 -17
  61. package/src/intellisense/javascript/fraction.ts +3 -3
  62. package/src/intellisense/javascript/infixOperator.ts +10 -10
  63. package/src/intellisense/javascript/integer.ts +1 -1
  64. package/src/intellisense/javascript/invocation.ts +8 -7
  65. package/src/intellisense/javascript/literal.ts +3 -3
  66. package/src/intellisense/javascript/numberLiteral.ts +5 -4
  67. package/src/intellisense/javascript/objectAccess.ts +2 -3
  68. package/src/intellisense/javascript/objectLiteral.ts +8 -7
  69. package/src/intellisense/javascript/optionalSpaces.ts +2 -1
  70. package/src/intellisense/javascript/parameters.ts +5 -5
  71. package/src/intellisense/javascript/prefixOperator.ts +3 -4
  72. package/src/intellisense/javascript/propertyAccess.ts +9 -8
  73. package/src/intellisense/javascript/stringLiteral.ts +14 -15
  74. package/src/patterns/Cursor.ts +42 -4
  75. package/src/patterns/CursorHistory.ts +20 -4
  76. package/src/patterns/FiniteRepeat.test.ts +52 -51
  77. package/src/patterns/FiniteRepeat.ts +60 -38
  78. package/src/patterns/InfiniteRepeat.test.ts +36 -49
  79. package/src/patterns/InfiniteRepeat.ts +70 -37
  80. package/src/patterns/Literal.test.ts +16 -27
  81. package/src/patterns/Literal.ts +34 -27
  82. package/src/patterns/Not.test.ts +7 -7
  83. package/src/patterns/Not.ts +24 -6
  84. package/src/patterns/Optional.test.ts +164 -0
  85. package/src/patterns/Optional.ts +143 -0
  86. package/src/patterns/{Or.test.ts → Options.test.ts} +51 -49
  87. package/src/patterns/{Or.ts → Options.ts} +32 -23
  88. package/src/patterns/Pattern.ts +6 -5
  89. package/src/patterns/Reference.test.ts +21 -22
  90. package/src/patterns/Reference.ts +26 -15
  91. package/src/patterns/Regex.test.ts +15 -15
  92. package/src/patterns/Regex.ts +29 -19
  93. package/src/patterns/Repeat.test.ts +12 -22
  94. package/src/patterns/Repeat.ts +22 -21
  95. package/src/patterns/{And.test.ts → Sequence.test.ts} +78 -78
  96. package/src/patterns/{And.ts → Sequence.ts} +40 -29
  97. package/src/patterns/arePatternsEqual.ts +12 -0
  98. package/src/patterns/clonePatterns.ts +2 -2
  99. package/src/grammar/patterns/andLiteral.ts +0 -8
  100. package/src/grammar/patterns/orLiteral.ts +0 -8
@@ -1,11 +1,11 @@
1
- import { And } from "../../patterns/And";
1
+ import { Sequence } from "../../patterns/Sequence";
2
2
  import { Literal } from "../../patterns/Literal";
3
3
  import { Regex } from "../../patterns/Regex";
4
4
 
5
5
  const period = new Literal("period", ".");
6
6
  const digit = new Regex("digit", "\\d+");
7
- const fraction = new And("fraction", [period, digit]);
7
+ const fraction = new Sequence("fraction", [period, digit]);
8
8
 
9
9
  export {
10
10
  fraction
11
- }
11
+ };
@@ -1,40 +1,40 @@
1
- import { Literal } from "../../patterns/Literal"
2
- import { Or } from "../../patterns/Or";
1
+ import { Literal } from "../../patterns/Literal";
2
+ import { Options } from "../../patterns/Options";
3
3
 
4
4
  const multiply = new Literal("multiply", "*");
5
5
  const divide = new Literal("divide", "/");
6
6
  const remainder = new Literal("remainder", "%");
7
7
  const add = new Literal("add", "+");
8
8
  const subtract = new Literal("subtract", "-");
9
- const greaterOrEqual = new Literal("greater-or-equal", ">=");
10
- const lessOrEqual = new Literal("less-or-equal", "<=");
9
+ const greaterOptionsEqual = new Literal("greater-or-equal", ">=");
10
+ const lessOptionsEqual = new Literal("less-or-equal", "<=");
11
11
  const greater = new Literal("greater", ">");
12
12
  const less = new Literal("less", "<");
13
13
  const equal = new Literal("equal", "==");
14
14
  const notEqual = new Literal("not-equal", "!=");
15
15
  const strictEqual = new Literal("strict-equal", "===");
16
16
  const strictNotEqual = new Literal("strict-not-equal", "!==");
17
- const logicalOr = new Literal("logical-or", "||");
17
+ const logicalOptions = new Literal("logical-or", "||");
18
18
  const logicalAnd = new Literal("logical-and", "&&");
19
19
 
20
- const infixOperator = new Or("infix-operator", [
20
+ const infixOperator = new Options("infix-operator", [
21
21
  multiply,
22
22
  divide,
23
23
  remainder,
24
24
  add,
25
25
  subtract,
26
- greaterOrEqual,
27
- lessOrEqual,
26
+ greaterOptionsEqual,
27
+ lessOptionsEqual,
28
28
  greater,
29
29
  less,
30
30
  strictEqual,
31
31
  strictNotEqual,
32
32
  equal,
33
33
  notEqual,
34
- logicalOr,
34
+ logicalOptions,
35
35
  logicalAnd
36
36
  ]);
37
37
 
38
- export { infixOperator }
38
+ export { infixOperator };
39
39
 
40
40
 
@@ -4,4 +4,4 @@ const integer = new Regex("integer", "([1-9][0-9]*)|0");
4
4
 
5
5
  export {
6
6
  integer
7
- }
7
+ };
@@ -1,28 +1,29 @@
1
- import { And } from "../../patterns/And";
1
+ import { Sequence } from "../../patterns/Sequence";
2
2
  import { Literal } from "../../patterns/Literal";
3
- import { Or } from "../../patterns/Or";
3
+ import { Options } from "../../patterns/Options";
4
4
  import { Reference } from "../../patterns/Reference";
5
5
  import { Regex } from "../../patterns/Regex";
6
6
  import { Repeat } from "../../patterns/Repeat";
7
7
  import { optionalSpaces } from "./optionalSpaces";
8
+ import { Optional } from "../../patterns/Optional";
8
9
 
9
10
  const divider = new Regex("invocation-divider", "\\s*,\\s*");
10
11
 
11
- const invocationWithArguments = new And("invocation-with-arguments", [
12
+ const invocationWithArguments = new Sequence("invocation-with-arguments", [
12
13
  new Literal("open-paren", "("),
13
14
  optionalSpaces,
14
- new Repeat("expressions", new Reference("expression"), { divider, min: 0 }),
15
+ new Optional("optional-expression", new Repeat("expressions", new Reference("expression"), { divider })),
15
16
  optionalSpaces,
16
17
  new Literal("close-paren", ")"),
17
18
  ]);
18
19
 
19
- const emptyInvocation = new And("empty-invocation", [
20
+ const emptyInvocation = new Sequence("empty-invocation", [
20
21
  new Literal("open-paren", "("),
21
22
  optionalSpaces,
22
23
  new Literal("close-paren", ")"),
23
24
  ]);
24
25
 
25
- export const invocation = new Or("invocation", [
26
+ export const invocation = new Options("invocation", [
26
27
  emptyInvocation,
27
28
  invocationWithArguments
28
- ])
29
+ ]);
@@ -1,14 +1,14 @@
1
- import { Or } from "../../patterns/Or";
1
+ import { Options } from "../../patterns/Options";
2
2
  import { arrayLiteral } from "./arrayLiteral";
3
3
  import { numberLiteral } from "./numberLiteral";
4
4
  import { objectLiteral } from "./objectLiteral";
5
5
  import { stringLiteral } from "./stringLiteral";
6
6
 
7
- const literal = new Or("literal", [
7
+ const literal = new Options("literal", [
8
8
  numberLiteral,
9
9
  stringLiteral,
10
10
  arrayLiteral,
11
11
  objectLiteral,
12
12
  ]);
13
13
 
14
- export { literal }
14
+ export { literal };
@@ -1,10 +1,11 @@
1
- import { And } from "../../patterns/And";
1
+ import { Optional } from "../../patterns/Optional";
2
+ import { Sequence } from "../../patterns/Sequence";
2
3
  import { exponent } from "./exponent";
3
4
  import { fraction } from "./fraction";
4
5
  import { integer } from "./integer";
5
6
 
6
- export const numberLiteral = new And("number-literal", [
7
+ export const numberLiteral = new Sequence("number-literal", [
7
8
  integer,
8
- fraction.clone("number-fraction", true),
9
- exponent.clone("number-exponent", true)
9
+ new Optional("number-fraction", fraction),
10
+ new Optional("number-exponent", exponent)
10
11
  ]);
@@ -1,9 +1,8 @@
1
- import { And } from "../../patterns/And";
2
- import { Reference } from "../../patterns/Reference";
1
+ import { Sequence } from "../../patterns/Sequence";
3
2
  import { name } from "./name";
4
3
  import { propertyAccess } from "./propertyAccess";
5
4
 
6
- export const objectAccess = new And("object-access", [
5
+ export const objectAccess = new Sequence("object-access", [
7
6
  name.clone("variable-name"),
8
7
  propertyAccess,
9
8
  ]);
@@ -1,15 +1,16 @@
1
- import { And } from "../../patterns/And";
1
+ import { Sequence } from "../../patterns/Sequence";
2
2
  import { Literal } from "../../patterns/Literal";
3
- import { Or } from "../../patterns/Or";
3
+ import { Options } from "../../patterns/Options";
4
4
  import { Reference } from "../../patterns/Reference";
5
5
  import { Regex } from "../../patterns/Regex";
6
6
  import { Repeat } from "../../patterns/Repeat";
7
7
  import { name } from "./name";
8
8
  import { optionalSpaces } from "./optionalSpaces";
9
9
  import { stringLiteral } from "./stringLiteral";
10
+ import { Optional } from "../../patterns/Optional";
10
11
 
11
- const propertyName = new Or("property-name", [stringLiteral.clone("object-property"), name.clone("object-property")]);
12
- const property = new And("property", [
12
+ const propertyName = new Options("property-name", [stringLiteral.clone("object-property"), name.clone("object-property")]);
13
+ const property = new Sequence("property", [
13
14
  propertyName,
14
15
  optionalSpaces,
15
16
  new Literal("colon", ":"),
@@ -17,9 +18,9 @@ const property = new And("property", [
17
18
  new Reference("expression"),
18
19
  ]);
19
20
  const divider = new Regex("property-divider", "\\s*,\\s*");
20
- const optionalProperties = new Repeat("properties", property, { divider, min: 0 });
21
+ const optionalProperties = new Optional("optional-properties", new Repeat("properties", property, { divider}));
21
22
 
22
- const objectLiteral = new And("object-literal", [
23
+ const objectLiteral = new Sequence("object-literal", [
23
24
  new Literal("open-curly-bracket", "{"),
24
25
  optionalSpaces,
25
26
  optionalProperties,
@@ -27,4 +28,4 @@ const objectLiteral = new And("object-literal", [
27
28
  new Literal("close-curly-bracket", "}"),
28
29
  ]);
29
30
 
30
- export { objectLiteral }
31
+ export { objectLiteral };
@@ -1,3 +1,4 @@
1
+ import { Optional } from "../../patterns/Optional";
1
2
  import { Regex } from "../../patterns/Regex";
2
3
 
3
- export const optionalSpaces = new Regex("optional-spaces", "\\s+", true);
4
+ export const optionalSpaces = new Optional("optional-spaces", new Regex("optional-spaces", "\\s+"));
@@ -1,19 +1,19 @@
1
- import { And } from "../../patterns/And";
1
+ import { Sequence } from "../../patterns/Sequence";
2
2
  import { Literal } from "../../patterns/Literal";
3
3
  import { Regex } from "../../patterns/Regex";
4
4
  import { Repeat } from "../../patterns/Repeat";
5
5
  import { name } from "./name";
6
+ import { optionalSpaces } from "./optionalSpaces";
6
7
 
7
8
  const divider = new Regex(",", "\\s*[,]\\s*");
8
9
  divider.setTokens([", "]);
9
10
 
10
- const optionalSpace = new Regex("optional-space", "\\s", true)
11
11
 
12
- const parameters = new And("parameters", [
12
+ const parameters = new Sequence("parameters", [
13
13
  new Literal("open-paren", "("),
14
- optionalSpace,
14
+ optionalSpaces,
15
15
  new Repeat("arguments", name, { divider, trimDivider: true }),
16
- optionalSpace,
16
+ optionalSpaces,
17
17
  new Literal("close-paren", ")"),
18
18
  ]);
19
19
 
@@ -1,13 +1,12 @@
1
1
  import { Literal } from "../../patterns/Literal";
2
- import { Or } from "../../patterns/Or";
3
- import { Regex } from "../../patterns/Regex";
2
+ import { Options } from "../../patterns/Options";
4
3
 
5
- const prefixOperator = new Or("prefix-operator", [
4
+ const prefixOperator = new Options("prefix-operator", [
6
5
  new Literal("typeof", "typeof "),
7
6
  new Literal("to-number", "+"),
8
7
  new Literal("negate", "-"),
9
8
  new Literal("logical-not", "!"),
10
9
  ]);
11
10
 
12
- export { prefixOperator }
11
+ export { prefixOperator };
13
12
 
@@ -1,28 +1,29 @@
1
- import { And } from "../../patterns/And";
1
+ import { Sequence } from "../../patterns/Sequence";
2
2
  import { Literal } from "../../patterns/Literal";
3
- import { Or } from "../../patterns/Or";
3
+ import { Options } from "../../patterns/Options";
4
4
  import { Reference } from "../../patterns/Reference";
5
5
  import { name } from "./name";
6
+ import { Optional } from "../../patterns/Optional";
6
7
 
7
- const dotPropertyAccess = new And("dot-property-access", [
8
+ const dotPropertyAccess = new Sequence("dot-property-access", [
8
9
  new Literal("period", "."),
9
10
  name.clone("property-name")
10
11
  ]);
11
12
 
12
- const bracketPropertyAccess = new And("bracket-property-access", [
13
+ const bracketPropertyAccess = new Sequence("bracket-property-access", [
13
14
  new Literal("open-square-bracket", "["),
14
15
  new Reference("expression"),
15
16
  new Literal("close-square-bracket", "]"),
16
17
  ]);
17
18
 
18
- const propertyAccessTypes = new Or("property-access-types", [
19
+ const propertyAccessTypes = new Options("property-access-types", [
19
20
  dotPropertyAccess,
20
21
  bracketPropertyAccess
21
22
  ]);
22
23
 
23
- const propertyAccess = new And("property-access", [
24
+ const propertyAccess = new Sequence("property-access", [
24
25
  propertyAccessTypes,
25
- new Reference("property-access", true)
26
+ new Optional("optional-property-access", new Reference("property-access"))
26
27
  ]);
27
28
 
28
- export { propertyAccess }
29
+ export { propertyAccess };
@@ -1,34 +1,33 @@
1
- import { And } from "../../patterns/And";
1
+ import { Sequence } from "../../patterns/Sequence";
2
2
  import { Literal } from "../../patterns/Literal";
3
- import { Or } from "../../patterns/Or";
3
+ import { Options } from "../../patterns/Options";
4
4
  import { Regex } from "../../patterns/Regex";
5
5
  import { Repeat } from "../../patterns/Repeat";
6
6
  import { escapedCharacter } from "./escapedCharacter";
7
+ import { Optional } from "../../patterns/Optional";
7
8
 
8
- const doubleQuoteStringLiteral = new And("double-string-literal", [
9
+ const doubleQuoteStringLiteral = new Sequence("double-string-literal", [
9
10
  new Literal("double-quote", "\""),
10
- new Repeat("characters",
11
- new Or("characters", [
11
+ new Optional("optional-characters", new Repeat("characters",
12
+ new Options("characters", [
12
13
  new Regex("normal-characters", "[^\\\"]+"),
13
14
  escapedCharacter
14
- ]),
15
- { min: 0 }
16
- ),
15
+ ])
16
+ )),
17
17
  new Literal("double-quote", "\""),
18
18
  ]);
19
19
 
20
- const singleQuoteStringLiteral = new And("single-string-literal", [
20
+ const singleQuoteStringLiteral = new Sequence("single-string-literal", [
21
21
  new Literal("single-quote", "'"),
22
- new Repeat("characters",
23
- new Or("characters", [
22
+ new Optional("optional-characters", new Repeat("characters",
23
+ new Options("characters", [
24
24
  new Regex("normal-characters", "[^\\']+"),
25
25
  escapedCharacter
26
26
  ]),
27
- { min: 0 }
28
- ),
27
+ )),
29
28
  new Literal("single-quote", "'"),
30
29
  ]);
31
30
 
32
- const stringLiteral = new Or("string-literal", [doubleQuoteStringLiteral, singleQuoteStringLiteral]);
31
+ const stringLiteral = new Options("string-literal", [doubleQuoteStringLiteral, singleQuoteStringLiteral]);
33
32
 
34
- export { stringLiteral }
33
+ export { stringLiteral };
@@ -1,5 +1,5 @@
1
1
  import { Node } from "../ast/Node";
2
- import { CursorHistory, Match } from "./CursorHistory";
2
+ import { CursorHistory, Match, Trace } from "./CursorHistory";
3
3
  import { ParseError } from "./ParseError";
4
4
  import { Pattern } from "./Pattern";
5
5
 
@@ -8,6 +8,7 @@ export class Cursor {
8
8
  private _index: number;
9
9
  private _length: number;
10
10
  private _history: CursorHistory;
11
+ private _stackTrace: Trace[];
11
12
 
12
13
  get text(): string {
13
14
  return this._text;
@@ -66,11 +67,11 @@ export class Cursor {
66
67
  }
67
68
 
68
69
  get hasError(): boolean {
69
- return this._history.error != null
70
+ return this._history.error != null;
70
71
  }
71
72
 
72
73
  get currentChar(): string {
73
- return this._text[this._index]
74
+ return this._text[this._index];
74
75
  }
75
76
 
76
77
  constructor(text: string) {
@@ -78,6 +79,7 @@ export class Cursor {
78
79
  this._index = 0;
79
80
  this._length = text.length;
80
81
  this._history = new CursorHistory();
82
+ this._stackTrace = [];
81
83
  }
82
84
 
83
85
  hasNext(): boolean {
@@ -131,7 +133,7 @@ export class Cursor {
131
133
  }
132
134
 
133
135
  resolveError(): void {
134
- this._history.resolveError()
136
+ this._history.resolveError();
135
137
  }
136
138
 
137
139
  startRecording(): void {
@@ -142,4 +144,40 @@ export class Cursor {
142
144
  this._history.stopRecording();
143
145
  }
144
146
 
147
+ startParseWith(pattern: Pattern) {
148
+ const patternName = pattern.name;
149
+
150
+ const trace = {
151
+ pattern,
152
+ cursorIndex: this.index
153
+ };
154
+
155
+ if (this._stackTrace.find(t => t.pattern.id === pattern.id && this.index === t.cursorIndex)) {
156
+ throw new Error(`Cyclical Pattern: ${this._stackTrace.map(t => `${t.pattern.name}#${t.pattern.id}{${t.cursorIndex}}`).join(" -> ")} -> ${patternName}#${pattern.id}{${this.index}}.`);
157
+ }
158
+
159
+ this._history.pushStackTrace(trace);
160
+ this._stackTrace.push(trace);
161
+ }
162
+
163
+ endParse() {
164
+ this._stackTrace.pop();
165
+ }
166
+
167
+ audit() {
168
+ return this._history.trace.map(t => {
169
+ const onChar = this.getChars(t.cursorIndex, t.cursorIndex);
170
+ const restChars = this.getChars(t.cursorIndex + 1, t.cursorIndex + 5);
171
+ const context = `{${t.cursorIndex}}[${onChar}]${restChars}`;
172
+ return `${this._buildPatternContext(t.pattern)}-->${context}`;
173
+ });
174
+ }
175
+
176
+ private _buildPatternContext(pattern: Pattern) {
177
+ if (pattern.parent != null) {
178
+ return `${pattern.parent.name}.${pattern.name}`;
179
+ }
180
+ return pattern.name;
181
+ }
182
+
145
183
  }
@@ -2,6 +2,11 @@ import { Node } from "../ast/Node";
2
2
  import { ParseError } from "./ParseError";
3
3
  import { Pattern } from "./Pattern";
4
4
 
5
+ export interface Trace {
6
+ pattern: Pattern;
7
+ cursorIndex: number;
8
+ }
9
+
5
10
  export interface Match {
6
11
  pattern: Pattern | null;
7
12
  node: Node | null;
@@ -16,6 +21,7 @@ export class CursorHistory {
16
21
  private _patterns: Pattern[] = [];
17
22
  private _nodes: Node[] = [];
18
23
  private _errors: ParseError[] = [];
24
+ private _trace: Trace[] = [];
19
25
 
20
26
  get isRecording(): boolean {
21
27
  return this._isRecording;
@@ -42,7 +48,7 @@ export class CursorHistory {
42
48
  }
43
49
 
44
50
  get error(): ParseError | null {
45
- return this._currentError
51
+ return this._currentError;
46
52
  }
47
53
 
48
54
  get nodes(): Node[] {
@@ -53,6 +59,10 @@ export class CursorHistory {
53
59
  return this._patterns;
54
60
  }
55
61
 
62
+ get trace(): Trace[] {
63
+ return this._trace;
64
+ }
65
+
56
66
  recordMatch(pattern: Pattern, node: Node): void {
57
67
  if (this._isRecording) {
58
68
  this._patterns.push(pattern);
@@ -67,7 +77,7 @@ export class CursorHistory {
67
77
  leafMatch.node === null || node.lastIndex > leafMatch.node.lastIndex;
68
78
 
69
79
  const isSameIndexMatch =
70
- leafMatch.node === null || node.lastIndex === leafMatch.node.lastIndex
80
+ leafMatch.node === null || node.lastIndex === leafMatch.node.lastIndex;
71
81
 
72
82
  if (isFurthestMatch) {
73
83
  // This is to save on GC churn.
@@ -85,10 +95,10 @@ export class CursorHistory {
85
95
  if (parent === pattern.parent) {
86
96
  return true;
87
97
  }
88
- parent = parent.parent
98
+ parent = parent.parent;
89
99
  }
90
100
  return false;
91
- })
101
+ });
92
102
 
93
103
  if (!isAncestor) {
94
104
  this._leafMatches.unshift({ pattern, node });
@@ -121,4 +131,10 @@ export class CursorHistory {
121
131
  this._currentError = null;
122
132
  }
123
133
 
134
+ pushStackTrace(trace: Trace) {
135
+ if (this._isRecording) {
136
+ this._trace.push(trace);
137
+ }
138
+ }
139
+
124
140
  }