clarity-pattern-parser 3.0.16 → 4.0.1

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 (169) hide show
  1. package/README.md +0 -191
  2. package/dist/ast/Node.d.ts +4 -5
  3. package/dist/index.browser.js +476 -731
  4. package/dist/index.browser.js.map +1 -1
  5. package/dist/index.d.ts +10 -18
  6. package/dist/index.esm.js +469 -716
  7. package/dist/index.esm.js.map +1 -1
  8. package/dist/index.js +476 -731
  9. package/dist/index.js.map +1 -1
  10. package/dist/patterns/And.d.ts +24 -0
  11. package/dist/patterns/Literal.d.ts +19 -0
  12. package/dist/patterns/LookAhead.d.ts +8 -0
  13. package/dist/patterns/Not.d.ts +11 -0
  14. package/dist/patterns/Or.d.ts +22 -0
  15. package/dist/patterns/Pattern.d.ts +6 -7
  16. package/dist/patterns/{RecursivePattern.d.ts → Recursive.d.ts} +4 -4
  17. package/dist/patterns/Reference.d.ts +14 -0
  18. package/dist/patterns/Regex.d.ts +21 -0
  19. package/dist/patterns/Repeat.d.ts +20 -0
  20. package/package.json +1 -1
  21. package/src/CursorHistory.ts +1 -1
  22. package/src/TextSuggester.ts +1 -1
  23. package/src/ast/Node.ts +20 -17
  24. package/src/ast/Visitor.ts +14 -18
  25. package/src/index.ts +17 -33
  26. package/src/patterns/And.ts +178 -0
  27. package/src/patterns/Literal.ts +91 -0
  28. package/src/patterns/Not.ts +50 -0
  29. package/src/patterns/Or.ts +132 -0
  30. package/src/patterns/Pattern.ts +31 -47
  31. package/src/patterns/Recursive.ts +92 -0
  32. package/src/patterns/{ReferencePattern.ts → Reference.ts} +32 -28
  33. package/src/patterns/Regex.ts +123 -0
  34. package/src/patterns/Repeat.ts +155 -0
  35. package/src/tests/{AndValue.test.ts → And.test.ts} +31 -41
  36. package/src/tests/CursorHistory.test.ts +6 -6
  37. package/src/tests/Cusor.test.ts +7 -10
  38. package/src/tests/Literal.test.ts +3 -5
  39. package/src/tests/LookAhead.test.ts +2 -51
  40. package/src/tests/Not.test.ts +51 -0
  41. package/src/tests/Or.test.ts +113 -0
  42. package/src/tests/Pattern.test.ts +40 -139
  43. package/src/tests/{RecursivePattern.test.ts → Recursive.test.ts} +10 -8
  44. package/src/tests/Reference.test.ts +16 -0
  45. package/src/tests/{RepeatValue.test.ts → Repeat.test.ts} +10 -42
  46. package/src/tests/TextSuggester.test.ts +30 -28
  47. package/src/tests/{NodeVisitor.test.ts → Visitor.test.ts} +42 -21
  48. package/src/tests/cssPatterns/cssValue.ts +2 -2
  49. package/src/tests/cssPatterns/divider.ts +2 -2
  50. package/src/tests/cssPatterns/hex.ts +2 -2
  51. package/src/tests/cssPatterns/method.ts +7 -9
  52. package/src/tests/cssPatterns/name.ts +2 -2
  53. package/src/tests/cssPatterns/number.ts +2 -2
  54. package/src/tests/cssPatterns/optionalSpaces.ts +1 -2
  55. package/src/tests/cssPatterns/spaces.ts +2 -2
  56. package/src/tests/cssPatterns/unit.ts +3 -3
  57. package/src/tests/cssPatterns/value.ts +2 -2
  58. package/src/tests/cssPatterns/values.ts +2 -2
  59. package/src/tests/htmlPatterns/element.ts +18 -33
  60. package/src/tests/javascriptPatterns/boolean.ts +2 -3
  61. package/src/tests/javascriptPatterns/json.ts +14 -26
  62. package/src/tests/javascriptPatterns/name.ts +3 -20
  63. package/src/tests/javascriptPatterns/number.ts +2 -2
  64. package/src/tests/javascriptPatterns/objectLiteral.ts +9 -16
  65. package/src/tests/javascriptPatterns/string.ts +26 -24
  66. package/src/tests/javascriptPatterns/unit.ts +3 -6
  67. package/src/tests/javascriptPatterns/whitespace.ts +8 -12
  68. package/src/tests/naturalLanguage/filter.ts +16 -33
  69. package/src/tests/patterns/sentence.ts +8 -8
  70. package/dist/Cursor.js +0 -105
  71. package/dist/Cursor.js.map +0 -1
  72. package/dist/CursorHistory.js +0 -104
  73. package/dist/CursorHistory.js.map +0 -1
  74. package/dist/Permutor.d.ts +0 -13
  75. package/dist/Permutor.js +0 -52
  76. package/dist/Permutor.js.map +0 -1
  77. package/dist/TextSuggester.js +0 -244
  78. package/dist/TextSuggester.js.map +0 -1
  79. package/dist/ast/CompositeNode.d.ts +0 -6
  80. package/dist/ast/CompositeNode.js +0 -17
  81. package/dist/ast/CompositeNode.js.map +0 -1
  82. package/dist/ast/Node.js +0 -16
  83. package/dist/ast/Node.js.map +0 -1
  84. package/dist/ast/NodeVisitor.d.ts +0 -31
  85. package/dist/ast/ValueNode.d.ts +0 -6
  86. package/dist/ast/ValueNode.js +0 -14
  87. package/dist/ast/ValueNode.js.map +0 -1
  88. package/dist/ast/Visitor.js +0 -209
  89. package/dist/ast/Visitor.js.map +0 -1
  90. package/dist/patterns/ParseError.js +0 -9
  91. package/dist/patterns/ParseError.js.map +0 -1
  92. package/dist/patterns/Pattern.js +0 -127
  93. package/dist/patterns/Pattern.js.map +0 -1
  94. package/dist/patterns/RecursivePattern.js +0 -65
  95. package/dist/patterns/RecursivePattern.js.map +0 -1
  96. package/dist/patterns/composite/AndComposite.d.ts +0 -22
  97. package/dist/patterns/composite/AndComposite.js +0 -117
  98. package/dist/patterns/composite/AndComposite.js.map +0 -1
  99. package/dist/patterns/composite/CompositePattern.d.ts +0 -4
  100. package/dist/patterns/composite/CompositePattern.js +0 -7
  101. package/dist/patterns/composite/CompositePattern.js.map +0 -1
  102. package/dist/patterns/composite/OptionalComposite.d.ts +0 -10
  103. package/dist/patterns/composite/OptionalComposite.js +0 -29
  104. package/dist/patterns/composite/OptionalComposite.js.map +0 -1
  105. package/dist/patterns/composite/OrComposite.d.ts +0 -16
  106. package/dist/patterns/composite/OrComposite.js +0 -69
  107. package/dist/patterns/composite/OrComposite.js.map +0 -1
  108. package/dist/patterns/composite/RepeatComposite.d.ts +0 -21
  109. package/dist/patterns/composite/RepeatComposite.js +0 -88
  110. package/dist/patterns/composite/RepeatComposite.js.map +0 -1
  111. package/dist/patterns/value/AndValue.d.ts +0 -21
  112. package/dist/patterns/value/AndValue.js +0 -118
  113. package/dist/patterns/value/AndValue.js.map +0 -1
  114. package/dist/patterns/value/AnyOfThese.d.ts +0 -18
  115. package/dist/patterns/value/AnyOfThese.js +0 -59
  116. package/dist/patterns/value/AnyOfThese.js.map +0 -1
  117. package/dist/patterns/value/Literal.d.ts +0 -20
  118. package/dist/patterns/value/Literal.js +0 -63
  119. package/dist/patterns/value/Literal.js.map +0 -1
  120. package/dist/patterns/value/NotValue.d.ts +0 -17
  121. package/dist/patterns/value/NotValue.js +0 -70
  122. package/dist/patterns/value/NotValue.js.map +0 -1
  123. package/dist/patterns/value/OptionalValue.d.ts +0 -9
  124. package/dist/patterns/value/OptionalValue.js +0 -32
  125. package/dist/patterns/value/OptionalValue.js.map +0 -1
  126. package/dist/patterns/value/OrValue.d.ts +0 -19
  127. package/dist/patterns/value/OrValue.js +0 -73
  128. package/dist/patterns/value/OrValue.js.map +0 -1
  129. package/dist/patterns/value/RegexValue.d.ts +0 -19
  130. package/dist/patterns/value/RegexValue.js +0 -69
  131. package/dist/patterns/value/RegexValue.js.map +0 -1
  132. package/dist/patterns/value/RepeatValue.d.ts +0 -19
  133. package/dist/patterns/value/RepeatValue.js +0 -89
  134. package/dist/patterns/value/RepeatValue.js.map +0 -1
  135. package/dist/patterns/value/ValuePattern.d.ts +0 -5
  136. package/dist/patterns/value/ValuePattern.js +0 -7
  137. package/dist/patterns/value/ValuePattern.js.map +0 -1
  138. package/src/Permutor.ts +0 -64
  139. package/src/ast/CompositeNode.ts +0 -26
  140. package/src/ast/ValueNode.ts +0 -28
  141. package/src/patterns/RecursivePattern.ts +0 -86
  142. package/src/patterns/composite/AndComposite.ts +0 -159
  143. package/src/patterns/composite/CompositePattern.ts +0 -7
  144. package/src/patterns/composite/OptionalComposite.ts +0 -37
  145. package/src/patterns/composite/OrComposite.ts +0 -96
  146. package/src/patterns/composite/RepeatComposite.ts +0 -130
  147. package/src/patterns/value/AndValue.ts +0 -152
  148. package/src/patterns/value/AnyOfThese.ts +0 -81
  149. package/src/patterns/value/Literal.ts +0 -92
  150. package/src/patterns/value/NotValue.ts +0 -95
  151. package/src/patterns/value/OptionalValue.ts +0 -39
  152. package/src/patterns/value/OrValue.ts +0 -103
  153. package/src/patterns/value/RegexValue.ts +0 -103
  154. package/src/patterns/value/RepeatValue.ts +0 -131
  155. package/src/patterns/value/ValuePattern.ts +0 -8
  156. package/src/tests/AndComposite.test.ts +0 -102
  157. package/src/tests/AnyOfThese.test.ts +0 -74
  158. package/src/tests/CompositeNode.test.ts +0 -33
  159. package/src/tests/NotValue.test.ts +0 -76
  160. package/src/tests/OptionalValue.test.ts +0 -50
  161. package/src/tests/OrComposite.test.ts +0 -75
  162. package/src/tests/OrValue.test.ts +0 -171
  163. package/src/tests/Permutor.test.ts +0 -30
  164. package/src/tests/ReferencePattern.test.ts +0 -24
  165. package/src/tests/RegexValue.test.ts +0 -22
  166. package/src/tests/RepeatComposite.test.ts +0 -58
  167. package/src/tests/ValueNode.test.ts +0 -24
  168. package/src/tests/javascriptPatterns/varStatement.ts +0 -0
  169. package/src/tests/readmeDemo.test.ts +0 -124
@@ -5,9 +5,9 @@ export default abstract class Pattern {
5
5
  protected _name: string;
6
6
  protected _children: Pattern[];
7
7
  protected _parent: Pattern | null;
8
- isSequence: boolean;
9
- constructor(type: string | undefined, name: string, children?: Pattern[]);
10
- private _assertName;
8
+ protected _isOptional: boolean;
9
+ get isOptional(): boolean;
10
+ constructor(type: string, name: string, children?: Pattern[], isOptional?: boolean);
11
11
  abstract parse(cursor: Cursor): Node | null;
12
12
  exec(text: string): Node | null;
13
13
  test(text: string): boolean;
@@ -17,11 +17,10 @@ export default abstract class Pattern {
17
17
  set parent(value: Pattern | null);
18
18
  get children(): Pattern[];
19
19
  set children(value: Pattern[]);
20
- protected _assertChildren(): void;
21
- private _cloneChildren;
22
- private _assignAsParent;
23
20
  abstract clone(name?: string): Pattern;
24
21
  abstract getTokens(): string[];
25
- getNextTokens(): string[];
26
22
  getTokenValue(): string | null;
23
+ getNextTokens(): string[];
24
+ private cloneChildren;
25
+ private assignAsParent;
27
26
  }
@@ -1,13 +1,13 @@
1
1
  import Pattern from "./Pattern";
2
2
  import Cursor from "../Cursor";
3
- export default class RecursivePattern extends Pattern {
3
+ export default class Recursive extends Pattern {
4
4
  isRecursing: boolean;
5
5
  pattern: Pattern | null;
6
- constructor(name: string);
6
+ constructor(name: string, isOptional?: boolean);
7
7
  getPattern(): Pattern | null;
8
- _climb(pattern: Pattern | null, isMatch: (pattern: Pattern | null) => boolean): Pattern | null;
8
+ private climb;
9
9
  parse(cursor: Cursor): import("..").Node | null;
10
- clone(name?: string): Pattern;
10
+ clone(name?: string, isOptional?: boolean): Recursive;
11
11
  getTokenValue(): string | null;
12
12
  getTokens(): string[];
13
13
  }
@@ -0,0 +1,14 @@
1
+ import Pattern from "./Pattern";
2
+ import Cursor from "../Cursor";
3
+ export default class Reference extends Pattern {
4
+ private isRecursing;
5
+ constructor(name: string, isOptional?: boolean);
6
+ private getRoot;
7
+ private findPattern;
8
+ private walkTheTree;
9
+ parse(cursor: Cursor): import("..").Node | null;
10
+ clone(name?: string, isOptional?: boolean): Reference;
11
+ getTokenValue(): string | null;
12
+ private safelyGetPattern;
13
+ getTokens(): string[];
14
+ }
@@ -0,0 +1,21 @@
1
+ import Node from "../ast/Node";
2
+ import Pattern from "./Pattern";
3
+ import Cursor from "../Cursor";
4
+ export default class Regex extends Pattern {
5
+ private regexString;
6
+ private regex;
7
+ private node;
8
+ private cursor;
9
+ private substring;
10
+ constructor(name: string, regex: string, isOptional?: boolean);
11
+ private assertArguments;
12
+ parse(cursor: Cursor): Node | null;
13
+ private resetState;
14
+ private tryToParse;
15
+ private processResult;
16
+ private processError;
17
+ private safelyGetCursor;
18
+ clone(name?: string, isOptional?: boolean): Regex;
19
+ getTokenValue(): string;
20
+ getTokens(): string[];
21
+ }
@@ -0,0 +1,20 @@
1
+ import Pattern from "./Pattern";
2
+ import Node from "../ast/Node";
3
+ import Cursor from "../Cursor";
4
+ export default class Repeat extends Pattern {
5
+ _pattern: Pattern;
6
+ _divider: Pattern;
7
+ nodes: Node[];
8
+ cursor: Cursor;
9
+ mark: number;
10
+ node: Node | null;
11
+ constructor(name: string, pattern: Pattern, divider?: Pattern, isOptional?: boolean);
12
+ private assertArguments;
13
+ private _reset;
14
+ parse(cursor: Cursor): Node | null;
15
+ private tryToParse;
16
+ private processResult;
17
+ private safelyGetCursor;
18
+ clone(name?: string, isOptional?: boolean): Repeat;
19
+ getTokens(): string[];
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clarity-pattern-parser",
3
- "version": "3.0.16",
3
+ "version": "4.0.1",
4
4
  "description": "Parsing Library for Typescript and Javascript.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.esm.js",
@@ -139,7 +139,7 @@ export default class CursorHistory {
139
139
  return cleanedStack;
140
140
  }
141
141
 
142
- getLastParseStack() {
142
+ getLastParseStack(): Node[] {
143
143
  const stacks = this.getAllParseStacks();
144
144
  return stacks[stacks.length - 1] || [];
145
145
  }
@@ -187,7 +187,7 @@ export default class TextSuggester {
187
187
  let options = this.rootPattern?.getTokens();
188
188
 
189
189
  options = options?.filter((option: any) => {
190
- return option.indexOf(this.text) > -1;
190
+ return option.indexOf(this.text) === 0;
191
191
  });
192
192
 
193
193
  if (options?.length === 0) {
package/src/ast/Node.ts CHANGED
@@ -1,36 +1,39 @@
1
- export default abstract class Node {
1
+ export default class Node {
2
2
  public type: string;
3
3
  public name: string;
4
4
  public startIndex: number;
5
5
  public endIndex: number;
6
- public isComposite: boolean;
7
- public children: Node[] = [];
8
- public value: string = "";
6
+ public children: Node[];
7
+ public value: string;
9
8
 
10
9
  constructor(
11
10
  type: string,
12
11
  name: string,
13
12
  startIndex: number,
14
13
  endIndex: number,
15
- isComposite = false
14
+ children: Node[] = [],
15
+ value: string = ""
16
16
  ) {
17
17
  this.type = type;
18
18
  this.name = name;
19
19
  this.startIndex = startIndex;
20
20
  this.endIndex = endIndex;
21
- this.isComposite = isComposite;
22
-
23
- if (
24
- typeof this.startIndex !== "number" ||
25
- typeof this.endIndex !== "number"
26
- ) {
27
- throw new Error(
28
- "Invalid Arguments: startIndex and endIndex need to be number."
29
- );
30
- }
21
+ this.children = children;
22
+ this.value = value;
31
23
  }
32
24
 
33
- abstract clone(): Node;
25
+ clone(): Node {
26
+ return new Node(
27
+ this.type,
28
+ this.name,
29
+ this.startIndex,
30
+ this.endIndex,
31
+ this.children.map((c) => c.clone()),
32
+ this.value
33
+ );
34
+ }
34
35
 
35
- abstract toString(): string;
36
+ toString() {
37
+ return this.value;
38
+ }
36
39
  }
@@ -11,11 +11,11 @@ export default class Visitor {
11
11
 
12
12
  flatten() {
13
13
  this.selectedNodes.forEach((node) => {
14
- if (node.isComposite) {
14
+ if (node.children.length > 0) {
15
15
  const children: Node[] = [];
16
16
 
17
17
  Visitor.walkUp(node, (descendant: Node) => {
18
- if (!descendant.isComposite) {
18
+ if (descendant.children.length === 0) {
19
19
  children.push(descendant);
20
20
  }
21
21
  });
@@ -38,14 +38,12 @@ export default class Visitor {
38
38
 
39
39
  private recursiveRemove(node: Node) {
40
40
  const nodesToRemove = this.selectedNodes;
41
- if (node.isComposite && Array.isArray(node.children)) {
42
- for (let x = 0; x < node.children.length; x++) {
43
- if (nodesToRemove.indexOf(node.children[x]) > -1) {
44
- node.children.splice(x, 1);
45
- x--;
46
- } else {
47
- this.recursiveRemove(node.children[x]);
48
- }
41
+ for (let x = 0; x < node.children.length; x++) {
42
+ if (nodesToRemove.indexOf(node.children[x]) > -1) {
43
+ node.children.splice(x, 1);
44
+ x--;
45
+ } else {
46
+ this.recursiveRemove(node.children[x]);
49
47
  }
50
48
  }
51
49
  }
@@ -136,12 +134,10 @@ export default class Visitor {
136
134
  }
137
135
 
138
136
  private recursiveTransform(node: Node, callback: (node: Node) => Node) {
139
- if (node.isComposite && Array.isArray(node.children)) {
140
- const length = node.children.length;
137
+ const length = node.children.length;
141
138
 
142
- for (let x = 0; x < length; x++) {
143
- node.children[x] = this.recursiveTransform(node.children[x], callback);
144
- }
139
+ for (let x = 0; x < length; x++) {
140
+ node.children[x] = this.recursiveTransform(node.children[x], callback);
145
141
  }
146
142
 
147
143
  return callback(node);
@@ -168,7 +164,7 @@ export default class Visitor {
168
164
  const node = this.root;
169
165
  const selectedNodes: Node[] = [];
170
166
 
171
- if (node.isComposite) {
167
+ if (node.children.length > 0) {
172
168
  Visitor.walkDown(node, (descendant: Node) => {
173
169
  if (callback(descendant)) {
174
170
  selectedNodes.push(descendant);
@@ -245,7 +241,7 @@ export default class Visitor {
245
241
  ) {
246
242
  ancestors.push(node);
247
243
 
248
- if (node.isComposite && Array.isArray(node.children)) {
244
+ if (node.children.length > 0) {
249
245
  const children = node.children.slice();
250
246
  children.forEach((c) => this.walkUp(c, callback, ancestors));
251
247
  }
@@ -264,7 +260,7 @@ export default class Visitor {
264
260
  callback(node, ancestors);
265
261
  ancestors.push(node);
266
262
 
267
- if (node.isComposite && Array.isArray(node.children)) {
263
+ if (node.children.length > 0) {
268
264
  const children = node.children.slice();
269
265
  children.forEach((c) => this.walkDown(c, callback, ancestors));
270
266
  }
package/src/index.ts CHANGED
@@ -1,49 +1,33 @@
1
1
  import Node from "./ast/Node";
2
- import CompositeNode from "./ast/CompositeNode";
3
- import ValueNode from "./ast/ValueNode";
4
2
  import Cursor from "./Cursor";
5
- import RegexValue from "./patterns/value/RegexValue";
6
- import AndValue from "./patterns/value/AndValue";
7
- import AnyOfThese from "./patterns/value/AnyOfThese";
8
- import Literal from "./patterns/value/Literal";
9
- import NotValue from "./patterns/value/NotValue";
10
- import OptionalValue from "./patterns/value/OptionalValue";
11
- import OrValue from "./patterns/value/OrValue";
12
- import RepeatValue from "./patterns/value/RepeatValue";
13
- import ValuePattern from "./patterns/value/ValuePattern";
14
- import AndComposite from "./patterns/composite/AndComposite";
15
- import CompositePattern from "./patterns/composite/CompositePattern";
16
- import OptionalComposite from "./patterns/composite/OptionalComposite";
17
- import OrComposite from "./patterns/composite/OrComposite";
18
- import RepeatComposite from "./patterns/composite/RepeatComposite";
3
+ import Regex from "./patterns/Regex";
4
+ import And from "./patterns/And";
5
+ import Literal from "./patterns/Literal";
6
+ import LookAhead from "./patterns/LookAhead";
7
+ import Not from "./patterns/Not";
8
+ import Or from "./patterns/Or";
9
+ import Repeat from "./patterns/Repeat";
19
10
  import ParseError from "./patterns/ParseError";
20
11
  import Pattern from "./patterns/Pattern";
21
- import RecursivePattern from "./patterns/RecursivePattern";
12
+ import Recursive from "./patterns/Recursive";
13
+ import Reference from "./patterns/Reference";
22
14
  import TextSuggester from "./TextSuggester";
23
15
  import Visitor from "./ast/Visitor";
24
16
 
25
17
  export {
26
18
  Node,
27
- CompositeNode,
28
- ValueNode,
29
19
  Cursor,
30
- RegexValue,
31
- AndValue,
32
- AnyOfThese,
20
+ Regex,
21
+ And,
33
22
  Literal,
34
- NotValue,
35
- OptionalValue,
36
- OrValue,
37
- RepeatValue,
38
- ValuePattern,
39
- AndComposite,
40
- CompositePattern,
41
- OptionalComposite,
42
- OrComposite,
43
- RepeatComposite,
23
+ Not,
24
+ Or,
25
+ Repeat,
44
26
  ParseError,
45
27
  Pattern,
46
- RecursivePattern,
28
+ Recursive,
29
+ Reference,
47
30
  TextSuggester,
48
31
  Visitor,
32
+ LookAhead,
49
33
  };
@@ -0,0 +1,178 @@
1
+ import ParseError from "../patterns/ParseError";
2
+ import Cursor from "../Cursor";
3
+ import Pattern from "./Pattern";
4
+ import Node from "../ast/Node";
5
+
6
+ export default class And extends Pattern {
7
+ public onPatternIndex: number = 0;
8
+ public nodes: (Node | null)[] = [];
9
+ public node: Node | null = null;
10
+ public cursor: Cursor | null = null;
11
+ public mark: number = 0;
12
+
13
+ constructor(name: string, patterns: Pattern[], isOptional = false) {
14
+ super("and", name, patterns, isOptional);
15
+ }
16
+
17
+ parse(cursor: Cursor) {
18
+ this.resetState(cursor);
19
+ this.tryToParse();
20
+
21
+ return this.node;
22
+ }
23
+
24
+ clone(name?: string, isOptional?: boolean) {
25
+ if (name == null) {
26
+ name = this.name;
27
+ }
28
+
29
+ if (isOptional == null){
30
+ isOptional = this._isOptional;
31
+ }
32
+
33
+ return new And(name, this._children, isOptional);
34
+ }
35
+
36
+ getTokens() {
37
+ let tokens: string[] = [];
38
+
39
+ for (let x = 0; x < this._children.length; x++) {
40
+ const child = this._children[x];
41
+
42
+ if (child.isOptional) {
43
+ tokens = tokens.concat(child.getTokens());
44
+ } else {
45
+ tokens = tokens.concat(child.getTokens());
46
+ break;
47
+ }
48
+ }
49
+
50
+ return tokens;
51
+ }
52
+
53
+ private resetState(cursor: Cursor) {
54
+ this.onPatternIndex = 0;
55
+ this.nodes = [];
56
+ this.node = null;
57
+ this.cursor = cursor;
58
+ this.mark = this.cursor.mark();
59
+ }
60
+
61
+ private tryToParse() {
62
+ const cursor = this.safelyGetCursor();
63
+
64
+ while (true) {
65
+ const pattern = this._children[this.onPatternIndex];
66
+ const node = pattern.parse(cursor);
67
+
68
+ if (cursor.hasUnresolvedError()) {
69
+ this.processError();
70
+ break;
71
+ } else {
72
+ this.nodes.push(node);
73
+ }
74
+
75
+ if (!this.shouldProceed()) {
76
+ this.processResult();
77
+ break;
78
+ }
79
+ }
80
+ }
81
+
82
+ private safelyGetCursor() {
83
+ const cursor = this.cursor;
84
+
85
+ if (cursor == null) {
86
+ throw new Error("Couldn't find cursor.");
87
+ }
88
+ return cursor;
89
+ }
90
+
91
+ private processResult() {
92
+ const cursor = this.safelyGetCursor();
93
+
94
+ if (cursor.hasUnresolvedError()) {
95
+ this.processError();
96
+ } else {
97
+ this.processSuccess();
98
+ }
99
+ }
100
+
101
+ private processError() {
102
+ const cursor = this.safelyGetCursor();
103
+
104
+ if (this.isOptional) {
105
+ cursor.moveToMark(this.mark);
106
+ cursor.resolveError();
107
+ }
108
+ this.node = null;
109
+ }
110
+
111
+ private shouldProceed() {
112
+ const cursor = this.safelyGetCursor();
113
+
114
+ if (this.hasMorePatterns()) {
115
+ const lastNode = this.nodes[this.nodes.length - 1];
116
+ const wasOptional = lastNode == null;
117
+
118
+ if (cursor.hasNext()) {
119
+ if (!wasOptional) {
120
+ cursor.next();
121
+ }
122
+
123
+ this.onPatternIndex++;
124
+ return true;
125
+ } else if (wasOptional) {
126
+ this.onPatternIndex++;
127
+ return true;
128
+ }
129
+
130
+ this.assertRestOfPatternsAreOptional();
131
+ return false;
132
+ } else {
133
+ return false;
134
+ }
135
+ }
136
+
137
+ private hasMorePatterns() {
138
+ return this.onPatternIndex + 1 < this._children.length;
139
+ }
140
+
141
+ private assertRestOfPatternsAreOptional() {
142
+ const cursor = this.safelyGetCursor();
143
+ const areTheRestOptional = this.areTheRemainingPatternsOptional();
144
+
145
+ if (!areTheRestOptional) {
146
+ const parseError = new ParseError(
147
+ `Could not match ${this.name} before string ran out.`,
148
+ this.onPatternIndex,
149
+ this
150
+ );
151
+
152
+ cursor.throwError(parseError);
153
+ }
154
+ }
155
+
156
+ private areTheRemainingPatternsOptional() {
157
+ return this.children
158
+ .slice(this.onPatternIndex + 1)
159
+ .map((p) => p.isOptional)
160
+ .every((r) => r);
161
+ }
162
+
163
+ private processSuccess() {
164
+ const cursor = this.safelyGetCursor();
165
+ const nodes = this.nodes.filter((node) => node != null) as Node[];
166
+ this.nodes = nodes;
167
+
168
+ const lastNode = nodes[this.nodes.length - 1];
169
+ const startIndex = this.mark;
170
+ const endIndex = lastNode.endIndex;
171
+ const value = nodes.map((node) => node.value).join("");
172
+
173
+ this.node = new Node("and", this.name, startIndex, endIndex, nodes, value);
174
+
175
+ cursor.index = this.node.endIndex;
176
+ cursor.addMatch(this, this.node);
177
+ }
178
+ }
@@ -0,0 +1,91 @@
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 Literal extends Pattern {
7
+ public literal: string;
8
+ public node: Node | null = null;
9
+ public cursor!: Cursor;
10
+ public mark: number = 0;
11
+ public substring: string = "";
12
+
13
+ constructor(name: string, literal: string, isOptional = false) {
14
+ super("literal", name, [], isOptional);
15
+ this.literal = literal;
16
+ this.assertArguments();
17
+ }
18
+
19
+ parse(cursor: Cursor) {
20
+ this.resetState(cursor);
21
+ this.tryToParse();
22
+
23
+ return this.node;
24
+ }
25
+
26
+ clone(name?: string, isOptional?: boolean) {
27
+ if (name == null) {
28
+ name = this.name;
29
+ }
30
+
31
+ if (isOptional == null) {
32
+ isOptional = this._isOptional;
33
+ }
34
+
35
+ return new Literal(name, this.literal, isOptional);
36
+ }
37
+
38
+ getTokens() {
39
+ return [this.literal];
40
+ }
41
+
42
+ private assertArguments() {
43
+ if (this.literal.length < 1) {
44
+ throw new Error(
45
+ "Invalid Arguments: The `literal` argument needs to be at least one character long."
46
+ );
47
+ }
48
+ }
49
+
50
+ private resetState(cursor: Cursor) {
51
+ this.cursor = cursor;
52
+ this.mark = this.cursor.mark();
53
+ this.substring = this.cursor.text.substring(
54
+ this.mark,
55
+ this.mark + this.literal.length
56
+ );
57
+ this.node = null;
58
+ }
59
+
60
+ private tryToParse() {
61
+ if (this.substring === this.literal) {
62
+ this.processResult();
63
+ } else {
64
+ this.processError();
65
+ }
66
+ }
67
+
68
+ private processError() {
69
+ this.node = null;
70
+
71
+ if (!this._isOptional) {
72
+ const message = `ParseError: Expected '${this.literal}' but found '${this.substring}'.`;
73
+ const parseError = new ParseError(message, this.cursor.getIndex(), this);
74
+ this.cursor.throwError(parseError);
75
+ }
76
+ }
77
+
78
+ private processResult() {
79
+ this.node = new Node(
80
+ "literal",
81
+ this.name,
82
+ this.mark,
83
+ this.mark + this.literal.length - 1,
84
+ [],
85
+ this.substring
86
+ );
87
+
88
+ this.cursor.index = this.node.endIndex;
89
+ this.cursor.addMatch(this, this.node);
90
+ }
91
+ }
@@ -0,0 +1,50 @@
1
+ import Pattern from "./Pattern";
2
+ import ParseError from "./ParseError";
3
+ import Cursor from "../Cursor";
4
+
5
+ export default class Not extends Pattern {
6
+ public cursor!: Cursor;
7
+ public mark: number = 0;
8
+
9
+ constructor(pattern: Pattern) {
10
+ super("not", `not-${pattern.name}`, [pattern]);
11
+ this._isOptional = true;
12
+ }
13
+
14
+ parse(cursor: Cursor) {
15
+ this.cursor = cursor;
16
+ this.mark = cursor.mark();
17
+ this.tryToParse();
18
+ return null;
19
+ }
20
+
21
+ private tryToParse() {
22
+ const mark = this.cursor.mark();
23
+ this.children[0].parse(this.cursor);
24
+
25
+ if (this.cursor.hasUnresolvedError()) {
26
+ this.cursor.resolveError();
27
+ this.cursor.moveToMark(mark);
28
+ } else {
29
+ this.cursor.moveToMark(mark);
30
+ const parseError = new ParseError(
31
+ `Match invalid pattern: ${this.children[0].name}.`,
32
+ this.mark,
33
+ this
34
+ );
35
+ this.cursor.throwError(parseError);
36
+ }
37
+ }
38
+
39
+ clone(name?: string) {
40
+ if (name == null) {
41
+ name = this.name;
42
+ }
43
+
44
+ return new Not(this.children[0]);
45
+ }
46
+
47
+ getTokens() {
48
+ return [];
49
+ }
50
+ }