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
package/dist/index.js CHANGED
@@ -3,44 +3,16 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  class Node {
6
- constructor(type, name, startIndex, endIndex, isComposite = false) {
7
- this.children = [];
8
- this.value = "";
6
+ constructor(type, name, startIndex, endIndex, children = [], value = "") {
9
7
  this.type = type;
10
8
  this.name = name;
11
9
  this.startIndex = startIndex;
12
10
  this.endIndex = endIndex;
13
- this.isComposite = isComposite;
14
- if (typeof this.startIndex !== "number" ||
15
- typeof this.endIndex !== "number") {
16
- throw new Error("Invalid Arguments: startIndex and endIndex need to be number.");
17
- }
18
- }
19
- }
20
-
21
- class CompositeNode extends Node {
22
- constructor(type, name, startIndex = 0, endIndex = 0) {
23
- super(type, name, startIndex, endIndex, true);
24
- }
25
- clone() {
26
- const node = new CompositeNode(this.type, this.name, this.startIndex, this.endIndex);
27
- node.children = this.children.map((child) => {
28
- return child.clone();
29
- });
30
- return node;
31
- }
32
- toString() {
33
- return this.children.map((child) => child.toString()).join("");
34
- }
35
- }
36
-
37
- class ValueNode extends Node {
38
- constructor(type, name, value, startIndex = 0, endIndex = 0) {
39
- super(type, name, startIndex, endIndex);
11
+ this.children = children;
40
12
  this.value = value;
41
13
  }
42
14
  clone() {
43
- return new ValueNode(this.type, this.name, this.value, this.startIndex, this.endIndex);
15
+ return new Node(this.type, this.name, this.startIndex, this.endIndex, this.children.map((c) => c.clone()), this.value);
44
16
  }
45
17
  toString() {
46
18
  return this.value;
@@ -265,19 +237,17 @@ class ParseError {
265
237
  }
266
238
 
267
239
  class Pattern {
268
- constructor(type = "", name, children = []) {
240
+ constructor(type, name, children = [], isOptional = false) {
241
+ this._isOptional = false;
269
242
  this._type = type;
270
243
  this._name = name;
271
244
  this._children = [];
272
245
  this._parent = null;
273
- this.isSequence = false;
274
- this._assertName();
246
+ this._isOptional = isOptional;
275
247
  this.children = children;
276
248
  }
277
- _assertName() {
278
- if (typeof this.name !== "string") {
279
- throw new Error("Invalid Argument: Patterns needs to have a name that's a string.");
280
- }
249
+ get isOptional() {
250
+ return this._isOptional;
281
251
  }
282
252
  exec(text) {
283
253
  const cursor = new Cursor(text);
@@ -302,38 +272,21 @@ class Pattern {
302
272
  return this._parent;
303
273
  }
304
274
  set parent(value) {
305
- if (value instanceof Pattern) {
306
- this._parent = value;
307
- }
275
+ this._parent = value;
308
276
  }
309
277
  get children() {
310
278
  return this._children;
311
279
  }
312
280
  set children(value) {
313
281
  this._children = value;
314
- this._cloneChildren();
315
- this._assertChildren();
316
- this._assignAsParent();
282
+ this.cloneChildren();
283
+ this.assignAsParent();
317
284
  }
318
- _assertChildren() {
319
- // Empty,can be overridden by subclasses.
320
- }
321
- _cloneChildren() {
322
- // We need to clone the patterns so nested patterns can be parsed.
323
- this._children = this._children.map((pattern) => {
324
- if (!(pattern instanceof Pattern)) {
325
- throw new Error(`The ${this.name} pattern has an invalid child pattern.`);
326
- }
327
- return pattern.clone();
328
- });
329
- // We need to freeze the children so they aren't modified.
330
- Object.freeze(this._children);
331
- }
332
- _assignAsParent() {
333
- this._children.forEach((child) => (child.parent = this));
285
+ getTokenValue() {
286
+ return null;
334
287
  }
335
288
  getNextTokens() {
336
- var _a, _b, _c;
289
+ var _a, _b;
337
290
  const parent = this._parent;
338
291
  if (parent != null) {
339
292
  const siblings = parent.children;
@@ -355,11 +308,11 @@ class Pattern {
355
308
  // Another thing I don't like.
356
309
  if (((_b = (_a = this._parent) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.indexOf("and")) === 0 &&
357
310
  nextSibling != null &&
358
- ((_c = nextSibling === null || nextSibling === void 0 ? void 0 : nextSibling.type) === null || _c === void 0 ? void 0 : _c.indexOf("optional")) === 0) {
311
+ nextSibling.isOptional) {
359
312
  let tokens = [];
360
313
  for (let x = index + 1; x < siblings.length; x++) {
361
314
  const child = siblings[x];
362
- if (child.type.indexOf("optional") === 0) {
315
+ if (child.isOptional) {
363
316
  tokens = tokens.concat(child.getTokens());
364
317
  }
365
318
  else {
@@ -385,30 +338,28 @@ class Pattern {
385
338
  }
386
339
  return [];
387
340
  }
388
- getTokenValue() {
389
- return null;
341
+ cloneChildren() {
342
+ this._children = this._children.map((pattern) => {
343
+ return pattern.clone();
344
+ });
345
+ Object.freeze(this._children);
390
346
  }
391
- }
392
-
393
- class ValuePattern extends Pattern {
394
- constructor(type, name, children = []) {
395
- super(type, name, children);
347
+ assignAsParent() {
348
+ this._children.forEach((child) => (child.parent = this));
396
349
  }
397
350
  }
398
351
 
399
- class RegexValue extends ValuePattern {
400
- constructor(name, regex) {
401
- super("regex-value", name);
352
+ class Regex extends Pattern {
353
+ constructor(name, regex, isOptional = false) {
354
+ super("regex", name, [], isOptional);
402
355
  this.node = null;
356
+ this.cursor = null;
403
357
  this.substring = "";
404
358
  this.regexString = regex;
405
359
  this.regex = new RegExp(`^${regex}`, "g");
406
- this._assertArguments();
360
+ this.assertArguments();
407
361
  }
408
- _assertArguments() {
409
- if (typeof this.regexString !== "string") {
410
- throw new Error("Invalid Arguments: The regex argument needs to be a string of regex.");
411
- }
362
+ assertArguments() {
412
363
  if (this.regexString.length < 1) {
413
364
  throw new Error("Invalid Arguments: The regex string argument needs to be at least one character long.");
414
365
  }
@@ -420,39 +371,57 @@ class RegexValue extends ValuePattern {
420
371
  }
421
372
  }
422
373
  parse(cursor) {
423
- this._reset(cursor);
424
- this._tryPattern();
374
+ this.resetState(cursor);
375
+ this.tryToParse();
425
376
  return this.node;
426
377
  }
427
- _reset(cursor) {
378
+ resetState(cursor) {
428
379
  this.cursor = cursor;
429
380
  this.regex.lastIndex = 0;
430
381
  this.substring = this.cursor.text.substr(this.cursor.getIndex());
431
382
  this.node = null;
432
383
  }
433
- _tryPattern() {
384
+ tryToParse() {
434
385
  const result = this.regex.exec(this.substring);
435
386
  if (result != null && result.index === 0) {
436
- const currentIndex = this.cursor.getIndex();
437
- const newIndex = currentIndex + result[0].length - 1;
438
- this.node = new ValueNode("regex-value", this.name, result[0], currentIndex, newIndex);
439
- this.cursor.index = newIndex;
440
- this.cursor.addMatch(this, this.node);
387
+ this.processResult(result);
441
388
  }
442
389
  else {
443
- this._processError();
390
+ this.processError();
444
391
  }
445
392
  }
446
- _processError() {
447
- const message = `ParseError: Expected regex pattern of '${this.regexString}' but found '${this.substring}'.`;
448
- const parseError = new ParseError(message, this.cursor.getIndex(), this);
449
- this.cursor.throwError(parseError);
393
+ processResult(result) {
394
+ const cursor = this.safelyGetCursor();
395
+ const currentIndex = cursor.getIndex();
396
+ const newIndex = currentIndex + result[0].length - 1;
397
+ this.node = new Node("regex", this.name, currentIndex, newIndex, [], result[0]);
398
+ cursor.moveToMark(newIndex);
399
+ cursor.addMatch(this, this.node);
450
400
  }
451
- clone(name) {
452
- if (typeof name !== "string") {
401
+ processError() {
402
+ const cursor = this.safelyGetCursor();
403
+ if (!this._isOptional) {
404
+ const message = `ParseError: Expected regex pattern of '${this.regexString}' but found '${this.substring}'.`;
405
+ const parseError = new ParseError(message, cursor.getIndex(), this);
406
+ cursor.throwError(parseError);
407
+ }
408
+ this.node = null;
409
+ }
410
+ safelyGetCursor() {
411
+ const cursor = this.cursor;
412
+ if (cursor == null) {
413
+ throw new Error("Couldn't find cursor.");
414
+ }
415
+ return cursor;
416
+ }
417
+ clone(name, isOptional) {
418
+ if (name == null) {
453
419
  name = this.name;
454
420
  }
455
- return new RegexValue(name, this.regexString);
421
+ if (isOptional == null) {
422
+ isOptional = this._isOptional;
423
+ }
424
+ return new Regex(name, this.regexString, isOptional);
456
425
  }
457
426
  getTokenValue() {
458
427
  return this.name;
@@ -462,712 +431,371 @@ class RegexValue extends ValuePattern {
462
431
  }
463
432
  }
464
433
 
465
- class OptionalValue extends ValuePattern {
466
- constructor(pattern) {
467
- super("optional-value", "optional-value", [pattern]);
468
- this._assertArguments();
469
- }
470
- _assertArguments() {
471
- if (!(this.children[0] instanceof ValuePattern)) {
472
- throw new Error("Invalid Arguments: Expected a ValuePattern.");
473
- }
434
+ class And extends Pattern {
435
+ constructor(name, patterns, isOptional = false) {
436
+ super("and", name, patterns, isOptional);
437
+ this.onPatternIndex = 0;
438
+ this.nodes = [];
439
+ this.node = null;
440
+ this.cursor = null;
441
+ this.mark = 0;
474
442
  }
475
443
  parse(cursor) {
476
- const mark = cursor.mark();
477
- const node = this.children[0].parse(cursor);
478
- if (cursor.hasUnresolvedError() || node == null) {
479
- cursor.resolveError();
480
- cursor.moveToMark(mark);
481
- return null;
444
+ this.resetState(cursor);
445
+ this.tryToParse();
446
+ return this.node;
447
+ }
448
+ clone(name, isOptional) {
449
+ if (name == null) {
450
+ name = this.name;
482
451
  }
483
- else {
484
- cursor.addMatch(this, node);
485
- return node;
452
+ if (isOptional == null) {
453
+ isOptional = this._isOptional;
486
454
  }
487
- }
488
- clone() {
489
- return new OptionalValue(this.children[0]);
455
+ return new And(name, this._children, isOptional);
490
456
  }
491
457
  getTokens() {
492
- return this._children[0].getTokens();
493
- }
494
- }
495
-
496
- class AndValue extends ValuePattern {
497
- constructor(name, patterns) {
498
- super("and-value", name, patterns);
499
- this.index = 0;
500
- this.nodes = [];
501
- this.node = null;
502
- this.mark = 0;
503
- this._assertArguments();
504
- }
505
- _assertArguments() {
506
- if (this._children.length < 2) {
507
- throw new Error("Invalid Argument: AndValue needs to have more than one value pattern.");
458
+ let tokens = [];
459
+ for (let x = 0; x < this._children.length; x++) {
460
+ const child = this._children[x];
461
+ if (child.isOptional) {
462
+ tokens = tokens.concat(child.getTokens());
463
+ }
464
+ else {
465
+ tokens = tokens.concat(child.getTokens());
466
+ break;
467
+ }
508
468
  }
469
+ return tokens;
509
470
  }
510
- _reset(cursor) {
511
- this.index = 0;
471
+ resetState(cursor) {
472
+ this.onPatternIndex = 0;
512
473
  this.nodes = [];
513
474
  this.node = null;
514
475
  this.cursor = cursor;
515
476
  this.mark = this.cursor.mark();
516
477
  }
517
- parse(cursor) {
518
- this._reset(cursor);
519
- this._tryPatterns();
520
- return this.node;
521
- }
522
- _tryPatterns() {
478
+ tryToParse() {
479
+ const cursor = this.safelyGetCursor();
523
480
  while (true) {
524
- const pattern = this._children[this.index];
525
- const node = pattern.parse(this.cursor);
526
- if (this.cursor.hasUnresolvedError()) {
481
+ const pattern = this._children[this.onPatternIndex];
482
+ const node = pattern.parse(cursor);
483
+ if (cursor.hasUnresolvedError()) {
484
+ this.processError();
527
485
  break;
528
486
  }
529
487
  else {
530
488
  this.nodes.push(node);
531
489
  }
532
- if (!this._next()) {
533
- this._processValue();
490
+ if (!this.shouldProceed()) {
491
+ this.processResult();
534
492
  break;
535
493
  }
536
494
  }
537
495
  }
538
- _next() {
539
- if (this._hasMorePatterns()) {
540
- if (this.cursor.hasNext()) {
541
- // If the last result was a failed optional, then don't increment the cursor.
542
- if (this.nodes[this.nodes.length - 1] != null) {
543
- this.cursor.next();
496
+ safelyGetCursor() {
497
+ const cursor = this.cursor;
498
+ if (cursor == null) {
499
+ throw new Error("Couldn't find cursor.");
500
+ }
501
+ return cursor;
502
+ }
503
+ processResult() {
504
+ const cursor = this.safelyGetCursor();
505
+ if (cursor.hasUnresolvedError()) {
506
+ this.processError();
507
+ }
508
+ else {
509
+ this.processSuccess();
510
+ }
511
+ }
512
+ processError() {
513
+ const cursor = this.safelyGetCursor();
514
+ if (this.isOptional) {
515
+ cursor.moveToMark(this.mark);
516
+ cursor.resolveError();
517
+ }
518
+ this.node = null;
519
+ }
520
+ shouldProceed() {
521
+ const cursor = this.safelyGetCursor();
522
+ if (this.hasMorePatterns()) {
523
+ const lastNode = this.nodes[this.nodes.length - 1];
524
+ const wasOptional = lastNode == null;
525
+ if (cursor.hasNext()) {
526
+ if (!wasOptional) {
527
+ cursor.next();
544
528
  }
545
- this.index++;
529
+ this.onPatternIndex++;
546
530
  return true;
547
531
  }
548
- else if (this.nodes[this.nodes.length - 1] == null) {
549
- this.index++;
532
+ else if (wasOptional) {
533
+ this.onPatternIndex++;
550
534
  return true;
551
535
  }
552
- this._assertRestOfPatternsAreOptional();
536
+ this.assertRestOfPatternsAreOptional();
553
537
  return false;
554
538
  }
555
539
  else {
556
540
  return false;
557
541
  }
558
542
  }
559
- _hasMorePatterns() {
560
- return this.index + 1 < this._children.length;
543
+ hasMorePatterns() {
544
+ return this.onPatternIndex + 1 < this._children.length;
561
545
  }
562
- _assertRestOfPatternsAreOptional() {
563
- const areTheRestOptional = this.children.every((pattern, index) => {
564
- return index <= this.index || pattern instanceof OptionalValue;
565
- });
546
+ assertRestOfPatternsAreOptional() {
547
+ const cursor = this.safelyGetCursor();
548
+ const areTheRestOptional = this.areTheRemainingPatternsOptional();
566
549
  if (!areTheRestOptional) {
567
- const parseError = new ParseError(`Could not match ${this.name} before string ran out.`, this.index, this);
568
- this.cursor.throwError(parseError);
569
- }
570
- }
571
- _processValue() {
572
- if (this.cursor.hasUnresolvedError()) {
573
- this.node = null;
574
- }
575
- else {
576
- this.nodes = this.nodes.filter((node) => node != null);
577
- const lastNode = this.nodes[this.nodes.length - 1];
578
- const startIndex = this.mark;
579
- const endIndex = lastNode.endIndex;
580
- const value = this.nodes.map((node) => node.value).join("");
581
- this.node = new ValueNode("and-value", this.name, value, startIndex, endIndex);
582
- this.cursor.index = this.node.endIndex;
583
- this.cursor.addMatch(this, this.node);
584
- }
585
- }
586
- clone(name) {
587
- if (typeof name !== "string") {
588
- name = this.name;
589
- }
590
- return new AndValue(name, this._children);
591
- }
592
- getTokens() {
593
- let tokens = [];
594
- for (let x = 0; x < this._children.length; x++) {
595
- const child = this._children[x];
596
- if (child instanceof OptionalValue) {
597
- tokens = tokens.concat(child.getTokens());
598
- }
599
- else {
600
- tokens = tokens.concat(child.getTokens());
601
- break;
602
- }
603
- }
604
- return tokens;
550
+ const parseError = new ParseError(`Could not match ${this.name} before string ran out.`, this.onPatternIndex, this);
551
+ cursor.throwError(parseError);
552
+ }
553
+ }
554
+ areTheRemainingPatternsOptional() {
555
+ return this.children
556
+ .slice(this.onPatternIndex + 1)
557
+ .map((p) => p.isOptional)
558
+ .every((r) => r);
559
+ }
560
+ processSuccess() {
561
+ const cursor = this.safelyGetCursor();
562
+ const nodes = this.nodes.filter((node) => node != null);
563
+ this.nodes = nodes;
564
+ const lastNode = nodes[this.nodes.length - 1];
565
+ const startIndex = this.mark;
566
+ const endIndex = lastNode.endIndex;
567
+ const value = nodes.map((node) => node.value).join("");
568
+ this.node = new Node("and", this.name, startIndex, endIndex, nodes, value);
569
+ cursor.index = this.node.endIndex;
570
+ cursor.addMatch(this, this.node);
605
571
  }
606
572
  }
607
573
 
608
- class AnyOfThese extends ValuePattern {
609
- constructor(name, characters) {
610
- super("any-of-these", name);
574
+ class Literal extends Pattern {
575
+ constructor(name, literal, isOptional = false) {
576
+ super("literal", name, [], isOptional);
611
577
  this.node = null;
612
578
  this.mark = 0;
613
- this.characters = characters;
614
- this._assertArguments();
615
- }
616
- _assertArguments() {
617
- if (typeof this.characters !== "string") {
618
- throw new Error("Invalid Arguments: The characters argument needs to be a string of characters.");
619
- }
620
- if (this.characters.length < 1) {
621
- throw new Error("Invalid Arguments: The characters argument needs to be at least one character long.");
622
- }
579
+ this.substring = "";
580
+ this.literal = literal;
581
+ this.assertArguments();
623
582
  }
624
583
  parse(cursor) {
625
- this._reset(cursor);
626
- this._tryPattern();
584
+ this.resetState(cursor);
585
+ this.tryToParse();
627
586
  return this.node;
628
587
  }
629
- _reset(cursor) {
630
- this.cursor = cursor;
631
- this.mark = this.cursor.mark();
632
- this.node = null;
633
- }
634
- _tryPattern() {
635
- if (this._isMatch()) {
636
- const value = this.cursor.getChar();
637
- const index = this.cursor.getIndex();
638
- this.node = new ValueNode("any-of-these", this.name, value, index, index);
639
- this.cursor.addMatch(this, this.node);
640
- }
641
- else {
642
- this._processError();
643
- }
644
- }
645
- _isMatch() {
646
- return this.characters.indexOf(this.cursor.getChar()) > -1;
647
- }
648
- _processError() {
649
- const message = `ParseError: Expected one of these characters, '${this.characters}' but found '${this.cursor.getChar()}' while parsing for '${this.name}'.`;
650
- const parseError = new ParseError(message, this.cursor.getIndex(), this);
651
- this.cursor.throwError(parseError);
652
- }
653
- clone(name) {
654
- if (typeof name !== "string") {
588
+ clone(name, isOptional) {
589
+ if (name == null) {
655
590
  name = this.name;
656
591
  }
657
- return new AnyOfThese(name, this.characters);
592
+ if (isOptional == null) {
593
+ isOptional = this._isOptional;
594
+ }
595
+ return new Literal(name, this.literal, isOptional);
658
596
  }
659
597
  getTokens() {
660
- return this.characters.split("");
661
- }
662
- }
663
-
664
- class Literal extends ValuePattern {
665
- constructor(name, literal) {
666
- super("literal", name);
667
- this.node = null;
668
- this.mark = 0;
669
- this.substring = "";
670
- this.literal = literal;
671
- this._assertArguments();
598
+ return [this.literal];
672
599
  }
673
- _assertArguments() {
674
- if (typeof this.literal !== "string") {
675
- throw new Error("Invalid Arguments: The literal argument needs to be a string of characters.");
676
- }
600
+ assertArguments() {
677
601
  if (this.literal.length < 1) {
678
- throw new Error("Invalid Arguments: The literalString argument needs to be at least one character long.");
602
+ throw new Error("Invalid Arguments: The `literal` argument needs to be at least one character long.");
679
603
  }
680
604
  }
681
- parse(cursor) {
682
- this._reset(cursor);
683
- this._tryPattern();
684
- return this.node;
685
- }
686
- _reset(cursor) {
605
+ resetState(cursor) {
687
606
  this.cursor = cursor;
688
607
  this.mark = this.cursor.mark();
689
608
  this.substring = this.cursor.text.substring(this.mark, this.mark + this.literal.length);
690
609
  this.node = null;
691
610
  }
692
- _tryPattern() {
611
+ tryToParse() {
693
612
  if (this.substring === this.literal) {
694
- this._processMatch();
613
+ this.processResult();
695
614
  }
696
615
  else {
697
- this._processError();
616
+ this.processError();
698
617
  }
699
618
  }
700
- _processError() {
701
- const message = `ParseError: Expected '${this.literal}' but found '${this.substring}'.`;
702
- const parseError = new ParseError(message, this.cursor.getIndex(), this);
703
- this.cursor.throwError(parseError);
619
+ processError() {
620
+ this.node = null;
621
+ if (!this._isOptional) {
622
+ const message = `ParseError: Expected '${this.literal}' but found '${this.substring}'.`;
623
+ const parseError = new ParseError(message, this.cursor.getIndex(), this);
624
+ this.cursor.throwError(parseError);
625
+ }
704
626
  }
705
- _processMatch() {
706
- this.node = new ValueNode("literal", this.name, this.substring, this.mark, this.mark + this.literal.length - 1);
627
+ processResult() {
628
+ this.node = new Node("literal", this.name, this.mark, this.mark + this.literal.length - 1, [], this.substring);
707
629
  this.cursor.index = this.node.endIndex;
708
630
  this.cursor.addMatch(this, this.node);
709
631
  }
710
- clone(name) {
711
- if (typeof name !== "string") {
712
- name = this.name;
632
+ }
633
+
634
+ class LookAhead extends Pattern {
635
+ constructor(pattern) {
636
+ super("look-ahead", "look-ahead", [pattern]);
637
+ }
638
+ parse(cursor) {
639
+ const mark = cursor.mark();
640
+ const node = this.children[0].parse(cursor);
641
+ if (cursor.hasUnresolvedError() || node == null) {
642
+ cursor.resolveError();
643
+ cursor.throwError(new ParseError("Couldn't find look ahead pattern.", mark, this.children[0]));
644
+ cursor.moveToMark(mark);
713
645
  }
714
- return new Literal(name, this.literal);
646
+ return null;
715
647
  }
716
- getTokenValue() {
717
- return this.literal;
648
+ clone() {
649
+ return new LookAhead(this.children[0].clone());
718
650
  }
719
651
  getTokens() {
720
- return [this.getTokenValue()];
652
+ return [];
721
653
  }
722
654
  }
723
655
 
724
- class NotValue extends ValuePattern {
725
- constructor(name, pattern) {
726
- super("not-value", name, [pattern]);
727
- this.match = "";
728
- this.node = null;
656
+ class Not extends Pattern {
657
+ constructor(pattern) {
658
+ super("not", `not-${pattern.name}`, [pattern]);
729
659
  this.mark = 0;
730
- this._assertArguments();
731
- }
732
- _assertArguments() {
733
- if (!(this.children[0] instanceof Pattern)) {
734
- throw new Error("Invalid Arguments: Expected the pattern to be a ValuePattern.");
735
- }
736
- if (typeof this.name !== "string") {
737
- throw new Error("Invalid Arguments: Expected name to be a string.");
738
- }
739
- }
740
- _reset(cursor) {
741
- this.match = "";
742
- this.node = null;
743
- this.cursor = cursor;
744
- this.mark = this.cursor.mark();
660
+ this._isOptional = true;
745
661
  }
746
662
  parse(cursor) {
747
- this._reset(cursor);
748
- this._tryPattern();
749
- return this.node;
750
- }
751
- _tryPattern() {
752
- while (true) {
753
- const mark = this.cursor.mark();
754
- this.children[0].parse(this.cursor);
755
- if (this.cursor.hasUnresolvedError()) {
756
- this.cursor.resolveError();
757
- this.cursor.moveToMark(mark);
758
- this.match += this.cursor.getChar();
759
- break;
760
- }
761
- else {
762
- this.cursor.moveToMark(mark);
763
- break;
764
- }
765
- }
766
- this._processMatch();
663
+ this.cursor = cursor;
664
+ this.mark = cursor.mark();
665
+ this.tryToParse();
666
+ return null;
767
667
  }
768
- _processMatch() {
769
- if (this.match.length === 0) {
770
- const parseError = new ParseError(`Didn't find any characters that didn't match the ${this.children[0].name} pattern.`, this.mark, this);
771
- this.cursor.throwError(parseError);
668
+ tryToParse() {
669
+ const mark = this.cursor.mark();
670
+ this.children[0].parse(this.cursor);
671
+ if (this.cursor.hasUnresolvedError()) {
672
+ this.cursor.resolveError();
673
+ this.cursor.moveToMark(mark);
772
674
  }
773
675
  else {
774
- this.node = new ValueNode("not-value", this.name, this.match, this.mark, this.mark);
775
- this.cursor.index = this.node.endIndex;
776
- this.cursor.addMatch(this, this.node);
676
+ this.cursor.moveToMark(mark);
677
+ const parseError = new ParseError(`Match invalid pattern: ${this.children[0].name}.`, this.mark, this);
678
+ this.cursor.throwError(parseError);
777
679
  }
778
680
  }
779
681
  clone(name) {
780
- if (typeof name !== "string") {
682
+ if (name == null) {
781
683
  name = this.name;
782
684
  }
783
- return new NotValue(name, this.children[0]);
685
+ return new Not(this.children[0]);
784
686
  }
785
687
  getTokens() {
786
688
  return [];
787
689
  }
788
690
  }
789
691
 
790
- class OrValue extends ValuePattern {
791
- constructor(name, patterns) {
792
- super("or-value", name, patterns);
793
- this.index = 0;
692
+ class Or extends Pattern {
693
+ constructor(name, patterns, isOptional = false) {
694
+ super("or", name, patterns, isOptional);
695
+ this.patternIndex = 0;
794
696
  this.errors = [];
795
697
  this.node = null;
698
+ this.cursor = null;
796
699
  this.mark = 0;
797
700
  this.parseError = null;
798
- this._assertArguments();
701
+ this.assertArguments();
799
702
  }
800
- _assertArguments() {
703
+ assertArguments() {
801
704
  if (this._children.length < 2) {
802
705
  throw new Error("Invalid Argument: OrValue needs to have more than one value pattern.");
803
706
  }
804
- const hasOptionalChildren = this._children.some((pattern) => pattern instanceof OptionalValue);
707
+ const hasOptionalChildren = this._children.some((pattern) => pattern.isOptional);
805
708
  if (hasOptionalChildren) {
806
- throw new Error("OrValues cannot have optional values.");
709
+ throw new Error("OrValues cannot have optional patterns.");
807
710
  }
808
711
  }
809
- _reset(cursor) {
810
- this.index = 0;
712
+ resetState(cursor) {
713
+ this.patternIndex = 0;
811
714
  this.errors = [];
812
715
  this.node = null;
813
716
  this.cursor = cursor;
814
717
  this.mark = cursor.mark();
815
718
  }
816
- parse(cursor) {
817
- this._reset(cursor);
818
- this._tryPattern();
819
- return this.node;
820
- }
821
- _tryPattern() {
822
- while (true) {
823
- const pattern = this._children[this.index];
824
- const node = pattern.parse(this.cursor);
825
- if (this.cursor.hasUnresolvedError()) {
826
- if (this.index + 1 < this._children.length) {
827
- this.cursor.resolveError();
828
- this.index++;
829
- this.cursor.moveToMark(this.mark);
830
- }
831
- else {
832
- this.node = null;
833
- break;
834
- }
835
- }
836
- else {
837
- this.node = new ValueNode("or-value", this.name, node.value, node.startIndex, node.endIndex);
838
- this.cursor.index = this.node.endIndex;
839
- this.cursor.addMatch(this, this.node);
840
- break;
841
- }
842
- }
843
- }
844
- clone(name) {
845
- if (typeof name !== "string") {
846
- name = this.name;
847
- }
848
- return new OrValue(name, this._children);
849
- }
850
- getTokens() {
851
- const tokens = this._children.map((c) => c.getTokens());
852
- const hasPrimitiveTokens = tokens.every((t) => t.every((value) => typeof value === "string"));
853
- if (hasPrimitiveTokens && tokens.length > 0) {
854
- return tokens.reduce((acc, t) => acc.concat(t), []);
855
- }
856
- return this._children[0].getTokens();
857
- }
858
- }
859
-
860
- class RepeatValue extends ValuePattern {
861
- constructor(name, pattern, divider) {
862
- super("repeat-value", name, divider != null ? [pattern, divider] : [pattern]);
863
- this.nodes = [];
864
- this.mark = 0;
865
- this.node = null;
866
- this._pattern = this.children[0];
867
- this._divider = this.children[1];
868
- this._assertArguments();
869
- }
870
- _assertArguments() {
871
- if (this._pattern instanceof OptionalValue) {
872
- throw new Error("Invalid Arguments: The pattern cannot be a optional pattern.");
719
+ safelyGetCursor() {
720
+ const cursor = this.cursor;
721
+ if (cursor == null) {
722
+ throw new Error("Couldn't find cursor.");
873
723
  }
874
- }
875
- _reset(cursor) {
876
- this.nodes = [];
877
- this.cursor = cursor;
878
- this.mark = this.cursor.mark();
724
+ return cursor;
879
725
  }
880
726
  parse(cursor) {
881
- this._reset(cursor);
882
- this._tryPattern();
727
+ this.resetState(cursor);
728
+ this.tryToParse();
883
729
  return this.node;
884
730
  }
885
- _tryPattern() {
731
+ tryToParse() {
732
+ const cursor = this.safelyGetCursor();
886
733
  while (true) {
887
- const node = this._pattern.parse(this.cursor);
888
- if (this.cursor.hasUnresolvedError()) {
889
- this._processMatch();
890
- break;
891
- }
892
- else {
893
- this.nodes.push(node);
894
- if (node.endIndex === this.cursor.lastIndex()) {
895
- this._processMatch();
734
+ const pattern = this._children[this.patternIndex];
735
+ const node = pattern.parse(cursor);
736
+ const hasError = cursor.hasUnresolvedError();
737
+ if (hasError) {
738
+ const shouldBreak = this.processError();
739
+ if (shouldBreak) {
896
740
  break;
897
741
  }
898
- this.cursor.next();
899
- if (this._divider != null) {
900
- const mark = this.cursor.mark();
901
- const node = this._divider.parse(this.cursor);
902
- if (this.cursor.hasUnresolvedError()) {
903
- this.cursor.moveToMark(mark);
904
- this._processMatch();
905
- break;
906
- }
907
- else {
908
- this.nodes.push(node);
909
- if (node.endIndex === this.cursor.lastIndex()) {
910
- this._processMatch();
911
- break;
912
- }
913
- this.cursor.next();
914
- }
915
- }
916
- }
917
- }
918
- }
919
- _processMatch() {
920
- const endsOnDivider = this.nodes.length % 2 === 0;
921
- const noMatch = this.nodes.length === 0;
922
- const hasDivider = this._divider != null;
923
- this.cursor.resolveError();
924
- if ((hasDivider && endsOnDivider) || noMatch) {
925
- const parseError = new ParseError(`Did not find a repeating match of ${this.name}.`, this.mark, this);
926
- this.cursor.throwError(parseError);
927
- this.node = null;
928
- }
929
- else {
930
- const value = this.nodes.map((node) => node.value).join("");
931
- this.node = new ValueNode("repeat-value", this.name, value, this.nodes[0].startIndex, this.nodes[this.nodes.length - 1].endIndex);
932
- this.cursor.index = this.node.endIndex;
933
- this.cursor.addMatch(this, this.node);
934
- }
935
- }
936
- clone(name) {
937
- if (typeof name !== "string") {
938
- name = this.name;
939
- }
940
- return new RepeatValue(name, this._pattern, this._divider);
941
- }
942
- getTokens() {
943
- return this._pattern.getTokens();
944
- }
945
- }
946
-
947
- class CompositePattern extends Pattern {
948
- constructor(type, name, children = []) {
949
- super(type, name, children);
950
- }
951
- }
952
-
953
- class OptionalComposite extends CompositePattern {
954
- constructor(pattern) {
955
- super("optional-composite", "optional-composite", [pattern]);
956
- }
957
- parse(cursor) {
958
- const mark = cursor.mark();
959
- this.mark = mark;
960
- const node = this.children[0].parse(cursor);
961
- if (cursor.hasUnresolvedError()) {
962
- cursor.resolveError();
963
- cursor.moveToMark(mark);
964
- return null;
965
- }
966
- else {
967
- if (node != null) {
968
- cursor.addMatch(this, node);
969
- }
970
- return node;
971
- }
972
- }
973
- clone() {
974
- return new OptionalComposite(this.children[0]);
975
- }
976
- getTokens() {
977
- return this._children[0].getTokens();
978
- }
979
- }
980
-
981
- class AndComposite extends CompositePattern {
982
- constructor(name, patterns = []) {
983
- super("and-composite", name, patterns);
984
- this._assertArguments();
985
- }
986
- _assertArguments() {
987
- if (this._children.length < 2) {
988
- throw new Error("Invalid Argument: AndValue needs to have more than one value pattern.");
989
- }
990
- }
991
- _reset(cursor) {
992
- this.index = 0;
993
- this.nodes = [];
994
- this.node = null;
995
- this.cursor = cursor;
996
- this.mark = this.cursor.mark();
997
- }
998
- parse(cursor) {
999
- this._reset(cursor);
1000
- this._tryPatterns();
1001
- return this.node;
1002
- }
1003
- _tryPatterns() {
1004
- while (true) {
1005
- const pattern = this._children[this.index];
1006
- const node = pattern.parse(this.cursor);
1007
- if (this.cursor.hasUnresolvedError()) {
1008
- this.cursor.moveToMark(this.mark);
1009
- break;
1010
- }
1011
- else {
1012
- this.nodes.push(node);
1013
742
  }
1014
- if (!this._next()) {
1015
- this._processValue();
743
+ else if (node != null) {
744
+ this.processResult(node);
1016
745
  break;
1017
746
  }
1018
747
  }
1019
748
  }
1020
- _next() {
1021
- if (this._hasMorePatterns()) {
1022
- if (this.cursor.hasNext()) {
1023
- // If the last result was a failed optional, then don't increment the cursor.
1024
- if (this.nodes[this.nodes.length - 1] != null) {
1025
- this.cursor.next();
1026
- }
1027
- this.index++;
1028
- return true;
1029
- }
1030
- else if (this.nodes[this.nodes.length - 1] == null) {
1031
- this.index++;
1032
- return true;
1033
- }
1034
- this._assertRestOfPatternsAreOptional();
1035
- return false;
1036
- }
1037
- else {
749
+ processError() {
750
+ const cursor = this.safelyGetCursor();
751
+ const isLastPattern = this.patternIndex + 1 === this._children.length;
752
+ if (!isLastPattern) {
753
+ this.patternIndex++;
754
+ cursor.resolveError();
755
+ cursor.moveToMark(this.mark);
1038
756
  return false;
1039
757
  }
1040
- }
1041
- _hasMorePatterns() {
1042
- return this.index + 1 < this._children.length;
1043
- }
1044
- _assertRestOfPatternsAreOptional() {
1045
- const areTheRestOptional = this.children.every((pattern, index) => {
1046
- return (index <= this.index ||
1047
- pattern instanceof OptionalValue ||
1048
- pattern instanceof OptionalComposite);
1049
- });
1050
- if (!areTheRestOptional) {
1051
- const parseError = new ParseError(`Could not match ${this.name} before string ran out.`, this.index, this);
1052
- this.cursor.throwError(parseError);
1053
- }
1054
- }
1055
- _processValue() {
1056
- if (!this.cursor.hasUnresolvedError()) {
1057
- this.nodes = this.nodes.filter((node) => node != null);
1058
- const lastNode = this.nodes[this.nodes.length - 1];
1059
- const startIndex = this.mark;
1060
- const endIndex = lastNode.endIndex;
1061
- this.node = new CompositeNode("and-composite", this.name, startIndex, endIndex);
1062
- this.node.children = this.nodes;
1063
- this.cursor.index = this.node.endIndex;
1064
- this.cursor.addMatch(this, this.node);
1065
- }
1066
758
  else {
1067
- this.node = null;
1068
- }
1069
- }
1070
- clone(name) {
1071
- if (typeof name !== "string") {
1072
- name = this.name;
1073
- }
1074
- return new AndComposite(name, this._children);
1075
- }
1076
- getTokens() {
1077
- let tokens = [];
1078
- for (let x = 0; x < this._children.length; x++) {
1079
- const child = this._children[x];
1080
- if (child instanceof OptionalValue ||
1081
- child instanceof OptionalComposite) {
1082
- tokens = tokens.concat(child.getTokens());
1083
- }
1084
- else {
1085
- tokens = tokens.concat(child.getTokens());
1086
- break;
759
+ if (this._isOptional) {
760
+ cursor.resolveError();
761
+ cursor.moveToMark(this.mark);
1087
762
  }
763
+ this.node = null;
764
+ return true;
1088
765
  }
1089
- return tokens;
1090
- }
1091
- }
1092
-
1093
- class OrComposite extends CompositePattern {
1094
- constructor(name, patterns) {
1095
- super("or-composite", name, patterns);
1096
- this._assertArguments();
1097
- }
1098
- _assertArguments() {
1099
- if (this._children.length < 2) {
1100
- throw new Error("Invalid Argument: OrValue needs to have more than one value pattern.");
1101
- }
1102
- const hasOptionalChildren = this._children.some((pattern) => pattern instanceof OptionalValue || pattern instanceof OptionalComposite);
1103
- if (hasOptionalChildren) {
1104
- throw new Error("OrComposite cannot have optional values.");
1105
- }
1106
- }
1107
- _reset(cursor) {
1108
- this.cursor = cursor;
1109
- this.mark = null;
1110
- this.index = 0;
1111
- this.node = null;
1112
- this.mark = cursor.mark();
1113
- }
1114
- parse(cursor) {
1115
- this._reset(cursor);
1116
- this._tryPattern();
1117
- if (this.node != null) {
1118
- this.cursor.addMatch(this, this.node);
1119
- }
1120
- return this.node;
1121
766
  }
1122
- _tryPattern() {
1123
- while (true) {
1124
- const pattern = this._children[this.index];
1125
- this.node = pattern.parse(this.cursor);
1126
- if (this.cursor.hasUnresolvedError()) {
1127
- if (this.index + 1 < this._children.length) {
1128
- this.cursor.resolveError();
1129
- this.index++;
1130
- this.cursor.moveToMark(this.mark);
1131
- }
1132
- else {
1133
- this.node = null;
1134
- break;
1135
- }
1136
- }
1137
- else {
1138
- this.cursor.index = this.node.endIndex;
1139
- break;
1140
- }
1141
- }
767
+ processResult(node) {
768
+ const cursor = this.safelyGetCursor();
769
+ this.node = new Node("or", this.name, node.startIndex, node.endIndex, [node], node.value);
770
+ cursor.index = this.node.endIndex;
771
+ cursor.addMatch(this, this.node);
1142
772
  }
1143
- clone(name) {
1144
- if (typeof name !== "string") {
773
+ clone(name, isOptional) {
774
+ if (name == null) {
1145
775
  name = this.name;
1146
776
  }
1147
- return new OrComposite(name, this._children);
777
+ if (isOptional == null) {
778
+ isOptional = this._isOptional;
779
+ }
780
+ return new Or(name, this._children, isOptional);
1148
781
  }
1149
782
  getTokens() {
1150
- const tokens = this._children.map((c) => c.getTokens());
1151
- const hasPrimitiveTokens = tokens.every((t) => t.every((value) => typeof value === "string"));
1152
- if (hasPrimitiveTokens && tokens.length > 0) {
1153
- return tokens.reduce((acc, t) => acc.concat(t), []);
1154
- }
1155
- return this._children[0].getTokens();
783
+ return this._children.reduce((acc, c) => acc.concat(c.getTokens()), []);
1156
784
  }
1157
785
  }
1158
786
 
1159
- class RepeatComposite extends CompositePattern {
1160
- constructor(name, pattern, divider) {
1161
- super("repeat-composite", name, divider != null ? [pattern, divider] : [pattern]);
787
+ class Repeat extends Pattern {
788
+ constructor(name, pattern, divider, isOptional = false) {
789
+ super("repeat", name, divider != null ? [pattern, divider] : [pattern], isOptional);
1162
790
  this.nodes = [];
1163
791
  this.mark = 0;
1164
792
  this.node = null;
1165
793
  this._pattern = this.children[0];
1166
794
  this._divider = this.children[1];
1167
- this._assertArguments();
795
+ this.assertArguments();
1168
796
  }
1169
- _assertArguments() {
1170
- if (this._pattern instanceof OptionalComposite) {
797
+ assertArguments() {
798
+ if (this._pattern.isOptional) {
1171
799
  throw new Error("Invalid Arguments: The pattern cannot be a optional pattern.");
1172
800
  }
1173
801
  }
@@ -1178,91 +806,108 @@ class RepeatComposite extends CompositePattern {
1178
806
  }
1179
807
  parse(cursor) {
1180
808
  this._reset(cursor);
1181
- this._tryPattern();
809
+ this.tryToParse();
1182
810
  return this.node;
1183
811
  }
1184
- _tryPattern() {
812
+ tryToParse() {
813
+ const cursor = this.safelyGetCursor();
1185
814
  while (true) {
1186
- const node = this._pattern.parse(this.cursor);
1187
- if (this.cursor.hasUnresolvedError() || node == null) {
1188
- this._processMatch();
815
+ const node = this._pattern.parse(cursor);
816
+ if (cursor.hasUnresolvedError()) {
817
+ this.processResult();
1189
818
  break;
1190
819
  }
1191
- else {
820
+ else if (node != null) {
1192
821
  this.nodes.push(node);
1193
- if (node.endIndex === this.cursor.lastIndex()) {
1194
- this._processMatch();
822
+ if (node.endIndex === cursor.lastIndex()) {
823
+ this.processResult();
1195
824
  break;
1196
825
  }
1197
- this.cursor.next();
826
+ cursor.next();
1198
827
  if (this._divider != null) {
1199
- const mark = this.cursor.mark();
1200
- const node = this._divider.parse(this.cursor);
1201
- if (this.cursor.hasUnresolvedError() || node == null) {
1202
- this.cursor.moveToMark(mark);
1203
- this._processMatch();
828
+ const mark = cursor.mark();
829
+ const node = this._divider.parse(cursor);
830
+ if (cursor.hasUnresolvedError()) {
831
+ cursor.moveToMark(mark);
832
+ this.processResult();
1204
833
  break;
1205
834
  }
1206
- else {
835
+ else if (node != null) {
1207
836
  this.nodes.push(node);
1208
- if (node.endIndex === this.cursor.lastIndex()) {
1209
- this._processMatch();
837
+ if (node.endIndex === cursor.lastIndex()) {
838
+ this.processResult();
1210
839
  break;
1211
840
  }
1212
- this.cursor.next();
841
+ cursor.next();
1213
842
  }
1214
843
  }
1215
844
  }
1216
845
  }
1217
846
  }
1218
- _processMatch() {
847
+ processResult() {
1219
848
  const endsOnDivider = this.nodes.length % 2 === 0;
1220
849
  const noMatch = this.nodes.length === 0;
1221
850
  const hasDivider = this._divider != null;
1222
851
  this.cursor.resolveError();
1223
852
  if ((hasDivider && endsOnDivider) || noMatch) {
1224
- this.cursor.throwError(new ParseError(`Did not find a repeating match of ${this.name}.`, this.mark, this));
853
+ if (this._isOptional) {
854
+ this.cursor.moveToMark(this.mark);
855
+ }
856
+ else {
857
+ const parseError = new ParseError(`Did not find a repeating match of ${this.name}.`, this.mark, this);
858
+ this.cursor.throwError(parseError);
859
+ }
1225
860
  this.node = null;
1226
861
  }
1227
862
  else {
1228
- this.node = new CompositeNode("repeat-composite", this.name, this.nodes[0].startIndex, this.nodes[this.nodes.length - 1].endIndex);
1229
- this.node.children = this.nodes;
863
+ const value = this.nodes.map((node) => node.value).join("");
864
+ this.node = new Node("repeat", this.name, this.nodes[0].startIndex, this.nodes[this.nodes.length - 1].endIndex, this.nodes, value);
1230
865
  this.cursor.index = this.node.endIndex;
1231
866
  this.cursor.addMatch(this, this.node);
1232
867
  }
1233
868
  }
1234
- clone(name) {
1235
- if (typeof name !== "string") {
869
+ safelyGetCursor() {
870
+ const cursor = this.cursor;
871
+ if (cursor == null) {
872
+ throw new Error("Couldn't find cursor.");
873
+ }
874
+ return cursor;
875
+ }
876
+ clone(name, isOptional) {
877
+ if (name == null) {
1236
878
  name = this.name;
1237
879
  }
1238
- return new RepeatComposite(name, this._pattern, this._divider);
880
+ if (isOptional == null) {
881
+ isOptional = this._isOptional;
882
+ }
883
+ return new Repeat(name, this._pattern, this._divider, isOptional);
1239
884
  }
1240
885
  getTokens() {
1241
886
  return this._pattern.getTokens();
1242
887
  }
1243
888
  }
1244
889
 
1245
- class RecursivePattern extends Pattern {
1246
- constructor(name) {
1247
- super("recursive", name);
890
+ class Recursive extends Pattern {
891
+ constructor(name, isOptional = false) {
892
+ super("recursive", name, [], isOptional);
1248
893
  this.pattern = null;
1249
894
  this.isRecursing = false;
1250
895
  }
1251
896
  getPattern() {
1252
- return this._climb(this.parent, (pattern) => {
897
+ return this.climb(this.parent, (pattern) => {
1253
898
  if (pattern == null) {
1254
899
  return false;
1255
900
  }
1256
901
  return pattern.name === this.name;
1257
902
  });
1258
903
  }
1259
- _climb(pattern, isMatch) {
904
+ climb(pattern, isMatch) {
1260
905
  if (isMatch(pattern)) {
1261
906
  return pattern;
1262
907
  }
1263
908
  else {
1264
909
  if (pattern && pattern.parent != null) {
1265
- return this._climb(pattern.parent, isMatch);
910
+ return this.climb(pattern.parent, isMatch);
1266
911
  }
1267
912
  return null;
1268
913
  }
@@ -1271,23 +916,33 @@ class RecursivePattern extends Pattern {
1271
916
  if (this.pattern == null) {
1272
917
  const pattern = this.getPattern();
1273
918
  if (pattern == null) {
1274
- cursor.throwError(new ParseError(`Couldn't find parent pattern to recursively parse, with the name ${this.name}.`, cursor.index, this));
919
+ if (!this._isOptional) {
920
+ cursor.throwError(new ParseError(`Couldn't find parent pattern to recursively parse, with the name ${this.name}.`, cursor.index, this));
921
+ }
1275
922
  return null;
1276
923
  }
1277
924
  this.pattern = pattern.clone();
1278
925
  this.pattern.parent = this;
1279
926
  }
927
+ const mark = cursor.mark();
1280
928
  const node = this.pattern.parse(cursor);
1281
929
  if (!cursor.hasUnresolvedError() && node != null) {
1282
930
  cursor.addMatch(this, node);
1283
931
  }
932
+ if (cursor.hasUnresolvedError() && this._isOptional) {
933
+ cursor.resolveError();
934
+ cursor.moveToMark(mark);
935
+ }
1284
936
  return node;
1285
937
  }
1286
- clone(name) {
1287
- if (typeof name !== "string") {
938
+ clone(name, isOptional) {
939
+ if (name == null) {
1288
940
  name = this.name;
1289
941
  }
1290
- return new RecursivePattern(name);
942
+ if (isOptional == null) {
943
+ isOptional = this._isOptional;
944
+ }
945
+ return new Recursive(name, isOptional);
1291
946
  }
1292
947
  getTokenValue() {
1293
948
  var _a;
@@ -1305,6 +960,108 @@ class RecursivePattern extends Pattern {
1305
960
  }
1306
961
  }
1307
962
 
963
+ class Reference extends Pattern {
964
+ constructor(name, isOptional = false) {
965
+ super("reference", name, [], isOptional);
966
+ this.isRecursing = false;
967
+ }
968
+ getRoot() {
969
+ let node = this.parent;
970
+ while (node != null) {
971
+ if (node.parent == null) {
972
+ return node;
973
+ }
974
+ node = node.parent;
975
+ }
976
+ return node;
977
+ }
978
+ findPattern() {
979
+ const root = this.getRoot();
980
+ let result = null;
981
+ if (root == null) {
982
+ return null;
983
+ }
984
+ this.walkTheTree(root, (pattern) => {
985
+ if (pattern.name === this.name &&
986
+ pattern != this &&
987
+ pattern.type != "reference") {
988
+ result = pattern;
989
+ return false;
990
+ }
991
+ return true;
992
+ });
993
+ return result;
994
+ }
995
+ walkTheTree(pattern, callback) {
996
+ for (let x = 0; x < pattern.children.length; x++) {
997
+ const p = pattern.children[x];
998
+ const continueWalking = this.walkTheTree(p, callback);
999
+ if (!continueWalking) {
1000
+ return false;
1001
+ }
1002
+ }
1003
+ return callback(pattern);
1004
+ }
1005
+ parse(cursor) {
1006
+ const mark = cursor.mark();
1007
+ try {
1008
+ const node = this.safelyGetPattern().parse(cursor);
1009
+ if (!cursor.hasUnresolvedError() && node != null) {
1010
+ cursor.addMatch(this, node);
1011
+ }
1012
+ if (cursor.hasUnresolvedError() && this._isOptional) {
1013
+ cursor.resolveError();
1014
+ cursor.moveToMark(mark);
1015
+ }
1016
+ return node;
1017
+ }
1018
+ catch (error) {
1019
+ if (this._isOptional) {
1020
+ cursor.moveToMark(mark);
1021
+ }
1022
+ else {
1023
+ cursor.throwError(new ParseError(`Couldn't find reference pattern to parse, with the name ${this.name}.`, cursor.index, this));
1024
+ }
1025
+ return null;
1026
+ }
1027
+ }
1028
+ clone(name, isOptional) {
1029
+ if (name == null) {
1030
+ name = this.name;
1031
+ }
1032
+ if (isOptional == null) {
1033
+ isOptional = this._isOptional;
1034
+ }
1035
+ return new Reference(name, isOptional);
1036
+ }
1037
+ getTokenValue() {
1038
+ return this.safelyGetPattern().getTokenValue();
1039
+ }
1040
+ safelyGetPattern() {
1041
+ let pattern = this.children[0];
1042
+ const hasNoPattern = pattern == null;
1043
+ if (hasNoPattern) {
1044
+ const reference = this.findPattern();
1045
+ if (reference == null) {
1046
+ throw new Error(`Couldn't find reference pattern, with the name ${this.name}.`);
1047
+ }
1048
+ pattern = reference;
1049
+ this.children = [pattern];
1050
+ }
1051
+ return pattern;
1052
+ }
1053
+ getTokens() {
1054
+ if (!this.isRecursing) {
1055
+ this.isRecursing = true;
1056
+ let pattern = this.safelyGetPattern();
1057
+ const tokens = pattern.getTokens();
1058
+ this.isRecursing = false;
1059
+ return tokens;
1060
+ }
1061
+ return [];
1062
+ }
1063
+ }
1064
+
1308
1065
  class TextSuggester {
1309
1066
  constructor() {
1310
1067
  this.cursor = null;
@@ -1556,10 +1313,10 @@ class Visitor {
1556
1313
  }
1557
1314
  flatten() {
1558
1315
  this.selectedNodes.forEach((node) => {
1559
- if (node.isComposite) {
1316
+ if (node.children.length > 0) {
1560
1317
  const children = [];
1561
1318
  Visitor.walkUp(node, (descendant) => {
1562
- if (!descendant.isComposite) {
1319
+ if (descendant.children.length === 0) {
1563
1320
  children.push(descendant);
1564
1321
  }
1565
1322
  });
@@ -1577,15 +1334,13 @@ class Visitor {
1577
1334
  }
1578
1335
  recursiveRemove(node) {
1579
1336
  const nodesToRemove = this.selectedNodes;
1580
- if (node.isComposite && Array.isArray(node.children)) {
1581
- for (let x = 0; x < node.children.length; x++) {
1582
- if (nodesToRemove.indexOf(node.children[x]) > -1) {
1583
- node.children.splice(x, 1);
1584
- x--;
1585
- }
1586
- else {
1587
- this.recursiveRemove(node.children[x]);
1588
- }
1337
+ for (let x = 0; x < node.children.length; x++) {
1338
+ if (nodesToRemove.indexOf(node.children[x]) > -1) {
1339
+ node.children.splice(x, 1);
1340
+ x--;
1341
+ }
1342
+ else {
1343
+ this.recursiveRemove(node.children[x]);
1589
1344
  }
1590
1345
  }
1591
1346
  }
@@ -1658,11 +1413,9 @@ class Visitor {
1658
1413
  return this;
1659
1414
  }
1660
1415
  recursiveTransform(node, callback) {
1661
- if (node.isComposite && Array.isArray(node.children)) {
1662
- const length = node.children.length;
1663
- for (let x = 0; x < length; x++) {
1664
- node.children[x] = this.recursiveTransform(node.children[x], callback);
1665
- }
1416
+ const length = node.children.length;
1417
+ for (let x = 0; x < length; x++) {
1418
+ node.children[x] = this.recursiveTransform(node.children[x], callback);
1666
1419
  }
1667
1420
  return callback(node);
1668
1421
  }
@@ -1682,7 +1435,7 @@ class Visitor {
1682
1435
  }
1683
1436
  const node = this.root;
1684
1437
  const selectedNodes = [];
1685
- if (node.isComposite) {
1438
+ if (node.children.length > 0) {
1686
1439
  Visitor.walkDown(node, (descendant) => {
1687
1440
  if (callback(descendant)) {
1688
1441
  selectedNodes.push(descendant);
@@ -1738,7 +1491,7 @@ class Visitor {
1738
1491
  }
1739
1492
  static walkUp(node, callback, ancestors = []) {
1740
1493
  ancestors.push(node);
1741
- if (node.isComposite && Array.isArray(node.children)) {
1494
+ if (node.children.length > 0) {
1742
1495
  const children = node.children.slice();
1743
1496
  children.forEach((c) => this.walkUp(c, callback, ancestors));
1744
1497
  }
@@ -1749,7 +1502,7 @@ class Visitor {
1749
1502
  static walkDown(node, callback, ancestors = []) {
1750
1503
  callback(node, ancestors);
1751
1504
  ancestors.push(node);
1752
- if (node.isComposite && Array.isArray(node.children)) {
1505
+ if (node.children.length > 0) {
1753
1506
  const children = node.children.slice();
1754
1507
  children.forEach((c) => this.walkDown(c, callback, ancestors));
1755
1508
  }
@@ -1758,27 +1511,19 @@ class Visitor {
1758
1511
  }
1759
1512
  }
1760
1513
 
1761
- exports.AndComposite = AndComposite;
1762
- exports.AndValue = AndValue;
1763
- exports.AnyOfThese = AnyOfThese;
1764
- exports.CompositeNode = CompositeNode;
1765
- exports.CompositePattern = CompositePattern;
1514
+ exports.And = And;
1766
1515
  exports.Cursor = Cursor;
1767
1516
  exports.Literal = Literal;
1517
+ exports.LookAhead = LookAhead;
1768
1518
  exports.Node = Node;
1769
- exports.NotValue = NotValue;
1770
- exports.OptionalComposite = OptionalComposite;
1771
- exports.OptionalValue = OptionalValue;
1772
- exports.OrComposite = OrComposite;
1773
- exports.OrValue = OrValue;
1519
+ exports.Not = Not;
1520
+ exports.Or = Or;
1774
1521
  exports.ParseError = ParseError;
1775
1522
  exports.Pattern = Pattern;
1776
- exports.RecursivePattern = RecursivePattern;
1777
- exports.RegexValue = RegexValue;
1778
- exports.RepeatComposite = RepeatComposite;
1779
- exports.RepeatValue = RepeatValue;
1523
+ exports.Recursive = Recursive;
1524
+ exports.Reference = Reference;
1525
+ exports.Regex = Regex;
1526
+ exports.Repeat = Repeat;
1780
1527
  exports.TextSuggester = TextSuggester;
1781
- exports.ValueNode = ValueNode;
1782
- exports.ValuePattern = ValuePattern;
1783
1528
  exports.Visitor = Visitor;
1784
1529
  //# sourceMappingURL=index.js.map