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