clarity-pattern-parser 4.0.3 → 6.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 (133) hide show
  1. package/README.md +466 -1
  2. package/TODO.md +76 -2
  3. package/dist/ast/Node.d.ts +49 -11
  4. package/dist/ast/Visitor.d.ts +31 -31
  5. package/dist/index.browser.js +1513 -1495
  6. package/dist/index.browser.js.map +1 -1
  7. package/dist/index.d.ts +17 -17
  8. package/dist/index.esm.js +1480 -1459
  9. package/dist/index.esm.js.map +1 -1
  10. package/dist/index.js +1481 -1463
  11. package/dist/index.js.map +1 -1
  12. package/dist/intellisense/AutoComplete.d.ts +28 -0
  13. package/dist/intellisense/Suggestion.d.ts +11 -0
  14. package/dist/intellisense/SuggestionOption.d.ts +4 -0
  15. package/dist/patterns/And.d.ts +37 -24
  16. package/dist/patterns/Cursor.d.ts +37 -0
  17. package/dist/patterns/CursorHistory.d.ts +30 -0
  18. package/dist/patterns/Literal.d.ts +35 -19
  19. package/dist/patterns/Not.d.ts +29 -11
  20. package/dist/patterns/Or.d.ts +33 -22
  21. package/dist/patterns/ParseError.d.ts +6 -8
  22. package/dist/patterns/ParseResult.d.ts +6 -0
  23. package/dist/patterns/Pattern.d.ts +20 -26
  24. package/dist/patterns/Reference.d.ts +34 -12
  25. package/dist/patterns/Regex.d.ts +41 -21
  26. package/dist/patterns/Repeat.d.ts +38 -20
  27. package/dist/patterns/clonePatterns.d.ts +2 -0
  28. package/dist/patterns/filterOutNull.d.ts +2 -0
  29. package/dist/patterns/findPattern.d.ts +2 -0
  30. package/dist/patterns/getNextPattern.d.ts +2 -0
  31. package/jest.config.js +2 -1
  32. package/package.json +4 -5
  33. package/rollup.config.js +1 -1
  34. package/src/ast/Node.test.ts +364 -0
  35. package/src/ast/Node.ts +237 -23
  36. package/src/index.ts +25 -27
  37. package/src/intellisense/AutoComplete.test.ts +150 -0
  38. package/src/intellisense/AutoComplete.ts +200 -0
  39. package/src/intellisense/Suggestion.ts +12 -0
  40. package/src/intellisense/SuggestionOption.ts +4 -0
  41. package/src/{tests/cssPatterns → intellisense/css}/cssValue.ts +1 -1
  42. package/src/{tests/cssPatterns → intellisense/css}/divider.ts +2 -1
  43. package/src/intellisense/css/hex.ts +6 -0
  44. package/src/{tests/cssPatterns → intellisense/css}/method.ts +8 -9
  45. package/src/intellisense/css/name.ts +5 -0
  46. package/src/{tests/javascriptPatterns → intellisense/css}/number.ts +3 -3
  47. package/src/intellisense/css/spaces.ts +6 -0
  48. package/src/intellisense/css/unit.ts +10 -0
  49. package/src/{tests/cssPatterns → intellisense/css}/value.ts +1 -1
  50. package/src/{tests/cssPatterns → intellisense/css}/values.ts +1 -1
  51. package/src/intellisense/javascript/Javascript.test.ts +203 -0
  52. package/src/intellisense/javascript/arrayLiteral.ts +25 -0
  53. package/src/intellisense/javascript/deleteStatement.ts +14 -0
  54. package/src/intellisense/javascript/escapedCharacter.ts +49 -0
  55. package/src/intellisense/javascript/exponent.ts +24 -0
  56. package/src/intellisense/javascript/expression.ts +87 -0
  57. package/src/intellisense/javascript/expressionStatement.ts +29 -0
  58. package/src/intellisense/javascript/fraction.ts +11 -0
  59. package/src/intellisense/javascript/infixOperator.ts +36 -0
  60. package/src/intellisense/javascript/integer.ts +7 -0
  61. package/src/intellisense/javascript/invocation.ts +28 -0
  62. package/src/intellisense/javascript/literal.ts +14 -0
  63. package/src/intellisense/javascript/name.ts +3 -0
  64. package/src/intellisense/javascript/numberLiteral.ts +10 -0
  65. package/src/intellisense/javascript/objectLiteral.ts +30 -0
  66. package/src/intellisense/javascript/optionalSpaces.ts +3 -0
  67. package/src/intellisense/javascript/parameters.ts +20 -0
  68. package/src/intellisense/javascript/prefixOperator.ts +13 -0
  69. package/src/intellisense/javascript/propertyAccess.ts +23 -0
  70. package/src/intellisense/javascript/stringLiteral.ts +28 -0
  71. package/src/patterns/And.test.ts +310 -0
  72. package/src/patterns/And.ts +244 -119
  73. package/src/patterns/Cursor.test.ts +93 -0
  74. package/src/patterns/Cursor.ts +133 -0
  75. package/src/patterns/CursorHistory.test.ts +54 -0
  76. package/src/patterns/CursorHistory.ts +95 -0
  77. package/src/patterns/Literal.test.ts +166 -0
  78. package/src/patterns/Literal.ts +141 -62
  79. package/src/patterns/Not.test.ts +168 -0
  80. package/src/patterns/Not.ts +113 -32
  81. package/src/patterns/Or.test.ts +209 -0
  82. package/src/patterns/Or.ts +128 -97
  83. package/src/patterns/ParseError.ts +3 -7
  84. package/src/patterns/ParseResult.ts +7 -0
  85. package/src/patterns/Pattern.ts +21 -150
  86. package/src/patterns/Reference.test.ts +193 -0
  87. package/src/patterns/Reference.ts +114 -88
  88. package/src/patterns/Regex.test.ts +133 -0
  89. package/src/patterns/Regex.ts +117 -60
  90. package/src/patterns/Repeat.test.ts +218 -0
  91. package/src/patterns/Repeat.ts +220 -103
  92. package/src/patterns/clonePatterns.ts +5 -0
  93. package/src/patterns/filterOutNull.ts +13 -0
  94. package/src/patterns/findPattern.ts +25 -0
  95. package/src/Cursor.ts +0 -141
  96. package/src/CursorHistory.ts +0 -146
  97. package/src/TextSuggester.ts +0 -317
  98. package/src/ast/Visitor.ts +0 -271
  99. package/src/patterns/LookAhead.ts +0 -32
  100. package/src/patterns/Recursive.ts +0 -92
  101. package/src/tests/And.test.ts +0 -180
  102. package/src/tests/ComplexExamples.test.ts +0 -86
  103. package/src/tests/CssPatterns.test.ts +0 -90
  104. package/src/tests/CursorHistory.test.ts +0 -107
  105. package/src/tests/Cusor.test.ts +0 -174
  106. package/src/tests/HtmlPatterns.test.ts +0 -34
  107. package/src/tests/Literal.test.ts +0 -79
  108. package/src/tests/LookAhead.test.ts +0 -44
  109. package/src/tests/Not.test.ts +0 -51
  110. package/src/tests/Or.test.ts +0 -113
  111. package/src/tests/Pattern.test.ts +0 -290
  112. package/src/tests/Recursive.test.ts +0 -64
  113. package/src/tests/Reference.test.ts +0 -16
  114. package/src/tests/Repeat.test.ts +0 -75
  115. package/src/tests/SpeedTest.test.ts +0 -31
  116. package/src/tests/TextSuggester.test.ts +0 -297
  117. package/src/tests/Visitor.test.ts +0 -331
  118. package/src/tests/cssPatterns/hex.ts +0 -5
  119. package/src/tests/cssPatterns/name.ts +0 -5
  120. package/src/tests/cssPatterns/number.ts +0 -8
  121. package/src/tests/cssPatterns/spaces.ts +0 -5
  122. package/src/tests/cssPatterns/unit.ts +0 -8
  123. package/src/tests/htmlPatterns/element.ts +0 -49
  124. package/src/tests/javascriptPatterns/boolean.ts +0 -10
  125. package/src/tests/javascriptPatterns/json.ts +0 -67
  126. package/src/tests/javascriptPatterns/name.ts +0 -5
  127. package/src/tests/javascriptPatterns/objectLiteral.ts +0 -40
  128. package/src/tests/javascriptPatterns/string.ts +0 -84
  129. package/src/tests/javascriptPatterns/unit.ts +0 -8
  130. package/src/tests/javascriptPatterns/whitespace.ts +0 -44
  131. package/src/tests/naturalLanguage/filter.ts +0 -37
  132. package/src/tests/patterns/sentence.ts +0 -37
  133. /package/src/{tests/cssPatterns → intellisense/css}/optionalSpaces.ts +0 -0
@@ -1,132 +1,163 @@
1
- import Pattern from "./Pattern";
2
- import ParseError from "./ParseError";
3
- import Cursor from "../Cursor";
4
- import Node from "../ast/Node";
5
-
6
- export default class Or extends Pattern {
7
- public patternIndex: number = 0;
8
- public errors: ParseError[] = [];
9
- public node: Node | null = null;
10
- public cursor: Cursor | null = null;
11
- public mark: number = 0;
12
- public parseError: ParseError | null = null;
13
-
14
- constructor(name: string, patterns: Pattern[], isOptional = false) {
15
- super("or", name, patterns, isOptional);
16
- this.assertArguments();
17
- }
18
-
19
- private assertArguments() {
20
- if (this._children.length < 2) {
21
- throw new Error(
22
- "Invalid Argument: OrValue needs to have more than one value pattern."
23
- );
24
- }
1
+ import { Node } from "../ast/Node";
2
+ import { Cursor } from "./Cursor";
3
+ import { Pattern } from "./Pattern";
4
+ import { clonePatterns } from "./clonePatterns";
5
+ import { findPattern } from "./findPattern";
6
+
7
+ export class Or implements Pattern {
8
+ private _type: string;
9
+ private _name: string;
10
+ private _parent: Pattern | null;
11
+ private _children: Pattern[];
12
+ private _isOptional: boolean;
13
+ private _firstIndex: number;
14
+
15
+ get type(): string {
16
+ return this._type;
17
+ }
25
18
 
26
- const hasOptionalChildren = this._children.some(
27
- (pattern) => pattern.isOptional
28
- );
19
+ get name(): string {
20
+ return this._name;
21
+ }
29
22
 
30
- if (hasOptionalChildren) {
31
- throw new Error("OrValues cannot have optional patterns.");
32
- }
23
+ get parent(): Pattern | null {
24
+ return this._parent;
25
+ }
26
+
27
+ set parent(pattern: Pattern | null) {
28
+ this._parent = pattern;
33
29
  }
34
30
 
35
- private resetState(cursor: Cursor) {
36
- this.patternIndex = 0;
37
- this.errors = [];
38
- this.node = null;
39
- this.cursor = cursor;
40
- this.mark = cursor.mark();
31
+ get children(): Pattern[] {
32
+ return this._children;
41
33
  }
42
34
 
43
- private safelyGetCursor() {
44
- const cursor = this.cursor;
35
+ get isOptional(): boolean {
36
+ return this._isOptional;
37
+ }
45
38
 
46
- if (cursor == null) {
47
- throw new Error("Couldn't find cursor.");
39
+ constructor(name: string, options: Pattern[], isOptional: boolean = false) {
40
+ if (options.length === 0) {
41
+ throw new Error("Need at least one pattern with an 'or' pattern.");
48
42
  }
49
- return cursor;
43
+
44
+ const children = clonePatterns(options, false);
45
+ this._assignChildrenToParent(children);
46
+
47
+ this._type = "or";
48
+ this._name = name;
49
+ this._parent = null;
50
+ this._children = children;
51
+ this._isOptional = isOptional;
52
+ this._firstIndex = 0;
50
53
  }
51
54
 
52
- parse(cursor: Cursor) {
53
- this.resetState(cursor);
54
- this.tryToParse();
55
+ private _assignChildrenToParent(children: Pattern[]): void {
56
+ for (const child of children) {
57
+ child.parent = this;
58
+ }
59
+ }
60
+
61
+ test(text: string) {
62
+ const cursor = new Cursor(text);
63
+ const ast = this.parse(cursor);
55
64
 
56
- return this.node;
65
+ return ast?.value === text;
57
66
  }
58
67
 
59
- private tryToParse() {
60
- const cursor = this.safelyGetCursor();
68
+ exec(text: string) {
69
+ const cursor = new Cursor(text);
70
+ const ast = this.parse(cursor);
61
71
 
62
- while (true) {
63
- const pattern = this._children[this.patternIndex];
64
- const node = pattern.parse(cursor);
65
- const hasError = cursor.hasUnresolvedError();
72
+ return {
73
+ ast: ast?.value === text ? ast : null,
74
+ cursor
75
+ };
76
+ }
66
77
 
67
- if (hasError) {
68
- const shouldBreak = this.processError();
69
- if (shouldBreak) {
70
- break;
71
- }
72
- } else if (node != null) {
73
- this.processResult(node);
74
- break;
75
- }
78
+ parse(cursor: Cursor): Node | null {
79
+ this._firstIndex = cursor.index;
80
+
81
+ const node = this._tryToParse(cursor);
82
+
83
+ if (node != null) {
84
+ cursor.resolveError();
85
+ return node
86
+ }
87
+
88
+ if (!this._isOptional) {
89
+ cursor.recordErrorAt(this._firstIndex, this)
90
+ return null;
76
91
  }
92
+
93
+ cursor.resolveError();
94
+ cursor.moveTo(this._firstIndex);
95
+ return null;
77
96
  }
78
97
 
79
- private processError() {
80
- const cursor = this.safelyGetCursor();
81
- const isLastPattern = this.patternIndex + 1 === this._children.length;
98
+ private _tryToParse(cursor: Cursor): Node | null {
99
+ for (const pattern of this._children) {
100
+ cursor.moveTo(this._firstIndex);
101
+ const result = pattern.parse(cursor);
82
102
 
83
- if (!isLastPattern) {
84
- this.patternIndex++;
85
- cursor.resolveError();
86
- cursor.moveToMark(this.mark);
87
- return false;
88
- } else {
89
- if (this._isOptional) {
90
- cursor.resolveError();
91
- cursor.moveToMark(this.mark);
103
+ if (!cursor.hasError) {
104
+ return result;
92
105
  }
93
- this.node = null;
94
- return true;
106
+
107
+ cursor.resolveError();
108
+ }
109
+
110
+ return null
111
+ }
112
+
113
+ getTokens(): string[] {
114
+ const tokens: string[] = [];
115
+
116
+ for (const child of this._children) {
117
+ tokens.push(...child.getTokens());
95
118
  }
119
+
120
+ return tokens;
96
121
  }
97
122
 
98
- private processResult(node: Node) {
99
- const cursor = this.safelyGetCursor();
123
+ getTokensAfter(_childReference: Pattern): string[] {
124
+ if (this._parent === null) {
125
+ return [];
126
+ }
100
127
 
101
- this.node = new Node(
102
- "or",
103
- this.name,
104
- node.startIndex,
105
- node.endIndex,
106
- [node],
107
- node.value
108
- );
128
+ return this._parent.getTokensAfter(this);
129
+ }
130
+
131
+ getNextTokens(): string[] {
132
+ if (this._parent == null) {
133
+ return []
134
+ }
109
135
 
110
- cursor.index = this.node.endIndex;
111
- cursor.addMatch(this, this.node);
136
+ return this._parent.getTokensAfter(this);
112
137
  }
113
138
 
114
- clone(name?: string, isOptional?: boolean) {
115
- if (name == null) {
116
- name = this.name;
139
+ getPatternsAfter(_childReference: Pattern): Pattern[] {
140
+ if (this._parent === null) {
141
+ return [];
117
142
  }
118
143
 
119
- if (isOptional == null) {
120
- isOptional = this._isOptional;
144
+ return this._parent.getPatternsAfter(this)
145
+ }
146
+
147
+ getNextPatterns(): Pattern[] {
148
+ if (this.parent == null) {
149
+ return [];
121
150
  }
122
151
 
123
- return new Or(name, this._children, isOptional);
152
+ return this.parent.getPatternsAfter(this)
153
+ }
154
+
155
+ findPattern(predicate: (p: Pattern) => boolean): Pattern | null {
156
+ return findPattern(this, predicate);
124
157
  }
125
158
 
126
- getTokens() {
127
- return this._children.reduce<string[]>(
128
- (acc, c) => acc.concat(c.getTokens()),
129
- []
130
- );
159
+ clone(name = this._name, isOptional = this._isOptional): Pattern {
160
+ const or = new Or(name, this._children, isOptional);
161
+ return or;
131
162
  }
132
163
  }
@@ -1,14 +1,10 @@
1
- import Pattern from "./Pattern";
1
+ import { Pattern } from "./Pattern";
2
2
 
3
- export default class ParseError {
4
- public message: string;
5
- public name: string;
3
+ export class ParseError {
6
4
  public index: number;
7
5
  public pattern: Pattern;
8
6
 
9
- constructor(message: string, index: number, pattern: Pattern) {
10
- this.name = "ParseError";
11
- this.message = message;
7
+ constructor(index: number, pattern: Pattern) {
12
8
  this.index = index;
13
9
  this.pattern = pattern;
14
10
  }
@@ -0,0 +1,7 @@
1
+ import { Node } from "../ast/Node";
2
+ import { Cursor } from "./Cursor";
3
+
4
+ export interface ParseResult {
5
+ ast: Node | null;
6
+ cursor: Cursor;
7
+ }
@@ -1,151 +1,22 @@
1
- import Cursor from "../Cursor";
2
- import Node from "../ast/Node";
3
-
4
- export default abstract class Pattern {
5
- protected _type: string;
6
- protected _name: string;
7
- protected _children: Pattern[];
8
- protected _parent: Pattern | null;
9
- protected _isOptional = false;
10
-
11
- get isOptional() {
12
- return this._isOptional;
13
- }
14
-
15
- constructor(
16
- type: string,
17
- name: string,
18
- children: Pattern[] = [],
19
- isOptional = false
20
- ) {
21
- this._type = type;
22
- this._name = name;
23
- this._children = [];
24
- this._parent = null;
25
- this._isOptional = isOptional;
26
- this.children = children;
27
- }
28
-
29
- abstract parse(cursor: Cursor): Node | null;
30
-
31
- exec(text: string) {
32
- const cursor = new Cursor(text);
33
- const node = this.parse(cursor);
34
-
35
- if (cursor.didSuccessfullyParse()) {
36
- return node;
37
- } else {
38
- return null;
39
- }
40
- }
41
-
42
- test(text: string) {
43
- return this.exec(text) != null;
44
- }
45
-
46
- get name() {
47
- return this._name;
48
- }
49
-
50
- get type() {
51
- return this._type;
52
- }
53
-
54
- get parent() {
55
- return this._parent;
56
- }
57
-
58
- set parent(value: Pattern | null) {
59
- this._parent = value;
60
- }
61
-
62
- get children() {
63
- return this._children;
64
- }
65
-
66
- set children(value) {
67
- this._children = value;
68
- this.cloneChildren();
69
- this.assignAsParent();
70
- }
71
-
72
- abstract clone(name?: string): Pattern;
73
- abstract getTokens(): string[];
74
-
75
- getTokenValue(): string | null {
76
- return null;
77
- }
78
-
79
- getNextTokens(): string[] {
80
- const parent = this._parent;
81
-
82
- if (parent != null) {
83
- const siblings = parent.children;
84
- const index = siblings.findIndex((c) => c === this);
85
- const nextSibling = siblings[index + 1];
86
-
87
- // I don't like this, so I think we need to rethink this.
88
- if (parent.type.indexOf("repeat") === 0) {
89
- const tokens = parent.getNextTokens();
90
- if (index === 0 && siblings.length > 1) {
91
- return nextSibling.getTokens().concat(tokens);
92
- } else if (index === 1) {
93
- return siblings[0].getTokens();
94
- } else {
95
- return this.getTokens().concat(tokens);
96
- }
97
- }
98
-
99
- // Another thing I don't like.
100
- if (
101
- this._parent?.type?.indexOf("and") === 0 &&
102
- nextSibling != null &&
103
- nextSibling.isOptional
104
- ) {
105
- let tokens: string[] = [];
106
-
107
- for (let x = index + 1; x < siblings.length; x++) {
108
- const child = siblings[x];
109
-
110
- if (child.isOptional) {
111
- tokens = tokens.concat(child.getTokens());
112
- } else {
113
- tokens = tokens.concat(child.getTokens());
114
- break;
115
- }
116
-
117
- if (x === siblings.length - 1) {
118
- tokens = tokens.concat(this._parent.getNextTokens());
119
- }
120
- }
121
-
122
- return tokens;
123
- }
124
-
125
- // If you are an or you have already qualified.
126
- if (parent.type.indexOf("or") === 0) {
127
- return parent.getNextTokens();
128
- }
129
-
130
- if (nextSibling != null) {
131
- return nextSibling.getTokens();
132
- } else {
133
- return parent.getNextTokens();
134
- }
135
- }
136
-
137
- return [];
138
- }
139
-
140
- private cloneChildren() {
141
- this._children = this._children.map((pattern) => {
142
- return pattern.clone();
143
- });
144
-
145
- Object.freeze(this._children);
146
- }
147
-
148
- private assignAsParent() {
149
- this._children.forEach((child) => (child.parent = this));
150
- }
1
+ import { Cursor } from "./Cursor";
2
+ import { Node } from "../ast/Node";
3
+ import { ParseResult } from "./ParseResult"
4
+
5
+ export interface Pattern {
6
+ type: string;
7
+ name: string;
8
+ parent: Pattern | null;
9
+ children: Pattern[];
10
+ isOptional: boolean;
11
+
12
+ parse(cursor: Cursor): Node | null;
13
+ exec(text: string): ParseResult;
14
+ test(text: string): boolean;
15
+ clone(name?: string, isOptional?: boolean): Pattern;
16
+ getTokens(): string[];
17
+ getTokensAfter(childReference: Pattern): string[];
18
+ getPatternsAfter(childReference: Pattern): Pattern[];
19
+ getNextPatterns(): Pattern[];
20
+ getNextTokens(): string[];
21
+ findPattern(predicate: (p: Pattern) => boolean): Pattern | null;
151
22
  }
@@ -0,0 +1,193 @@
1
+ import { Node } from "../ast/Node";
2
+ import { And } from "./And";
3
+ import { Cursor } from "./Cursor";
4
+ import { findPattern } from "./findPattern";
5
+ import { Literal } from "./Literal";
6
+ import { Or } from "./Or";
7
+ import { Pattern } from "./Pattern";
8
+ import { Reference } from "./Reference";
9
+ import { Regex } from "./Regex";
10
+ import { Repeat } from "./Repeat";
11
+
12
+ function createValuePattern() {
13
+ const number = new Regex("number", "\\d+");
14
+ number.setTokens(["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]);
15
+
16
+ const openBracket = new Literal("open-bracket", "[");
17
+ const closeBracket = new Literal("close-bracket", "]");
18
+ const divider = new Regex("divider", "\\s*,\\s+");
19
+ divider.setTokens([", "]);
20
+
21
+ const valueRef = new Reference("value");
22
+ const values = new Repeat("values", valueRef, divider);
23
+ const array = new And("array", [openBracket, values, closeBracket]);
24
+ const value = new Or("value", [number, array]);
25
+
26
+ return value;
27
+ }
28
+
29
+ describe("Reference", () => {
30
+ test("One Deep Successful Parse", () => {
31
+ const value = createValuePattern();
32
+ const cursor = new Cursor("[1, 2]");
33
+ const result = value.parse(cursor);
34
+
35
+ const expected = new Node("and", "array", 0, 5, [
36
+ new Node("literal", "open-bracket", 0, 0, [], "["),
37
+ new Node("repeat", "values", 1, 4, [
38
+ new Node("regex", "number", 1, 1, [], "1"),
39
+ new Node("regex", "divider", 2, 3, [], ", "),
40
+ new Node("regex", "number", 4, 4, [], "2")
41
+ ]),
42
+ new Node("literal", "close-bracket", 5, 5, [], "]"),
43
+ ])
44
+
45
+ expect(result).toEqual(expected);
46
+ });
47
+
48
+ test("No Reference Pattern", () => {
49
+ const ref = new Reference("bad-reference");
50
+
51
+ expect(() => {
52
+ ref.parse(new Cursor("text"))
53
+ }).toThrowError()
54
+ });
55
+
56
+ test("Get Tokens", () => {
57
+ const value = createValuePattern();
58
+ const ref = findPattern(value, (p) => p.type === "reference");
59
+ const tokens = ref?.getTokens();
60
+ const expected = [
61
+ "1",
62
+ "2",
63
+ "3",
64
+ "4",
65
+ "5",
66
+ "6",
67
+ "7",
68
+ "8",
69
+ "9",
70
+ "0",
71
+ "["
72
+ ];
73
+
74
+ expect(tokens).toEqual(expected);
75
+ });
76
+
77
+ test("Get Tokens After With No Parent", () => {
78
+ const ref = new Reference("bad-reference");
79
+ const tokens = ref.getTokensAfter(new Literal("bogus", "bogus"))
80
+
81
+ expect(tokens).toEqual([]);
82
+ });
83
+
84
+ test("Properties", () => {
85
+ const ref = new Reference("ref");
86
+
87
+ expect(ref.type).toBe("reference");
88
+ expect(ref.name).toBe("ref");
89
+ expect(ref.isOptional).toBeFalsy();
90
+ expect(ref.parent).toBe(null)
91
+ expect(ref.children).toEqual([])
92
+ });
93
+
94
+ test("Exec", () => {
95
+ const value = createValuePattern();
96
+ const reference = findPattern(value, p => p.type === "reference") as Reference
97
+ const { ast: result } = reference.exec("B");
98
+ expect(result).toBeNull()
99
+ });
100
+
101
+ test("Test With Match", () => {
102
+ const value = createValuePattern();
103
+ const reference = findPattern(value, p => p.type === "reference") as Reference
104
+ const result = reference.test("[1]");
105
+ expect(result).toBeTruthy()
106
+ });
107
+
108
+ test("Test No Match", () => {
109
+ const value = createValuePattern();
110
+ const reference = findPattern(value, p => p.type === "reference") as Reference
111
+ const result = reference.test("B");
112
+ expect(result).toBeFalsy()
113
+ });
114
+
115
+ test("Find Pattern", () => {
116
+ const value = createValuePattern();
117
+ const reference = value.findPattern(p => p.type === "reference") as Pattern;
118
+
119
+ const pattern = reference?.findPattern(p => p.name === "Nada");
120
+
121
+ expect(pattern).toBe(null);
122
+ });
123
+
124
+
125
+ test("Get Next Tokens", () => {
126
+ const value = createValuePattern();
127
+ const reference = value.findPattern(p => p.type === "reference") as Pattern;
128
+ const tokens = reference.getNextTokens();
129
+
130
+ expect(tokens).toEqual([", ", "]"]);
131
+ });
132
+
133
+ test("Get Next Tokens With Null Parent", () => {
134
+ const reference = new Reference("ref-name");
135
+ const tokens = reference.getNextTokens();
136
+
137
+ expect(tokens).toEqual([])
138
+ });
139
+
140
+ test("Get Tokens After", () => {
141
+ const value = createValuePattern();
142
+ const reference = value.findPattern(p => p.type === "reference") as Pattern;
143
+ const tokens = reference.getTokensAfter(new Literal("bogus", "Bogus"));
144
+
145
+ expect(tokens).toEqual([", ", "]"]);
146
+ });
147
+
148
+ test("Get Tokens After With Null Parent", () => {
149
+ const reference = new Reference("ref-name");
150
+ const tokens = reference.getTokensAfter(new Literal("bogus", "Bogus"));
151
+
152
+ expect(tokens).toEqual([])
153
+ });
154
+
155
+ test("Get Patterns After", () => {
156
+ const value = createValuePattern();
157
+ const reference = value.findPattern(p => p.type === "reference") as Pattern;
158
+ const patterns = reference.getPatternsAfter(new Literal("bogus", "Bogus"));
159
+
160
+ expect(patterns.length).toEqual(2);
161
+ expect(patterns[0].type).toEqual("regex");
162
+ expect(patterns[0].name).toEqual("divider");
163
+ expect(patterns[1].type).toEqual("literal");
164
+ expect(patterns[1].name).toEqual("close-bracket");
165
+ });
166
+
167
+ test("Get Patterns After With Null Parent", () => {
168
+ const reference = new Reference("ref-name");
169
+ const patterns = reference.getPatternsAfter(new Literal("bogus", "Bogus"));
170
+
171
+ expect(patterns).toEqual([])
172
+ });
173
+
174
+ test("Get Next Patterns", () => {
175
+ const value = createValuePattern();
176
+ const reference = value.findPattern(p => p.type === "reference") as Pattern;
177
+ const patterns = reference.getNextPatterns();
178
+
179
+ expect(patterns.length).toEqual(2);
180
+ expect(patterns[0].type).toEqual("regex");
181
+ expect(patterns[0].name).toEqual("divider");
182
+ expect(patterns[1].type).toEqual("literal");
183
+ expect(patterns[1].name).toEqual("close-bracket");
184
+ });
185
+
186
+ test("Get Next Patterns With Null Parent", () => {
187
+ const reference = new Reference("ref-name");
188
+ const patterns = reference.getNextPatterns();
189
+
190
+ expect(patterns).toEqual([])
191
+ });
192
+
193
+ });