clarity-pattern-parser 8.2.0 → 8.3.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.
package/dist/index.js CHANGED
@@ -3,16 +3,6 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  class Node {
6
- constructor(type, name, firstIndex, lastIndex, children = [], value = "") {
7
- this._type = type;
8
- this._name = name;
9
- this._firstIndex = firstIndex;
10
- this._lastIndex = lastIndex;
11
- this._parent = null;
12
- this._children = children;
13
- this._value = value;
14
- this._children.forEach(c => c._parent = this);
15
- }
16
6
  get type() {
17
7
  return this._type;
18
8
  }
@@ -43,6 +33,16 @@ class Node {
43
33
  get value() {
44
34
  return this.toString();
45
35
  }
36
+ constructor(type, name, firstIndex, lastIndex, children = [], value = "") {
37
+ this._type = type;
38
+ this._name = name;
39
+ this._firstIndex = firstIndex;
40
+ this._lastIndex = lastIndex;
41
+ this._parent = null;
42
+ this._children = children;
43
+ this._value = value;
44
+ this._children.forEach(c => c._parent = this);
45
+ }
46
46
  removeChild(node) {
47
47
  const index = this._children.indexOf(node);
48
48
  if (index > -1) {
@@ -180,6 +180,36 @@ class Node {
180
180
  }
181
181
  }
182
182
 
183
+ /******************************************************************************
184
+ Copyright (c) Microsoft Corporation.
185
+
186
+ Permission to use, copy, modify, and/or distribute this software for any
187
+ purpose with or without fee is hereby granted.
188
+
189
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
190
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
191
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
192
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
193
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
194
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
195
+ PERFORMANCE OF THIS SOFTWARE.
196
+ ***************************************************************************** */
197
+
198
+ function __awaiter(thisArg, _arguments, P, generator) {
199
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
200
+ return new (P || (P = Promise))(function (resolve, reject) {
201
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
202
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
203
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
204
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
205
+ });
206
+ }
207
+
208
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
209
+ var e = new Error(message);
210
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
211
+ };
212
+
183
213
  class ParseError {
184
214
  constructor(startIndex, endIndex, pattern) {
185
215
  this.startIndex = startIndex;
@@ -283,12 +313,6 @@ class CursorHistory {
283
313
  }
284
314
 
285
315
  class Cursor {
286
- constructor(text) {
287
- this._text = text;
288
- this._index = 0;
289
- this._length = text.length;
290
- this._history = new CursorHistory();
291
- }
292
316
  get text() {
293
317
  return this._text;
294
318
  }
@@ -331,6 +355,12 @@ class Cursor {
331
355
  get currentChar() {
332
356
  return this._text[this._index];
333
357
  }
358
+ constructor(text) {
359
+ this._text = text;
360
+ this._index = 0;
361
+ this._length = text.length;
362
+ this._history = new CursorHistory();
363
+ }
334
364
  hasNext() {
335
365
  return this._index + 1 < this._length;
336
366
  }
@@ -382,20 +412,6 @@ class Cursor {
382
412
  }
383
413
 
384
414
  class Literal {
385
- constructor(name, value, isOptional = false) {
386
- if (value.length === 0) {
387
- throw new Error("Value Cannot be empty.");
388
- }
389
- this._type = "literal";
390
- this._name = name;
391
- this._literal = value;
392
- this._runes = Array.from(value);
393
- this._isOptional = isOptional;
394
- this._parent = null;
395
- this._firstIndex = 0;
396
- this._lastIndex = 0;
397
- this._endIndex = 0;
398
- }
399
415
  get type() {
400
416
  return this._type;
401
417
  }
@@ -414,6 +430,20 @@ class Literal {
414
430
  get isOptional() {
415
431
  return this._isOptional;
416
432
  }
433
+ constructor(name, value, isOptional = false) {
434
+ if (value.length === 0) {
435
+ throw new Error("Value Cannot be empty.");
436
+ }
437
+ this._type = "literal";
438
+ this._name = name;
439
+ this._literal = value;
440
+ this._runes = Array.from(value);
441
+ this._isOptional = isOptional;
442
+ this._parent = null;
443
+ this._firstIndex = 0;
444
+ this._lastIndex = 0;
445
+ this._endIndex = 0;
446
+ }
417
447
  test(text) {
418
448
  const cursor = new Cursor(text);
419
449
  const ast = this.parse(cursor);
@@ -504,20 +534,6 @@ class Literal {
504
534
  }
505
535
 
506
536
  class Regex {
507
- constructor(name, regex, isOptional = false) {
508
- this._node = null;
509
- this._cursor = null;
510
- this._firstIndex = -1;
511
- this._substring = "";
512
- this._tokens = [];
513
- this._type = "regex";
514
- this._name = name;
515
- this._isOptional = isOptional;
516
- this._parent = null;
517
- this._originalRegexString = regex;
518
- this._regex = new RegExp(`^${regex}`, "g");
519
- this.assertArguments();
520
- }
521
537
  get type() {
522
538
  return this._type;
523
539
  }
@@ -536,6 +552,20 @@ class Regex {
536
552
  get isOptional() {
537
553
  return this._isOptional;
538
554
  }
555
+ constructor(name, regex, isOptional = false) {
556
+ this._node = null;
557
+ this._cursor = null;
558
+ this._firstIndex = -1;
559
+ this._substring = "";
560
+ this._tokens = [];
561
+ this._type = "regex";
562
+ this._name = name;
563
+ this._isOptional = isOptional;
564
+ this._parent = null;
565
+ this._originalRegexString = regex;
566
+ this._regex = new RegExp(`^${regex}`, "g");
567
+ this.assertArguments();
568
+ }
539
569
  assertArguments() {
540
570
  if (this._originalRegexString.length < 1) {
541
571
  throw new Error("Invalid Arguments: The regex string argument needs to be at least one character long.");
@@ -654,14 +684,6 @@ function findPattern(pattern, predicate) {
654
684
  }
655
685
 
656
686
  class Reference {
657
- constructor(name, isOptional = false) {
658
- this._type = "reference";
659
- this._name = name;
660
- this._parent = null;
661
- this._isOptional = isOptional;
662
- this._pattern = null;
663
- this._children = [];
664
- }
665
687
  get type() {
666
688
  return this._type;
667
689
  }
@@ -680,6 +702,14 @@ class Reference {
680
702
  get isOptional() {
681
703
  return this._isOptional;
682
704
  }
705
+ constructor(name, isOptional = false) {
706
+ this._type = "reference";
707
+ this._name = name;
708
+ this._parent = null;
709
+ this._isOptional = isOptional;
710
+ this._pattern = null;
711
+ this._children = [];
712
+ }
683
713
  test(text) {
684
714
  const cursor = new Cursor(text);
685
715
  const ast = this.parse(cursor);
@@ -771,20 +801,6 @@ function clonePatterns(patterns, isOptional) {
771
801
  }
772
802
 
773
803
  class Or {
774
- constructor(name, options, isOptional = false, isGreedy = false) {
775
- if (options.length === 0) {
776
- throw new Error("Need at least one pattern with an 'or' pattern.");
777
- }
778
- const children = clonePatterns(options, false);
779
- this._assignChildrenToParent(children);
780
- this._type = "or";
781
- this._name = name;
782
- this._parent = null;
783
- this._children = children;
784
- this._isOptional = isOptional;
785
- this._firstIndex = 0;
786
- this._isGreedy = isGreedy;
787
- }
788
804
  get type() {
789
805
  return this._type;
790
806
  }
@@ -803,6 +819,20 @@ class Or {
803
819
  get isOptional() {
804
820
  return this._isOptional;
805
821
  }
822
+ constructor(name, options, isOptional = false, isGreedy = false) {
823
+ if (options.length === 0) {
824
+ throw new Error("Need at least one pattern with an 'or' pattern.");
825
+ }
826
+ const children = clonePatterns(options, false);
827
+ this._assignChildrenToParent(children);
828
+ this._type = "or";
829
+ this._name = name;
830
+ this._parent = null;
831
+ this._children = children;
832
+ this._isOptional = isOptional;
833
+ this._firstIndex = 0;
834
+ this._isGreedy = isGreedy;
835
+ }
806
836
  _assignChildrenToParent(children) {
807
837
  for (const child of children) {
808
838
  child.parent = this;
@@ -825,6 +855,7 @@ class Or {
825
855
  this._firstIndex = cursor.index;
826
856
  const node = this._tryToParse(cursor);
827
857
  if (node != null) {
858
+ cursor.moveTo(node.lastIndex);
828
859
  cursor.resolveError();
829
860
  return node;
830
861
  }
@@ -895,28 +926,12 @@ class Or {
895
926
  return findPattern(this, predicate);
896
927
  }
897
928
  clone(name = this._name, isOptional = this._isOptional) {
898
- const or = new Or(name, this._children, isOptional);
929
+ const or = new Or(name, this._children, isOptional, this._isGreedy);
899
930
  return or;
900
931
  }
901
932
  }
902
933
 
903
934
  class FiniteRepeat {
904
- constructor(name, pattern, repeatAmount, options = {}) {
905
- this._type = "finite-repeat";
906
- this._name = name;
907
- this._parent = null;
908
- this._children = [];
909
- this._hasDivider = options.divider != null;
910
- this._min = options.min != null ? options.min : 1;
911
- this._max = repeatAmount;
912
- this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
913
- for (let i = 0; i < repeatAmount; i++) {
914
- this._children.push(pattern.clone(pattern.name));
915
- if (options.divider != null && (i < repeatAmount - 1 || !this._trimDivider)) {
916
- this._children.push(options.divider.clone(options.divider.name, false));
917
- }
918
- }
919
- }
920
935
  get type() {
921
936
  return this._type;
922
937
  }
@@ -941,6 +956,22 @@ class FiniteRepeat {
941
956
  get max() {
942
957
  return this._max;
943
958
  }
959
+ constructor(name, pattern, repeatAmount, options = {}) {
960
+ this._type = "finite-repeat";
961
+ this._name = name;
962
+ this._parent = null;
963
+ this._children = [];
964
+ this._hasDivider = options.divider != null;
965
+ this._min = options.min != null ? options.min : 1;
966
+ this._max = repeatAmount;
967
+ this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
968
+ for (let i = 0; i < repeatAmount; i++) {
969
+ this._children.push(pattern.clone(pattern.name));
970
+ if (options.divider != null && (i < repeatAmount - 1 || !this._trimDivider)) {
971
+ this._children.push(options.divider.clone(options.divider.name, false));
972
+ }
973
+ }
974
+ }
944
975
  parse(cursor) {
945
976
  const startIndex = cursor.index;
946
977
  const nodes = [];
@@ -973,8 +1004,9 @@ class FiniteRepeat {
973
1004
  }
974
1005
  }
975
1006
  if (matchCount < this._min) {
1007
+ const lastIndex = cursor.index;
976
1008
  cursor.moveTo(startIndex);
977
- cursor.recordErrorAt(startIndex, startIndex, this);
1009
+ cursor.recordErrorAt(startIndex, lastIndex, this);
978
1010
  return null;
979
1011
  }
980
1012
  else if (nodes.length === 0) {
@@ -1065,28 +1097,6 @@ class FiniteRepeat {
1065
1097
  }
1066
1098
 
1067
1099
  class InfiniteRepeat {
1068
- constructor(name, pattern, options = {}) {
1069
- const min = options.min != null ? options.min : 1;
1070
- const divider = options.divider;
1071
- let children;
1072
- if (divider != null) {
1073
- children = [pattern.clone(), divider.clone(divider.name, false)];
1074
- }
1075
- else {
1076
- children = [pattern.clone()];
1077
- }
1078
- this._assignChildrenToParent(children);
1079
- this._type = "infinite-repeat";
1080
- this._name = name;
1081
- this._min = min;
1082
- this._parent = null;
1083
- this._children = children;
1084
- this._pattern = children[0];
1085
- this._divider = children[1];
1086
- this._firstIndex = -1;
1087
- this._nodes = [];
1088
- this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
1089
- }
1090
1100
  get type() {
1091
1101
  return this._type;
1092
1102
  }
@@ -1108,6 +1118,28 @@ class InfiniteRepeat {
1108
1118
  get min() {
1109
1119
  return this._min;
1110
1120
  }
1121
+ constructor(name, pattern, options = {}) {
1122
+ const min = options.min != null ? options.min : 1;
1123
+ const divider = options.divider;
1124
+ let children;
1125
+ if (divider != null) {
1126
+ children = [pattern.clone(pattern.name, false), divider.clone(divider.name, false)];
1127
+ }
1128
+ else {
1129
+ children = [pattern.clone(pattern.name, false)];
1130
+ }
1131
+ this._assignChildrenToParent(children);
1132
+ this._type = "infinite-repeat";
1133
+ this._name = name;
1134
+ this._min = min;
1135
+ this._parent = null;
1136
+ this._children = children;
1137
+ this._pattern = children[0];
1138
+ this._divider = children[1];
1139
+ this._firstIndex = -1;
1140
+ this._nodes = [];
1141
+ this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
1142
+ }
1111
1143
  _assignChildrenToParent(children) {
1112
1144
  for (const child of children) {
1113
1145
  child.parent = this;
@@ -1214,6 +1246,10 @@ class InfiniteRepeat {
1214
1246
  const dividerNode = this._nodes.pop();
1215
1247
  cursor.moveTo(dividerNode.firstIndex);
1216
1248
  }
1249
+ // if (this._nodes.length === 0) {
1250
+ // cursor.moveTo(this._firstIndex);
1251
+ // return null;
1252
+ // }
1217
1253
  const lastIndex = this._nodes[this._nodes.length - 1].lastIndex;
1218
1254
  cursor.moveTo(lastIndex);
1219
1255
  return new Node(this._type, this._name, this._firstIndex, lastIndex, this._nodes);
@@ -1301,19 +1337,6 @@ class InfiniteRepeat {
1301
1337
  }
1302
1338
 
1303
1339
  class Repeat {
1304
- constructor(name, pattern, options = {}) {
1305
- this._pattern = pattern;
1306
- this._parent = null;
1307
- this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
1308
- if (this._options.max !== Infinity) {
1309
- this._repeatPattern = new FiniteRepeat(name, pattern, this._options.max, this._options);
1310
- }
1311
- else {
1312
- this._repeatPattern = new InfiniteRepeat(name, pattern, this._options);
1313
- }
1314
- this._children = [this._repeatPattern];
1315
- this._repeatPattern.parent = this;
1316
- }
1317
1340
  get type() {
1318
1341
  return this._repeatPattern.type;
1319
1342
  }
@@ -1332,6 +1355,19 @@ class Repeat {
1332
1355
  get isOptional() {
1333
1356
  return this._repeatPattern.isOptional;
1334
1357
  }
1358
+ constructor(name, pattern, options = {}) {
1359
+ this._pattern = pattern;
1360
+ this._parent = null;
1361
+ this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
1362
+ if (this._options.max !== Infinity) {
1363
+ this._repeatPattern = new FiniteRepeat(name, pattern, this._options.max, this._options);
1364
+ }
1365
+ else {
1366
+ this._repeatPattern = new InfiniteRepeat(name, pattern, this._options);
1367
+ }
1368
+ this._children = [this._repeatPattern];
1369
+ this._repeatPattern.parent = this;
1370
+ }
1335
1371
  parse(cursor) {
1336
1372
  return this._repeatPattern.parse(cursor);
1337
1373
  }
@@ -1401,20 +1437,6 @@ function filterOutNull(nodes) {
1401
1437
  }
1402
1438
 
1403
1439
  class And {
1404
- constructor(name, sequence, isOptional = false) {
1405
- if (sequence.length === 0) {
1406
- throw new Error("Need at least one pattern with an 'and' pattern.");
1407
- }
1408
- const children = clonePatterns(sequence);
1409
- this._assignChildrenToParent(children);
1410
- this._type = "and";
1411
- this._name = name;
1412
- this._isOptional = isOptional;
1413
- this._parent = null;
1414
- this._children = children;
1415
- this._firstIndex = -1;
1416
- this._nodes = [];
1417
- }
1418
1440
  get type() {
1419
1441
  return this._type;
1420
1442
  }
@@ -1433,6 +1455,20 @@ class And {
1433
1455
  get isOptional() {
1434
1456
  return this._isOptional;
1435
1457
  }
1458
+ constructor(name, sequence, isOptional = false) {
1459
+ if (sequence.length === 0) {
1460
+ throw new Error("Need at least one pattern with an 'and' pattern.");
1461
+ }
1462
+ const children = clonePatterns(sequence);
1463
+ this._assignChildrenToParent(children);
1464
+ this._type = "and";
1465
+ this._name = name;
1466
+ this._isOptional = isOptional;
1467
+ this._parent = null;
1468
+ this._children = children;
1469
+ this._firstIndex = -1;
1470
+ this._nodes = [];
1471
+ }
1436
1472
  _assignChildrenToParent(children) {
1437
1473
  for (const child of children) {
1438
1474
  child.parent = this;
@@ -1545,7 +1581,6 @@ class And {
1545
1581
  createNode(cursor) {
1546
1582
  const children = filterOutNull(this._nodes);
1547
1583
  const lastIndex = children[children.length - 1].lastIndex;
1548
- cursor.getChars(this._firstIndex, lastIndex);
1549
1584
  cursor.moveTo(lastIndex);
1550
1585
  return new Node("and", this._name, this._firstIndex, lastIndex, children);
1551
1586
  }
@@ -1587,9 +1622,6 @@ class And {
1587
1622
  let index = -1;
1588
1623
  for (let i = 0; i < this._children.length; i++) {
1589
1624
  if (this._children[i] === childReference) {
1590
- if (i + 1 < this._children.length) {
1591
- this._children[i + 1];
1592
- }
1593
1625
  nextSiblingIndex = i + 1;
1594
1626
  index = i;
1595
1627
  break;
@@ -1631,11 +1663,11 @@ class And {
1631
1663
  }
1632
1664
  }
1633
1665
 
1634
- const name = new Regex("name", "[a-zA-Z_-]+[a-zA-Z0-9_-]*");
1666
+ const name$1 = new Regex("name", "[a-zA-Z_-]+[a-zA-Z0-9_-]*");
1635
1667
 
1636
1668
  const optionalNot = new Literal("not", "!", true);
1637
1669
  const optionalIsOptional$1 = new Literal("is-optional", "?", true);
1638
- const patternName$1 = name.clone("pattern-name");
1670
+ const patternName$1 = name$1.clone("pattern-name");
1639
1671
  const pattern$1 = new And("pattern", [
1640
1672
  optionalNot,
1641
1673
  patternName$1,
@@ -1648,44 +1680,44 @@ const andLiteral = new Repeat("and-literal", pattern$1, { divider: divider$1, mi
1648
1680
 
1649
1681
  const divider = new Regex("or-divider", "\\s*[|]\\s*");
1650
1682
  divider.setTokens([" | "]);
1651
- const orLiteral = new Repeat("or-literal", name.clone("pattern-name"), { divider, min: 2 });
1683
+ const orLiteral = new Repeat("or-literal", name$1.clone("pattern-name"), { divider, min: 2 });
1652
1684
 
1653
1685
  const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1654
1686
 
1655
- const spaces = new Regex("spaces", "[ \\t]+");
1656
- spaces.setTokens([" "]);
1687
+ const spaces$1 = new Regex("spaces", "[ \\t]+");
1688
+ spaces$1.setTokens([" "]);
1657
1689
 
1658
1690
  const optionalIsOptional = new Literal("is-optional", "?", true);
1659
- const patternName = name.clone("pattern-name");
1691
+ const patternName = name$1.clone("pattern-name");
1660
1692
  const pattern = new And("pattern", [
1661
1693
  patternName,
1662
1694
  optionalIsOptional,
1663
1695
  ]);
1664
- const optionalSpaces$1 = spaces.clone("optional-spaces", true);
1665
- const dividerPattern = name.clone("divider-pattern");
1666
- const openBracket = new Literal("open-bracket", "{");
1667
- const closeBracket = new Literal("close-bracket", "}");
1696
+ const optionalSpaces$2 = spaces$1.clone("optional-spaces", true);
1697
+ const dividerPattern = name$1.clone("divider-pattern");
1698
+ const openBracket$1 = new Literal("open-bracket", "{");
1699
+ const closeBracket$1 = new Literal("close-bracket", "}");
1668
1700
  const comma = new Literal("comma", ",");
1669
1701
  const integer = new Regex("integer", "([1-9][0-9]*)|0");
1670
1702
  integer.setTokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
1671
1703
  const optionalInteger = integer.clone("integer", true);
1672
1704
  const bounds = new And("bounds", [
1673
- openBracket,
1674
- optionalSpaces$1,
1705
+ openBracket$1,
1706
+ optionalSpaces$2,
1675
1707
  optionalInteger.clone("min"),
1676
- optionalSpaces$1,
1708
+ optionalSpaces$2,
1677
1709
  comma,
1678
- optionalSpaces$1,
1710
+ optionalSpaces$2,
1679
1711
  optionalInteger.clone("max"),
1680
- optionalSpaces$1,
1681
- closeBracket
1712
+ optionalSpaces$2,
1713
+ closeBracket$1
1682
1714
  ]);
1683
1715
  const exactCount = new And("exact-count", [
1684
- openBracket,
1685
- optionalSpaces$1,
1716
+ openBracket$1,
1717
+ optionalSpaces$2,
1686
1718
  integer,
1687
- optionalSpaces$1,
1688
- closeBracket,
1719
+ optionalSpaces$2,
1720
+ closeBracket$1,
1689
1721
  ]);
1690
1722
  const quantifierShorthand = new Regex("quantifier-shorthand", "\\*|\\+");
1691
1723
  quantifierShorthand.setTokens(["*", "+"]);
@@ -1702,19 +1734,19 @@ const dividerComma = new Regex("divider-comma", "\\s*,\\s*");
1702
1734
  dividerComma.setTokens([", "]);
1703
1735
  const repeatLiteral = new And("repeat-literal", [
1704
1736
  openParen,
1705
- optionalSpaces$1,
1737
+ optionalSpaces$2,
1706
1738
  pattern,
1707
1739
  optional,
1708
1740
  new And("optional-divider-section", [dividerComma, dividerPattern], true),
1709
- optionalSpaces$1,
1741
+ optionalSpaces$2,
1710
1742
  closeParen,
1711
- new And("quantifier-section", [optionalSpaces$1, quantifier]),
1712
- new And("optional-trim-divider-section", [spaces, trimDivider], true)
1743
+ new And("quantifier-section", [optionalSpaces$2, quantifier]),
1744
+ new And("optional-trim-divider-section", [spaces$1, trimDivider], true)
1713
1745
  ]);
1714
1746
 
1715
1747
  const literal = new Regex("literal", "\"(?:\\\\[\"\\\\]|[^\n\"\\\\])*\"");
1716
1748
 
1717
- const optionalSpaces = spaces.clone("optional-spaces", true);
1749
+ const optionalSpaces$1 = spaces$1.clone("optional-spaces", true);
1718
1750
  const assignOperator = new Literal("assign-operator", "=");
1719
1751
  const optionalComment = comment.clone("inline-comment", true);
1720
1752
  const statements = new Or("statements", [
@@ -1723,39 +1755,57 @@ const statements = new Or("statements", [
1723
1755
  orLiteral,
1724
1756
  andLiteral,
1725
1757
  repeatLiteral,
1726
- name.clone("alias-literal"),
1758
+ name$1.clone("alias-literal"),
1727
1759
  ]);
1728
1760
  const statement = new And("statement", [
1729
- optionalSpaces,
1730
- name,
1731
- optionalSpaces,
1761
+ optionalSpaces$1,
1762
+ name$1,
1763
+ optionalSpaces$1,
1732
1764
  assignOperator,
1733
- optionalSpaces,
1765
+ optionalSpaces$1,
1734
1766
  statements,
1735
- optionalSpaces,
1767
+ optionalSpaces$1,
1736
1768
  optionalComment,
1769
+ optionalSpaces$1,
1770
+ ]);
1771
+
1772
+ const spaces = new Regex("spaces", "\\s+", true);
1773
+ const importNameDivider = new Regex("import-name-divider", "(\\s+)?,(\\s+)?");
1774
+ const importKeyword = new Literal("import", "import");
1775
+ const fromKeyword = new Literal("from", "from");
1776
+ const openBracket = new Literal("open-bracket", "{");
1777
+ const closeBracket = new Literal("close-bracket", "}");
1778
+ const name = new Regex("import-name", "[^}\\s,]+");
1779
+ const importedNames = new Repeat("imported-names", name, { divider: importNameDivider });
1780
+ const optionalSpaces = spaces.clone("optional-spaces", true);
1781
+ const importStatement = new And("import-statement", [
1782
+ importKeyword,
1783
+ optionalSpaces,
1784
+ openBracket,
1785
+ optionalSpaces,
1786
+ importedNames,
1737
1787
  optionalSpaces,
1788
+ closeBracket,
1789
+ optionalSpaces,
1790
+ fromKeyword,
1791
+ spaces,
1792
+ literal.clone("url"),
1738
1793
  ]);
1739
1794
 
1740
- const whitespace = new Regex("whitespace", "[ \\t]+");
1795
+ const whitespace = new Regex("whitespace", "[ \\t]+((\\r?\\n)+)?");
1741
1796
  const newLine = new Regex("new-line", "(\\r?\\n)+");
1742
1797
  whitespace.setTokens([" "]);
1743
1798
  newLine.setTokens(["\n"]);
1744
1799
  const line = new Or("line", [
1800
+ newLine,
1801
+ whitespace,
1745
1802
  comment,
1746
- statement,
1747
- whitespace
1748
- ], true);
1749
- const grammar = new Repeat("grammar", line, { divider: newLine });
1803
+ importStatement,
1804
+ statement
1805
+ ]);
1806
+ const grammar = new Repeat("grammer", line);
1750
1807
 
1751
1808
  class Not {
1752
- constructor(name, pattern) {
1753
- this._type = "not";
1754
- this._name = name;
1755
- this._parent = null;
1756
- this._children = [pattern.clone(pattern.name, false)];
1757
- this._children[0].parent = this;
1758
- }
1759
1809
  get type() {
1760
1810
  return this._type;
1761
1811
  }
@@ -1774,6 +1824,13 @@ class Not {
1774
1824
  get isOptional() {
1775
1825
  return false;
1776
1826
  }
1827
+ constructor(name, pattern) {
1828
+ this._type = "not";
1829
+ this._name = name;
1830
+ this._parent = null;
1831
+ this._children = [pattern.clone(pattern.name, false)];
1832
+ this._children[0].parent = this;
1833
+ }
1777
1834
  test(text) {
1778
1835
  const cursor = new Cursor(text);
1779
1836
  this.parse(cursor);
@@ -2043,10 +2100,16 @@ function getFurthestOptions(options) {
2043
2100
  class ParseContext {
2044
2101
  constructor() {
2045
2102
  this.patternsByName = new Map();
2103
+ this.importedPatternsByName = new Map();
2046
2104
  }
2047
2105
  }
2106
+ function defaultImportResolver(_path, _basePath) {
2107
+ throw new Error("No import resolver supplied.");
2108
+ }
2048
2109
  class Grammar {
2049
- constructor() {
2110
+ constructor(options = {}) {
2111
+ this._meta = options.meta == null ? null : options.meta;
2112
+ this._resolveImport = options.resolveImport == null ? defaultImportResolver : options.resolveImport;
2050
2113
  this._parseContext = new ParseContext();
2051
2114
  this._autoComplete = new AutoComplete(grammar, {
2052
2115
  greedyPatternNames: ["spaces", "optional-spaces", "whitespace", "new-line"],
@@ -2058,9 +2121,31 @@ class Grammar {
2058
2121
  }
2059
2122
  });
2060
2123
  }
2124
+ import(path) {
2125
+ return __awaiter(this, void 0, void 0, function* () {
2126
+ const grammarFile = yield this._resolveImport(path, null);
2127
+ const grammar = new Grammar({ resolveImport: this._resolveImport, meta: { originPath: grammarFile.path } });
2128
+ return grammar.parse(grammarFile.expression);
2129
+ });
2130
+ }
2061
2131
  parse(expression) {
2132
+ return __awaiter(this, void 0, void 0, function* () {
2133
+ this._parseContext = new ParseContext();
2134
+ const ast = this._tryToParse(expression);
2135
+ yield this._resolveImports(ast);
2136
+ this._buildPatterns(ast);
2137
+ this._cleanAst(ast);
2138
+ return this._parseContext.patternsByName;
2139
+ });
2140
+ }
2141
+ parseString(expression) {
2062
2142
  this._parseContext = new ParseContext();
2063
- this._tryToParse(expression);
2143
+ const ast = this._tryToParse(expression);
2144
+ if (this._hasImports(ast)) {
2145
+ throw new Error("Cannot use imports on parseString, use parse instead.");
2146
+ }
2147
+ this._buildPatterns(ast);
2148
+ this._cleanAst(ast);
2064
2149
  return this._parseContext.patternsByName;
2065
2150
  }
2066
2151
  _tryToParse(expression) {
@@ -2077,8 +2162,14 @@ class Grammar {
2077
2162
  throw new Error(message);
2078
2163
  }
2079
2164
  // If it is complete it will always have a node. So we have to cast it.
2080
- this._cleanAst(ast);
2081
- this._buildPatterns(ast);
2165
+ return ast;
2166
+ }
2167
+ _hasImports(ast) {
2168
+ const importBlock = ast.find(n => n.name === "import-block");
2169
+ if (importBlock == null) {
2170
+ return false;
2171
+ }
2172
+ return importBlock && importBlock.children.length > 0;
2082
2173
  }
2083
2174
  _cleanAst(ast) {
2084
2175
  ast.findAll(n => n.name === "spaces" ||
@@ -2119,6 +2210,36 @@ class Grammar {
2119
2210
  }
2120
2211
  });
2121
2212
  }
2213
+ _resolveImports(ast) {
2214
+ var _a;
2215
+ return __awaiter(this, void 0, void 0, function* () {
2216
+ const parseContext = this._parseContext;
2217
+ const importStatements = ast.findAll(n => n.name === "import-statement");
2218
+ for (const importStatement of importStatements) {
2219
+ const urlNode = importStatement.find(n => n.name === "url");
2220
+ const url = urlNode.value.slice(1, -1);
2221
+ const grammarFile = yield this._resolveImport(url, ((_a = this._meta) === null || _a === void 0 ? void 0 : _a.originPath) || null);
2222
+ const grammar = new Grammar({ resolveImport: this._resolveImport, meta: { originPath: grammarFile.path } });
2223
+ try {
2224
+ const patterns = yield grammar.parse(grammarFile.expression);
2225
+ const importNames = importStatement.findAll(n => n.name === "import-name").map(n => n.value);
2226
+ importNames.forEach((importName) => {
2227
+ if (parseContext.importedPatternsByName.has(importName)) {
2228
+ throw new Error(`'${importName}' was already used within another import.`);
2229
+ }
2230
+ const pattern = patterns.get(importName);
2231
+ if (pattern == null) {
2232
+ throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${url}.`);
2233
+ }
2234
+ parseContext.importedPatternsByName.set(importName, pattern);
2235
+ });
2236
+ }
2237
+ catch (e) {
2238
+ throw new Error(`Failed loading expression from: "${url}". Error details: "${e.message}"`);
2239
+ }
2240
+ }
2241
+ });
2242
+ }
2122
2243
  _buildLiteral(statementNode) {
2123
2244
  const nameNode = statementNode.find(n => n.name === "name");
2124
2245
  const literalNode = statementNode.find(n => n.name === "literal");
@@ -2138,14 +2259,17 @@ class Grammar {
2138
2259
  _buildOr(statementNode) {
2139
2260
  const nameNode = statementNode.find(n => n.name === "name");
2140
2261
  const orNode = statementNode.find(n => n.name === "or-literal");
2141
- const patternNodes = orNode.children.filter(n => n.name == "pattern-name");
2262
+ const patternNodes = orNode.children.filter(n => n.name === "pattern-name");
2142
2263
  const name = nameNode.value;
2143
2264
  const patterns = patternNodes.map(n => this._getPattern(n.value));
2144
- const or = new Or(name, patterns);
2265
+ const or = new Or(name, patterns, false, true);
2145
2266
  this._parseContext.patternsByName.set(name, or);
2146
2267
  }
2147
2268
  _getPattern(name) {
2148
- const pattern = this._parseContext.patternsByName.get(name);
2269
+ let pattern = this._parseContext.patternsByName.get(name);
2270
+ if (pattern == null) {
2271
+ pattern = this._parseContext.importedPatternsByName.get(name);
2272
+ }
2149
2273
  if (pattern == null) {
2150
2274
  return new Reference(name);
2151
2275
  }
@@ -2154,7 +2278,7 @@ class Grammar {
2154
2278
  _buildAnd(statementNode) {
2155
2279
  const nameNode = statementNode.find(n => n.name === "name");
2156
2280
  const andNode = statementNode.find(n => n.name === "and-literal");
2157
- const patternNodes = andNode.children.filter(n => n.name == "pattern");
2281
+ const patternNodes = andNode.children.filter(n => n.name === "pattern");
2158
2282
  const name = nameNode.value;
2159
2283
  const patterns = patternNodes.map(n => {
2160
2284
  const nameNode = n.find(n => n.name === "pattern-name");
@@ -2173,7 +2297,7 @@ class Grammar {
2173
2297
  _buildRepeat(statementNode) {
2174
2298
  const nameNode = statementNode.find(n => n.name === "name");
2175
2299
  const repeatNode = statementNode.find(n => n.name === "repeat-literal");
2176
- const patternNode = repeatNode.find(n => n.name == "pattern");
2300
+ const patternNode = repeatNode.find(n => n.name === "pattern");
2177
2301
  const patternNameNode = patternNode.find(n => n.name === "pattern-name");
2178
2302
  const dividerNode = repeatNode.find(n => n.name === "divider-pattern");
2179
2303
  const bounds = repeatNode.find(n => n.name === "bounds");
@@ -2230,10 +2354,18 @@ class Grammar {
2230
2354
  const alias = pattern.clone(name);
2231
2355
  this._parseContext.patternsByName.set(name, alias);
2232
2356
  }
2233
- static parse(expression) {
2234
- const grammar = new Grammar();
2357
+ static parse(expression, options) {
2358
+ const grammar = new Grammar(options);
2235
2359
  return grammar.parse(expression);
2236
2360
  }
2361
+ static import(path, options) {
2362
+ const grammar = new Grammar(options);
2363
+ return grammar.import(path);
2364
+ }
2365
+ static parseString(expression) {
2366
+ const grammar = new Grammar();
2367
+ return grammar.parseString(expression);
2368
+ }
2237
2369
  }
2238
2370
 
2239
2371
  exports.And = And;