clarity-pattern-parser 3.0.16 → 4.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 (168) 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/ast/Node.ts +20 -17
  23. package/src/ast/Visitor.ts +14 -18
  24. package/src/index.ts +17 -33
  25. package/src/patterns/And.ts +178 -0
  26. package/src/patterns/Literal.ts +91 -0
  27. package/src/patterns/Not.ts +50 -0
  28. package/src/patterns/Or.ts +132 -0
  29. package/src/patterns/Pattern.ts +31 -47
  30. package/src/patterns/Recursive.ts +92 -0
  31. package/src/patterns/{ReferencePattern.ts → Reference.ts} +32 -28
  32. package/src/patterns/Regex.ts +123 -0
  33. package/src/patterns/Repeat.ts +155 -0
  34. package/src/tests/{AndValue.test.ts → And.test.ts} +31 -41
  35. package/src/tests/CursorHistory.test.ts +6 -6
  36. package/src/tests/Cusor.test.ts +7 -10
  37. package/src/tests/Literal.test.ts +3 -5
  38. package/src/tests/LookAhead.test.ts +2 -51
  39. package/src/tests/Not.test.ts +51 -0
  40. package/src/tests/Or.test.ts +113 -0
  41. package/src/tests/Pattern.test.ts +40 -139
  42. package/src/tests/{RecursivePattern.test.ts → Recursive.test.ts} +10 -8
  43. package/src/tests/Reference.test.ts +16 -0
  44. package/src/tests/{RepeatValue.test.ts → Repeat.test.ts} +10 -42
  45. package/src/tests/TextSuggester.test.ts +20 -28
  46. package/src/tests/{NodeVisitor.test.ts → Visitor.test.ts} +42 -21
  47. package/src/tests/cssPatterns/cssValue.ts +2 -2
  48. package/src/tests/cssPatterns/divider.ts +2 -2
  49. package/src/tests/cssPatterns/hex.ts +2 -2
  50. package/src/tests/cssPatterns/method.ts +7 -9
  51. package/src/tests/cssPatterns/name.ts +2 -2
  52. package/src/tests/cssPatterns/number.ts +2 -2
  53. package/src/tests/cssPatterns/optionalSpaces.ts +1 -2
  54. package/src/tests/cssPatterns/spaces.ts +2 -2
  55. package/src/tests/cssPatterns/unit.ts +3 -3
  56. package/src/tests/cssPatterns/value.ts +2 -2
  57. package/src/tests/cssPatterns/values.ts +2 -2
  58. package/src/tests/htmlPatterns/element.ts +18 -33
  59. package/src/tests/javascriptPatterns/boolean.ts +2 -3
  60. package/src/tests/javascriptPatterns/json.ts +14 -26
  61. package/src/tests/javascriptPatterns/name.ts +3 -20
  62. package/src/tests/javascriptPatterns/number.ts +2 -2
  63. package/src/tests/javascriptPatterns/objectLiteral.ts +9 -16
  64. package/src/tests/javascriptPatterns/string.ts +26 -24
  65. package/src/tests/javascriptPatterns/unit.ts +3 -6
  66. package/src/tests/javascriptPatterns/whitespace.ts +8 -12
  67. package/src/tests/naturalLanguage/filter.ts +16 -33
  68. package/src/tests/patterns/sentence.ts +8 -8
  69. package/dist/Cursor.js +0 -105
  70. package/dist/Cursor.js.map +0 -1
  71. package/dist/CursorHistory.js +0 -104
  72. package/dist/CursorHistory.js.map +0 -1
  73. package/dist/Permutor.d.ts +0 -13
  74. package/dist/Permutor.js +0 -52
  75. package/dist/Permutor.js.map +0 -1
  76. package/dist/TextSuggester.js +0 -244
  77. package/dist/TextSuggester.js.map +0 -1
  78. package/dist/ast/CompositeNode.d.ts +0 -6
  79. package/dist/ast/CompositeNode.js +0 -17
  80. package/dist/ast/CompositeNode.js.map +0 -1
  81. package/dist/ast/Node.js +0 -16
  82. package/dist/ast/Node.js.map +0 -1
  83. package/dist/ast/NodeVisitor.d.ts +0 -31
  84. package/dist/ast/ValueNode.d.ts +0 -6
  85. package/dist/ast/ValueNode.js +0 -14
  86. package/dist/ast/ValueNode.js.map +0 -1
  87. package/dist/ast/Visitor.js +0 -209
  88. package/dist/ast/Visitor.js.map +0 -1
  89. package/dist/patterns/ParseError.js +0 -9
  90. package/dist/patterns/ParseError.js.map +0 -1
  91. package/dist/patterns/Pattern.js +0 -127
  92. package/dist/patterns/Pattern.js.map +0 -1
  93. package/dist/patterns/RecursivePattern.js +0 -65
  94. package/dist/patterns/RecursivePattern.js.map +0 -1
  95. package/dist/patterns/composite/AndComposite.d.ts +0 -22
  96. package/dist/patterns/composite/AndComposite.js +0 -117
  97. package/dist/patterns/composite/AndComposite.js.map +0 -1
  98. package/dist/patterns/composite/CompositePattern.d.ts +0 -4
  99. package/dist/patterns/composite/CompositePattern.js +0 -7
  100. package/dist/patterns/composite/CompositePattern.js.map +0 -1
  101. package/dist/patterns/composite/OptionalComposite.d.ts +0 -10
  102. package/dist/patterns/composite/OptionalComposite.js +0 -29
  103. package/dist/patterns/composite/OptionalComposite.js.map +0 -1
  104. package/dist/patterns/composite/OrComposite.d.ts +0 -16
  105. package/dist/patterns/composite/OrComposite.js +0 -69
  106. package/dist/patterns/composite/OrComposite.js.map +0 -1
  107. package/dist/patterns/composite/RepeatComposite.d.ts +0 -21
  108. package/dist/patterns/composite/RepeatComposite.js +0 -88
  109. package/dist/patterns/composite/RepeatComposite.js.map +0 -1
  110. package/dist/patterns/value/AndValue.d.ts +0 -21
  111. package/dist/patterns/value/AndValue.js +0 -118
  112. package/dist/patterns/value/AndValue.js.map +0 -1
  113. package/dist/patterns/value/AnyOfThese.d.ts +0 -18
  114. package/dist/patterns/value/AnyOfThese.js +0 -59
  115. package/dist/patterns/value/AnyOfThese.js.map +0 -1
  116. package/dist/patterns/value/Literal.d.ts +0 -20
  117. package/dist/patterns/value/Literal.js +0 -63
  118. package/dist/patterns/value/Literal.js.map +0 -1
  119. package/dist/patterns/value/NotValue.d.ts +0 -17
  120. package/dist/patterns/value/NotValue.js +0 -70
  121. package/dist/patterns/value/NotValue.js.map +0 -1
  122. package/dist/patterns/value/OptionalValue.d.ts +0 -9
  123. package/dist/patterns/value/OptionalValue.js +0 -32
  124. package/dist/patterns/value/OptionalValue.js.map +0 -1
  125. package/dist/patterns/value/OrValue.d.ts +0 -19
  126. package/dist/patterns/value/OrValue.js +0 -73
  127. package/dist/patterns/value/OrValue.js.map +0 -1
  128. package/dist/patterns/value/RegexValue.d.ts +0 -19
  129. package/dist/patterns/value/RegexValue.js +0 -69
  130. package/dist/patterns/value/RegexValue.js.map +0 -1
  131. package/dist/patterns/value/RepeatValue.d.ts +0 -19
  132. package/dist/patterns/value/RepeatValue.js +0 -89
  133. package/dist/patterns/value/RepeatValue.js.map +0 -1
  134. package/dist/patterns/value/ValuePattern.d.ts +0 -5
  135. package/dist/patterns/value/ValuePattern.js +0 -7
  136. package/dist/patterns/value/ValuePattern.js.map +0 -1
  137. package/src/Permutor.ts +0 -64
  138. package/src/ast/CompositeNode.ts +0 -26
  139. package/src/ast/ValueNode.ts +0 -28
  140. package/src/patterns/RecursivePattern.ts +0 -86
  141. package/src/patterns/composite/AndComposite.ts +0 -159
  142. package/src/patterns/composite/CompositePattern.ts +0 -7
  143. package/src/patterns/composite/OptionalComposite.ts +0 -37
  144. package/src/patterns/composite/OrComposite.ts +0 -96
  145. package/src/patterns/composite/RepeatComposite.ts +0 -130
  146. package/src/patterns/value/AndValue.ts +0 -152
  147. package/src/patterns/value/AnyOfThese.ts +0 -81
  148. package/src/patterns/value/Literal.ts +0 -92
  149. package/src/patterns/value/NotValue.ts +0 -95
  150. package/src/patterns/value/OptionalValue.ts +0 -39
  151. package/src/patterns/value/OrValue.ts +0 -103
  152. package/src/patterns/value/RegexValue.ts +0 -103
  153. package/src/patterns/value/RepeatValue.ts +0 -131
  154. package/src/patterns/value/ValuePattern.ts +0 -8
  155. package/src/tests/AndComposite.test.ts +0 -102
  156. package/src/tests/AnyOfThese.test.ts +0 -74
  157. package/src/tests/CompositeNode.test.ts +0 -33
  158. package/src/tests/NotValue.test.ts +0 -76
  159. package/src/tests/OptionalValue.test.ts +0 -50
  160. package/src/tests/OrComposite.test.ts +0 -75
  161. package/src/tests/OrValue.test.ts +0 -171
  162. package/src/tests/Permutor.test.ts +0 -30
  163. package/src/tests/ReferencePattern.test.ts +0 -24
  164. package/src/tests/RegexValue.test.ts +0 -22
  165. package/src/tests/RepeatComposite.test.ts +0 -58
  166. package/src/tests/ValueNode.test.ts +0 -24
  167. package/src/tests/javascriptPatterns/varStatement.ts +0 -0
  168. 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.0",
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
  }
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
+ }