clarity-pattern-parser 4.0.2 → 5.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 (132) hide show
  1. package/README.md +176 -1
  2. package/TODO.md +22 -2
  3. package/dist/ast/Node.d.ts +43 -11
  4. package/dist/ast/Visitor.d.ts +31 -31
  5. package/dist/index.browser.js +1248 -1495
  6. package/dist/index.browser.js.map +1 -1
  7. package/dist/index.d.ts +12 -16
  8. package/dist/index.esm.js +1218 -1460
  9. package/dist/index.esm.js.map +1 -1
  10. package/dist/index.js +1217 -1464
  11. package/dist/index.js.map +1 -1
  12. package/dist/patterns/And.d.ts +37 -24
  13. package/dist/patterns/Cursor.d.ts +35 -0
  14. package/dist/patterns/CursorHistory.d.ts +30 -0
  15. package/dist/patterns/Literal.d.ts +36 -19
  16. package/dist/patterns/Not.d.ts +26 -11
  17. package/dist/patterns/Or.d.ts +31 -22
  18. package/dist/patterns/ParseError.d.ts +6 -8
  19. package/dist/patterns/ParseResult.d.ts +6 -0
  20. package/dist/patterns/Pattern.d.ts +17 -26
  21. package/dist/patterns/Reference.d.ts +31 -12
  22. package/dist/patterns/Regex.d.ts +42 -21
  23. package/dist/patterns/Repeat.d.ts +38 -20
  24. package/dist/patterns/clonePatterns.d.ts +2 -0
  25. package/dist/patterns/filterOutNull.d.ts +2 -0
  26. package/dist/patterns/findPattern.d.ts +2 -0
  27. package/dist/patterns/getNextPattern.d.ts +2 -0
  28. package/jest.config.js +2 -1
  29. package/package.json +4 -5
  30. package/rollup.config.js +1 -1
  31. package/src/ast/Node.test.ts +254 -0
  32. package/src/ast/Node.ts +171 -23
  33. package/src/index.ts +11 -19
  34. package/src/intellisense/AutoComplete.test.ts +72 -0
  35. package/src/intellisense/AutoComplete.ts +146 -0
  36. package/src/intellisense/Suggestion.ts +13 -0
  37. package/src/intellisense/SuggestionOption.ts +4 -0
  38. package/src/{tests/cssPatterns → intellisense/css}/cssValue.ts +1 -1
  39. package/src/{tests/cssPatterns → intellisense/css}/divider.ts +2 -1
  40. package/src/intellisense/css/hex.ts +6 -0
  41. package/src/{tests/cssPatterns → intellisense/css}/method.ts +8 -9
  42. package/src/intellisense/css/name.ts +5 -0
  43. package/src/{tests/javascriptPatterns → intellisense/css}/number.ts +3 -3
  44. package/src/intellisense/css/spaces.ts +6 -0
  45. package/src/intellisense/css/unit.ts +10 -0
  46. package/src/{tests/cssPatterns → intellisense/css}/value.ts +1 -1
  47. package/src/{tests/cssPatterns → intellisense/css}/values.ts +1 -1
  48. package/src/intellisense/javascript/Javascript.test.ts +203 -0
  49. package/src/intellisense/javascript/arrayLiteral.ts +25 -0
  50. package/src/intellisense/javascript/deleteStatement.ts +14 -0
  51. package/src/intellisense/javascript/escapedCharacter.ts +50 -0
  52. package/src/intellisense/javascript/exponent.ts +26 -0
  53. package/src/intellisense/javascript/expression.ts +87 -0
  54. package/src/intellisense/javascript/expressionStatement.ts +29 -0
  55. package/src/intellisense/javascript/fraction.ts +13 -0
  56. package/src/intellisense/javascript/infixOperator.ts +36 -0
  57. package/src/intellisense/javascript/integer.ts +7 -0
  58. package/src/intellisense/javascript/invocation.ts +28 -0
  59. package/src/intellisense/javascript/literal.ts +14 -0
  60. package/src/intellisense/javascript/name.ts +3 -0
  61. package/src/intellisense/javascript/numberLiteral.ts +10 -0
  62. package/src/intellisense/javascript/objectLiteral.ts +30 -0
  63. package/src/intellisense/javascript/optionalSpaces.ts +3 -0
  64. package/src/intellisense/javascript/parameters.ts +20 -0
  65. package/src/intellisense/javascript/prefixOperator.ts +13 -0
  66. package/src/intellisense/javascript/propertyAccess.ts +23 -0
  67. package/src/intellisense/javascript/stringLiteral.ts +28 -0
  68. package/src/patterns/And.test.ts +299 -0
  69. package/src/patterns/And.ts +222 -119
  70. package/src/patterns/Cursor.test.ts +93 -0
  71. package/src/patterns/Cursor.ts +130 -0
  72. package/src/patterns/CursorHistory.test.ts +54 -0
  73. package/src/patterns/CursorHistory.ts +95 -0
  74. package/src/patterns/Literal.test.ts +134 -0
  75. package/src/patterns/Literal.ts +151 -61
  76. package/src/patterns/Not.test.ts +88 -0
  77. package/src/patterns/Not.ts +74 -33
  78. package/src/patterns/Or.test.ts +105 -0
  79. package/src/patterns/Or.ts +106 -98
  80. package/src/patterns/ParseError.ts +3 -7
  81. package/src/patterns/ParseResult.ts +7 -0
  82. package/src/patterns/Pattern.ts +18 -150
  83. package/src/patterns/Reference.test.ts +104 -0
  84. package/src/patterns/Reference.ts +94 -94
  85. package/src/patterns/Regex.test.ts +101 -0
  86. package/src/patterns/Regex.ts +129 -60
  87. package/src/patterns/Repeat.test.ts +196 -0
  88. package/src/patterns/Repeat.ts +208 -104
  89. package/src/patterns/clonePatterns.ts +5 -0
  90. package/src/patterns/filterOutNull.ts +13 -0
  91. package/src/patterns/findPattern.ts +25 -0
  92. package/src/patterns/getNextPattern.test.ts +39 -0
  93. package/src/patterns/getNextPattern.ts +18 -0
  94. package/src/Cursor.ts +0 -141
  95. package/src/CursorHistory.ts +0 -146
  96. package/src/TextSuggester.ts +0 -317
  97. package/src/ast/Visitor.ts +0 -271
  98. package/src/patterns/LookAhead.ts +0 -32
  99. package/src/patterns/Recursive.ts +0 -92
  100. package/src/tests/And.test.ts +0 -180
  101. package/src/tests/ComplexExamples.test.ts +0 -86
  102. package/src/tests/CssPatterns.test.ts +0 -90
  103. package/src/tests/CursorHistory.test.ts +0 -107
  104. package/src/tests/Cusor.test.ts +0 -174
  105. package/src/tests/HtmlPatterns.test.ts +0 -34
  106. package/src/tests/Literal.test.ts +0 -79
  107. package/src/tests/LookAhead.test.ts +0 -44
  108. package/src/tests/Not.test.ts +0 -51
  109. package/src/tests/Or.test.ts +0 -113
  110. package/src/tests/Pattern.test.ts +0 -290
  111. package/src/tests/Recursive.test.ts +0 -64
  112. package/src/tests/Reference.test.ts +0 -16
  113. package/src/tests/Repeat.test.ts +0 -75
  114. package/src/tests/SpeedTest.test.ts +0 -31
  115. package/src/tests/TextSuggester.test.ts +0 -297
  116. package/src/tests/Visitor.test.ts +0 -331
  117. package/src/tests/cssPatterns/hex.ts +0 -5
  118. package/src/tests/cssPatterns/name.ts +0 -5
  119. package/src/tests/cssPatterns/number.ts +0 -8
  120. package/src/tests/cssPatterns/spaces.ts +0 -5
  121. package/src/tests/cssPatterns/unit.ts +0 -8
  122. package/src/tests/htmlPatterns/element.ts +0 -49
  123. package/src/tests/javascriptPatterns/boolean.ts +0 -10
  124. package/src/tests/javascriptPatterns/json.ts +0 -67
  125. package/src/tests/javascriptPatterns/name.ts +0 -5
  126. package/src/tests/javascriptPatterns/objectLiteral.ts +0 -40
  127. package/src/tests/javascriptPatterns/string.ts +0 -84
  128. package/src/tests/javascriptPatterns/unit.ts +0 -8
  129. package/src/tests/javascriptPatterns/whitespace.ts +0 -44
  130. package/src/tests/naturalLanguage/filter.ts +0 -37
  131. package/src/tests/patterns/sentence.ts +0 -37
  132. /package/src/{tests/cssPatterns → intellisense/css}/optionalSpaces.ts +0 -0
@@ -1,127 +1,127 @@
1
- import Pattern from "./Pattern";
2
- import ParserError from "./ParseError";
3
- import Cursor from "../Cursor";
1
+ import { Node } from "../ast/Node";
2
+ import { Cursor } from "./Cursor";
3
+ import { Pattern } from "./Pattern";
4
+ import { findPattern } from "./findPattern";
5
+ import { getNextPattern } from "./getNextPattern";
6
+
7
+ export class Reference implements Pattern {
8
+ private _type: string;
9
+ private _name: string;
10
+ private _parent: Pattern | null;
11
+ private _isOptional: boolean;
12
+ private _pattern: Pattern | null;
13
+ private _children: Pattern[];
14
+
15
+ get type(): string {
16
+ return this._type;
17
+ }
4
18
 
5
- export default class Reference extends Pattern {
6
- constructor(name: string, isOptional = false) {
7
- super("reference", name, [], isOptional);
19
+ get name(): string {
20
+ return this._name;
8
21
  }
9
22
 
10
- private getRoot() {
11
- let node = this.parent;
12
- while (node != null) {
13
- if (node.parent == null) {
14
- return node;
15
- }
16
- node = node.parent;
17
- }
18
- return node;
23
+ get isOptional(): boolean {
24
+ return this._isOptional;
19
25
  }
20
26
 
21
- private findPattern(): Pattern | null {
22
- const root = this.getRoot();
23
- let result: Pattern | null = null;
27
+ get parent(): Pattern | null {
28
+ return this._parent;
29
+ }
24
30
 
25
- if (root == null) {
26
- return null;
27
- }
31
+ set parent(pattern: Pattern | null) {
32
+ this._parent = pattern;
33
+ }
28
34
 
29
- this.walkTheTree(root, (pattern) => {
30
- if (
31
- pattern.name === this.name &&
32
- pattern != this &&
33
- pattern.type != "reference"
34
- ) {
35
- result = pattern;
36
- return false;
37
- }
38
- return true;
39
- });
35
+ get children(): Pattern[] {
36
+ return this._children
37
+ }
40
38
 
41
- return result;
39
+ constructor(name: string, isOptional: boolean = false) {
40
+ this._type = "reference";
41
+ this._name = name;
42
+ this._parent = null;
43
+ this._isOptional = isOptional;
44
+ this._pattern = null;
45
+ this._children = [];
42
46
  }
43
47
 
44
- private walkTheTree(
45
- pattern: Pattern,
46
- callback: (pattern: Pattern) => boolean
47
- ) {
48
- for (let x = 0; x < pattern.children.length; x++) {
49
- const p = pattern.children[x];
50
- const continueWalking = this.walkTheTree(p, callback);
48
+ parseText(text: string) {
49
+ const cursor = new Cursor(text);
50
+ const ast = this.parse(cursor)
51
51
 
52
- if (!continueWalking) {
53
- return false;
54
- }
52
+ return {
53
+ ast,
54
+ cursor
55
+ };
56
+ }
57
+
58
+ parse(cursor: Cursor): Node | null {
59
+ return this._getPatternSafely().parse(cursor);
60
+ }
61
+
62
+ clone(name = this._name, isOptional = this._isOptional): Pattern {
63
+ return new Reference(name, isOptional);
64
+ }
65
+
66
+ getTokens(): string[] {
67
+ return this._getPatternSafely().getTokens();
68
+ }
69
+
70
+ getNextTokens(_lastMatched: Pattern): string[] {
71
+ if (this.parent == null) {
72
+ return [];
55
73
  }
56
74
 
57
- return callback(pattern);
75
+ return this.parent.getNextTokens(this);
58
76
  }
59
77
 
60
- parse(cursor: Cursor) {
61
- const mark = cursor.mark();
78
+ getNextPattern(): Pattern | null {
79
+ return getNextPattern(this)
80
+ }
62
81
 
63
- try {
64
- const node = this.safelyGetPattern().parse(cursor);
82
+ findPattern(_isMatch: (p: Pattern)=>boolean): Pattern | null{
83
+ return null;
84
+ }
65
85
 
66
- if (!cursor.hasUnresolvedError() && node != null) {
67
- cursor.addMatch(this, node);
68
- }
86
+ private _getPatternSafely(): Pattern {
87
+ if (this._pattern === null) {
88
+ const pattern = this._findPattern();
69
89
 
70
- if (cursor.hasUnresolvedError() && this._isOptional) {
71
- cursor.resolveError();
72
- cursor.moveToMark(mark);
90
+ if (pattern === null) {
91
+ throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
73
92
  }
74
93
 
75
- return node;
76
- } catch (error) {
77
- if (this._isOptional) {
78
- cursor.moveToMark(mark);
79
- } else {
80
- cursor.throwError(
81
- new ParserError(
82
- `Couldn't find reference pattern to parse, with the name ${this.name}.`,
83
- cursor.index,
84
- this as Pattern
85
- )
86
- );
87
- }
94
+ const clonedPattern = pattern.clone(this._name, this._isOptional);
95
+ clonedPattern.parent = this;
88
96
 
89
- return null;
97
+ this._pattern = clonedPattern;
98
+ this._children = [this._pattern];
90
99
  }
91
- }
92
100
 
93
- clone(name?: string, isOptional?: boolean) {
94
- if (name == null) {
95
- name = this.name;
96
- }
101
+ return this._pattern;
102
+ }
97
103
 
98
- if (isOptional == null) {
99
- isOptional = this._isOptional;
100
- }
104
+ private _findPattern(): Pattern | null {
105
+ const root = this._getRoot();
101
106
 
102
- return new Reference(name, isOptional);
107
+ return findPattern(root, (pattern: Pattern) => {
108
+ return pattern.name === this._name && pattern.type !== "reference";
109
+ });
103
110
  }
104
111
 
105
- private safelyGetPattern() {
106
- let pattern = this.children[0];
107
- const hasNoPattern = pattern == null;
112
+ private _getRoot(): Pattern {
113
+ let node: Pattern = this;
108
114
 
109
- if (hasNoPattern) {
110
- const reference = this.findPattern();
111
- if (reference == null) {
112
- throw new Error(
113
- `Couldn't find reference pattern, with the name ${this.name}.`
114
- );
115
- }
115
+ while (true) {
116
+ const parent = node.parent;
116
117
 
117
- pattern = reference;
118
- this.children = [pattern];
118
+ if (parent == null) {
119
+ break;
120
+ } else {
121
+ node = parent
122
+ }
119
123
  }
120
124
 
121
- return pattern;
122
- }
123
-
124
- getTokens() {
125
- return this.safelyGetPattern().getTokens();
125
+ return node;
126
126
  }
127
127
  }
@@ -0,0 +1,101 @@
1
+ import { Cursor } from "./Cursor";
2
+ import { Regex } from "./Regex";
3
+ import { Node } from "../ast/Node"
4
+ import { And } from "./And";
5
+ import { Literal } from "./Literal";
6
+
7
+ describe("Regex", () => {
8
+ test("Empty String", () => {
9
+ expect(() => new Regex("empty", "")).toThrowError()
10
+ });
11
+
12
+ test("Starts With ^", () => {
13
+ expect(() => new Regex("carrot", "^")).toThrowError()
14
+ });
15
+
16
+ test("Ends With $", () => {
17
+ expect(() => new Regex("money", ".$")).toThrowError()
18
+ });
19
+
20
+ test("Successful Parse", () => {
21
+ const number = new Regex("number", "\\d");
22
+ const cursor = new Cursor("1");
23
+ const result = number.parse(cursor);
24
+ const expected = new Node("regex", "number", 0, 0, [], "1");
25
+
26
+ expect(result).toEqual(expected);
27
+ expect(cursor.hasError).toBeFalsy()
28
+ })
29
+
30
+ test("Failed Parse", () => {
31
+ const number = new Regex("number", "\\d");
32
+ const cursor = new Cursor("F");
33
+ const result = number.parse(cursor);
34
+
35
+ expect(result).toBeNull();
36
+ expect(cursor.hasError).toBeTruthy()
37
+ });
38
+
39
+
40
+ test("Get Tokens", () => {
41
+ const parent = new And("parent", [
42
+ new Regex("a", "A"),
43
+ new Regex("b", "B")
44
+ ]);
45
+
46
+ const a = parent.children[0] as Regex;
47
+ const b = parent.children[1] as Regex;
48
+
49
+ a.setTokens(["A"]);
50
+ b.setTokens(["B"]);
51
+
52
+ let tokens = a.getTokens();
53
+ let expectedTokens = ["A"];
54
+
55
+ expect(tokens).toEqual(expectedTokens);
56
+
57
+ a.enableContextualTokenAggregation();
58
+
59
+ tokens = a.getTokens();
60
+ expectedTokens = ["AB"];
61
+
62
+ expect(tokens).toEqual(expectedTokens);
63
+
64
+ a.disableContextualTokenAggregation();
65
+
66
+ tokens = a.getTokens();
67
+ expectedTokens = ["A"];
68
+
69
+ expect(tokens).toEqual(expectedTokens);
70
+ });
71
+
72
+ test("Get Next Tokens", () => {
73
+ const regex = new Regex("a", "A");
74
+ const tokens = regex.getNextTokens(new Literal("bogus", "bogus"));
75
+ const expected: string[] = [];
76
+
77
+ expect(tokens).toEqual(expected)
78
+ });
79
+
80
+ test("Get Next Pattern", () => {
81
+ const regex = new Regex("a", "A");
82
+ const nextPattern = regex.getNextPattern();
83
+
84
+ expect(nextPattern).toBeNull()
85
+ });
86
+
87
+ test("Properties", () => {
88
+ const regex = new Regex("a", "A");
89
+
90
+ expect(regex.type).toBe("regex");
91
+ expect(regex.name).toBe("a");
92
+ expect(regex.parent).toBeNull();
93
+ expect(regex.children).toEqual([]);
94
+ });
95
+
96
+ test("Parse Text", () => {
97
+ const regex = new Regex("a", "A");
98
+ const { ast: result } = regex.parseText("B");
99
+ expect(result).toBeNull();
100
+ });
101
+ });
@@ -1,123 +1,192 @@
1
- import ParseError from "./ParseError";
2
- import Node from "../ast/Node";
3
- import Pattern from "./Pattern";
4
- import Cursor from "../Cursor";
5
-
6
- export default class Regex extends Pattern {
7
- private regexString: string;
8
- private regex: RegExp;
9
- private node: Node | null = null;
10
- private cursor: Cursor | null = null;
11
- private substring: string = "";
1
+ import { Node } from "../ast/Node";
2
+ import { Pattern } from "./Pattern";
3
+ import { Cursor } from "./Cursor";
4
+ import { getNextPattern } from "./getNextPattern";
5
+
6
+ export class Regex implements Pattern {
7
+ private _type: string;
8
+ private _name: string;
9
+ private _isOptional: boolean;
10
+ private _parent: Pattern | null;
11
+ private _originalRegexString: string;
12
+ private _regex: RegExp;
13
+ private _node: Node | null = null;
14
+ private _cursor: Cursor | null = null;
15
+ private _substring: string = "";
16
+ private _tokens: string[] = [];
17
+ private _hasContextualTokenAggregation = false;
18
+ private _isRetrievingContextualTokens: boolean = false;
19
+
20
+ get type(): string {
21
+ return this._type;
22
+ }
23
+
24
+ get name(): string {
25
+ return this._name;
26
+ }
27
+
28
+ get parent(): Pattern | null {
29
+ return this._parent;
30
+ }
31
+
32
+ set parent(pattern: Pattern | null) {
33
+ this._parent = pattern;
34
+ }
35
+
36
+ get children(): Pattern[] {
37
+ return [];
38
+ }
39
+
40
+ get isOptional(): boolean {
41
+ return this._isOptional;
42
+ }
12
43
 
13
44
  constructor(name: string, regex: string, isOptional = false) {
14
- super("regex", name, [], isOptional);
15
- this.regexString = regex;
16
- this.regex = new RegExp(`^${regex}`, "g");
45
+ this._type = "regex"
46
+ this._name = name;
47
+ this._isOptional = isOptional;
48
+ this._parent = null;
49
+ this._originalRegexString = regex;
50
+ this._regex = new RegExp(`^${regex}`, "g");
17
51
  this.assertArguments();
18
52
  }
19
53
 
20
54
  private assertArguments() {
21
- if (this.regexString.length < 1) {
55
+ if (this._originalRegexString.length < 1) {
22
56
  throw new Error(
23
57
  "Invalid Arguments: The regex string argument needs to be at least one character long."
24
58
  );
25
59
  }
26
60
 
27
- if (this.regexString.charAt(0) === "^") {
61
+ if (this._originalRegexString.charAt(0) === "^") {
28
62
  throw new Error(
29
63
  "Invalid Arguments: The regex string cannot start with a '^' because it is expected to be in the middle of a string."
30
64
  );
31
65
  }
32
66
 
33
- if (this.regexString.charAt(this.regexString.length - 1) === "$") {
67
+ if (this._originalRegexString.charAt(this._originalRegexString.length - 1) === "$") {
34
68
  throw new Error(
35
69
  "Invalid Arguments: The regex string cannot end with a '$' because it is expected to be in the middle of a string."
36
70
  );
37
71
  }
38
72
  }
39
73
 
74
+ parseText(text: string) {
75
+ const cursor = new Cursor(text);
76
+ const ast = this.parse(cursor)
77
+
78
+ return {
79
+ ast,
80
+ cursor
81
+ };
82
+ }
83
+
40
84
  parse(cursor: Cursor) {
41
85
  this.resetState(cursor);
42
- this.tryToParse();
86
+ this.tryToParse(cursor);
43
87
 
44
- return this.node;
88
+ return this._node;
45
89
  }
46
90
 
47
91
  private resetState(cursor: Cursor) {
48
- this.cursor = cursor;
49
- this.regex.lastIndex = 0;
50
- this.substring = this.cursor.text.substr(this.cursor.getIndex());
51
- this.node = null;
92
+ this._cursor = cursor;
93
+ this._regex.lastIndex = 0;
94
+ this._substring = this._cursor.text.substr(this._cursor.index);
95
+ this._node = null;
52
96
  }
53
97
 
54
- private tryToParse() {
55
- const result = this.regex.exec(this.substring);
98
+ private tryToParse(cursor: Cursor) {
99
+ const result = this._regex.exec(this._substring);
56
100
 
57
101
  if (result != null && result.index === 0) {
58
- this.processResult(result);
102
+ this.processResult(cursor, result);
59
103
  } else {
60
- this.processError();
104
+ this.processError(cursor);
61
105
  }
62
106
  }
63
107
 
64
- private processResult(result: RegExpExecArray) {
65
- const cursor = this.safelyGetCursor();
66
- const currentIndex = cursor.getIndex();
108
+ private processResult(cursor: Cursor, result: RegExpExecArray) {
109
+ const currentIndex = cursor.index;
67
110
  const newIndex = currentIndex + result[0].length - 1;
68
111
 
69
- this.node = new Node(
112
+ this._node = new Node(
70
113
  "regex",
71
- this.name,
114
+ this._name,
72
115
  currentIndex,
73
116
  newIndex,
74
117
  [],
75
118
  result[0]
76
119
  );
77
120
 
78
- cursor.moveToMark(newIndex);
79
- cursor.addMatch(this, this.node);
121
+ cursor.moveTo(newIndex);
122
+ cursor.recordMatch(this, this._node);
80
123
  }
81
124
 
82
- private processError() {
83
- const cursor = this.safelyGetCursor();
84
-
125
+ private processError(cursor: Cursor) {
85
126
  if (!this._isOptional) {
86
- const message = `ParseError: Expected regex pattern of '${this.regexString}' but found '${this.substring}'.`;
87
- const parseError = new ParseError(message, cursor.getIndex(), this);
88
-
89
- cursor.throwError(parseError);
127
+ cursor.recordErrorAt(cursor.index, this);
90
128
  }
91
129
 
92
- this.node = null;
130
+ this._node = null;
93
131
  }
94
132
 
95
- private safelyGetCursor() {
96
- const cursor = this.cursor;
133
+ clone(name = this._name, isOptional = this._isOptional) {
134
+ const pattern = new Regex(name, this._originalRegexString, isOptional);
135
+ pattern._tokens = this._tokens.slice();
136
+ pattern._hasContextualTokenAggregation =
137
+ this._hasContextualTokenAggregation;
97
138
 
98
- if (cursor == null) {
99
- throw new Error("Couldn't find cursor.");
100
- }
101
- return cursor;
139
+ return pattern;
102
140
  }
103
141
 
104
- clone(name?: string, isOptional?: boolean) {
105
- if (name == null) {
106
- name = this.name;
142
+ getTokens() {
143
+ const parent = this._parent;
144
+
145
+ if (this._hasContextualTokenAggregation &&
146
+ parent != null &&
147
+ !this._isRetrievingContextualTokens
148
+ ) {
149
+ this._isRetrievingContextualTokens = true;
150
+
151
+ const tokens = this._tokens;
152
+ const aggregateTokens: string[] = [];
153
+ const nextTokens = parent.getNextTokens(this);
154
+
155
+ for (let nextToken of nextTokens) {
156
+ for (let token of tokens) {
157
+ aggregateTokens.push(token + nextToken);
158
+ }
159
+ }
160
+
161
+ this._isRetrievingContextualTokens = false
162
+ return aggregateTokens;
107
163
  }
108
164
 
109
- if (isOptional == null) {
110
- isOptional = this._isOptional;
111
- }
165
+ return this._tokens;
166
+ }
112
167
 
113
- return new Regex(name, this.regexString, isOptional);
168
+ getNextTokens(_reference: Pattern): string[] {
169
+ return [];
114
170
  }
115
171
 
116
- getTokenValue() {
117
- return this.name;
172
+ getNextPattern(): Pattern | null {
173
+ return getNextPattern(this)
174
+ }
175
+
176
+ findPattern(_isMatch: (p: Pattern)=>boolean): Pattern | null{
177
+ return null;
118
178
  }
119
179
 
120
- getTokens() {
121
- return [this.name];
180
+ setTokens(tokens: string[]) {
181
+ this._tokens = tokens;
182
+ }
183
+
184
+ enableContextualTokenAggregation() {
185
+ this._hasContextualTokenAggregation = true;
122
186
  }
123
- }
187
+
188
+ disableContextualTokenAggregation() {
189
+ this._hasContextualTokenAggregation = false;
190
+ }
191
+
192
+ }