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