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.esm.js CHANGED
@@ -1,14 +1,4 @@
1
1
  class Node {
2
- constructor(type, name, firstIndex, lastIndex, children = [], value = "") {
3
- this._type = type;
4
- this._name = name;
5
- this._firstIndex = firstIndex;
6
- this._lastIndex = lastIndex;
7
- this._parent = null;
8
- this._children = children;
9
- this._value = value;
10
- this._children.forEach(c => c._parent = this);
11
- }
12
2
  get type() {
13
3
  return this._type;
14
4
  }
@@ -39,6 +29,16 @@ class Node {
39
29
  get value() {
40
30
  return this.toString();
41
31
  }
32
+ constructor(type, name, firstIndex, lastIndex, children = [], value = "") {
33
+ this._type = type;
34
+ this._name = name;
35
+ this._firstIndex = firstIndex;
36
+ this._lastIndex = lastIndex;
37
+ this._parent = null;
38
+ this._children = children;
39
+ this._value = value;
40
+ this._children.forEach(c => c._parent = this);
41
+ }
42
42
  removeChild(node) {
43
43
  const index = this._children.indexOf(node);
44
44
  if (index > -1) {
@@ -176,6 +176,36 @@ class Node {
176
176
  }
177
177
  }
178
178
 
179
+ /******************************************************************************
180
+ Copyright (c) Microsoft Corporation.
181
+
182
+ Permission to use, copy, modify, and/or distribute this software for any
183
+ purpose with or without fee is hereby granted.
184
+
185
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
186
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
187
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
188
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
189
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
190
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
191
+ PERFORMANCE OF THIS SOFTWARE.
192
+ ***************************************************************************** */
193
+
194
+ function __awaiter(thisArg, _arguments, P, generator) {
195
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
196
+ return new (P || (P = Promise))(function (resolve, reject) {
197
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
198
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
199
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
200
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
201
+ });
202
+ }
203
+
204
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
205
+ var e = new Error(message);
206
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
207
+ };
208
+
179
209
  class ParseError {
180
210
  constructor(startIndex, endIndex, pattern) {
181
211
  this.startIndex = startIndex;
@@ -279,12 +309,6 @@ class CursorHistory {
279
309
  }
280
310
 
281
311
  class Cursor {
282
- constructor(text) {
283
- this._text = text;
284
- this._index = 0;
285
- this._length = text.length;
286
- this._history = new CursorHistory();
287
- }
288
312
  get text() {
289
313
  return this._text;
290
314
  }
@@ -327,6 +351,12 @@ class Cursor {
327
351
  get currentChar() {
328
352
  return this._text[this._index];
329
353
  }
354
+ constructor(text) {
355
+ this._text = text;
356
+ this._index = 0;
357
+ this._length = text.length;
358
+ this._history = new CursorHistory();
359
+ }
330
360
  hasNext() {
331
361
  return this._index + 1 < this._length;
332
362
  }
@@ -378,20 +408,6 @@ class Cursor {
378
408
  }
379
409
 
380
410
  class Literal {
381
- constructor(name, value, isOptional = false) {
382
- if (value.length === 0) {
383
- throw new Error("Value Cannot be empty.");
384
- }
385
- this._type = "literal";
386
- this._name = name;
387
- this._literal = value;
388
- this._runes = Array.from(value);
389
- this._isOptional = isOptional;
390
- this._parent = null;
391
- this._firstIndex = 0;
392
- this._lastIndex = 0;
393
- this._endIndex = 0;
394
- }
395
411
  get type() {
396
412
  return this._type;
397
413
  }
@@ -410,6 +426,20 @@ class Literal {
410
426
  get isOptional() {
411
427
  return this._isOptional;
412
428
  }
429
+ constructor(name, value, isOptional = false) {
430
+ if (value.length === 0) {
431
+ throw new Error("Value Cannot be empty.");
432
+ }
433
+ this._type = "literal";
434
+ this._name = name;
435
+ this._literal = value;
436
+ this._runes = Array.from(value);
437
+ this._isOptional = isOptional;
438
+ this._parent = null;
439
+ this._firstIndex = 0;
440
+ this._lastIndex = 0;
441
+ this._endIndex = 0;
442
+ }
413
443
  test(text) {
414
444
  const cursor = new Cursor(text);
415
445
  const ast = this.parse(cursor);
@@ -500,20 +530,6 @@ class Literal {
500
530
  }
501
531
 
502
532
  class Regex {
503
- constructor(name, regex, isOptional = false) {
504
- this._node = null;
505
- this._cursor = null;
506
- this._firstIndex = -1;
507
- this._substring = "";
508
- this._tokens = [];
509
- this._type = "regex";
510
- this._name = name;
511
- this._isOptional = isOptional;
512
- this._parent = null;
513
- this._originalRegexString = regex;
514
- this._regex = new RegExp(`^${regex}`, "g");
515
- this.assertArguments();
516
- }
517
533
  get type() {
518
534
  return this._type;
519
535
  }
@@ -532,6 +548,20 @@ class Regex {
532
548
  get isOptional() {
533
549
  return this._isOptional;
534
550
  }
551
+ constructor(name, regex, isOptional = false) {
552
+ this._node = null;
553
+ this._cursor = null;
554
+ this._firstIndex = -1;
555
+ this._substring = "";
556
+ this._tokens = [];
557
+ this._type = "regex";
558
+ this._name = name;
559
+ this._isOptional = isOptional;
560
+ this._parent = null;
561
+ this._originalRegexString = regex;
562
+ this._regex = new RegExp(`^${regex}`, "g");
563
+ this.assertArguments();
564
+ }
535
565
  assertArguments() {
536
566
  if (this._originalRegexString.length < 1) {
537
567
  throw new Error("Invalid Arguments: The regex string argument needs to be at least one character long.");
@@ -650,14 +680,6 @@ function findPattern(pattern, predicate) {
650
680
  }
651
681
 
652
682
  class Reference {
653
- constructor(name, isOptional = false) {
654
- this._type = "reference";
655
- this._name = name;
656
- this._parent = null;
657
- this._isOptional = isOptional;
658
- this._pattern = null;
659
- this._children = [];
660
- }
661
683
  get type() {
662
684
  return this._type;
663
685
  }
@@ -676,6 +698,14 @@ class Reference {
676
698
  get isOptional() {
677
699
  return this._isOptional;
678
700
  }
701
+ constructor(name, isOptional = false) {
702
+ this._type = "reference";
703
+ this._name = name;
704
+ this._parent = null;
705
+ this._isOptional = isOptional;
706
+ this._pattern = null;
707
+ this._children = [];
708
+ }
679
709
  test(text) {
680
710
  const cursor = new Cursor(text);
681
711
  const ast = this.parse(cursor);
@@ -767,20 +797,6 @@ function clonePatterns(patterns, isOptional) {
767
797
  }
768
798
 
769
799
  class Or {
770
- constructor(name, options, isOptional = false, isGreedy = false) {
771
- if (options.length === 0) {
772
- throw new Error("Need at least one pattern with an 'or' pattern.");
773
- }
774
- const children = clonePatterns(options, false);
775
- this._assignChildrenToParent(children);
776
- this._type = "or";
777
- this._name = name;
778
- this._parent = null;
779
- this._children = children;
780
- this._isOptional = isOptional;
781
- this._firstIndex = 0;
782
- this._isGreedy = isGreedy;
783
- }
784
800
  get type() {
785
801
  return this._type;
786
802
  }
@@ -799,6 +815,20 @@ class Or {
799
815
  get isOptional() {
800
816
  return this._isOptional;
801
817
  }
818
+ constructor(name, options, isOptional = false, isGreedy = false) {
819
+ if (options.length === 0) {
820
+ throw new Error("Need at least one pattern with an 'or' pattern.");
821
+ }
822
+ const children = clonePatterns(options, false);
823
+ this._assignChildrenToParent(children);
824
+ this._type = "or";
825
+ this._name = name;
826
+ this._parent = null;
827
+ this._children = children;
828
+ this._isOptional = isOptional;
829
+ this._firstIndex = 0;
830
+ this._isGreedy = isGreedy;
831
+ }
802
832
  _assignChildrenToParent(children) {
803
833
  for (const child of children) {
804
834
  child.parent = this;
@@ -821,6 +851,7 @@ class Or {
821
851
  this._firstIndex = cursor.index;
822
852
  const node = this._tryToParse(cursor);
823
853
  if (node != null) {
854
+ cursor.moveTo(node.lastIndex);
824
855
  cursor.resolveError();
825
856
  return node;
826
857
  }
@@ -891,28 +922,12 @@ class Or {
891
922
  return findPattern(this, predicate);
892
923
  }
893
924
  clone(name = this._name, isOptional = this._isOptional) {
894
- const or = new Or(name, this._children, isOptional);
925
+ const or = new Or(name, this._children, isOptional, this._isGreedy);
895
926
  return or;
896
927
  }
897
928
  }
898
929
 
899
930
  class FiniteRepeat {
900
- constructor(name, pattern, repeatAmount, options = {}) {
901
- this._type = "finite-repeat";
902
- this._name = name;
903
- this._parent = null;
904
- this._children = [];
905
- this._hasDivider = options.divider != null;
906
- this._min = options.min != null ? options.min : 1;
907
- this._max = repeatAmount;
908
- this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
909
- for (let i = 0; i < repeatAmount; i++) {
910
- this._children.push(pattern.clone(pattern.name));
911
- if (options.divider != null && (i < repeatAmount - 1 || !this._trimDivider)) {
912
- this._children.push(options.divider.clone(options.divider.name, false));
913
- }
914
- }
915
- }
916
931
  get type() {
917
932
  return this._type;
918
933
  }
@@ -937,6 +952,22 @@ class FiniteRepeat {
937
952
  get max() {
938
953
  return this._max;
939
954
  }
955
+ constructor(name, pattern, repeatAmount, options = {}) {
956
+ this._type = "finite-repeat";
957
+ this._name = name;
958
+ this._parent = null;
959
+ this._children = [];
960
+ this._hasDivider = options.divider != null;
961
+ this._min = options.min != null ? options.min : 1;
962
+ this._max = repeatAmount;
963
+ this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
964
+ for (let i = 0; i < repeatAmount; i++) {
965
+ this._children.push(pattern.clone(pattern.name));
966
+ if (options.divider != null && (i < repeatAmount - 1 || !this._trimDivider)) {
967
+ this._children.push(options.divider.clone(options.divider.name, false));
968
+ }
969
+ }
970
+ }
940
971
  parse(cursor) {
941
972
  const startIndex = cursor.index;
942
973
  const nodes = [];
@@ -969,8 +1000,9 @@ class FiniteRepeat {
969
1000
  }
970
1001
  }
971
1002
  if (matchCount < this._min) {
1003
+ const lastIndex = cursor.index;
972
1004
  cursor.moveTo(startIndex);
973
- cursor.recordErrorAt(startIndex, startIndex, this);
1005
+ cursor.recordErrorAt(startIndex, lastIndex, this);
974
1006
  return null;
975
1007
  }
976
1008
  else if (nodes.length === 0) {
@@ -1061,28 +1093,6 @@ class FiniteRepeat {
1061
1093
  }
1062
1094
 
1063
1095
  class InfiniteRepeat {
1064
- constructor(name, pattern, options = {}) {
1065
- const min = options.min != null ? options.min : 1;
1066
- const divider = options.divider;
1067
- let children;
1068
- if (divider != null) {
1069
- children = [pattern.clone(), divider.clone(divider.name, false)];
1070
- }
1071
- else {
1072
- children = [pattern.clone()];
1073
- }
1074
- this._assignChildrenToParent(children);
1075
- this._type = "infinite-repeat";
1076
- this._name = name;
1077
- this._min = min;
1078
- this._parent = null;
1079
- this._children = children;
1080
- this._pattern = children[0];
1081
- this._divider = children[1];
1082
- this._firstIndex = -1;
1083
- this._nodes = [];
1084
- this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
1085
- }
1086
1096
  get type() {
1087
1097
  return this._type;
1088
1098
  }
@@ -1104,6 +1114,28 @@ class InfiniteRepeat {
1104
1114
  get min() {
1105
1115
  return this._min;
1106
1116
  }
1117
+ constructor(name, pattern, options = {}) {
1118
+ const min = options.min != null ? options.min : 1;
1119
+ const divider = options.divider;
1120
+ let children;
1121
+ if (divider != null) {
1122
+ children = [pattern.clone(pattern.name, false), divider.clone(divider.name, false)];
1123
+ }
1124
+ else {
1125
+ children = [pattern.clone(pattern.name, false)];
1126
+ }
1127
+ this._assignChildrenToParent(children);
1128
+ this._type = "infinite-repeat";
1129
+ this._name = name;
1130
+ this._min = min;
1131
+ this._parent = null;
1132
+ this._children = children;
1133
+ this._pattern = children[0];
1134
+ this._divider = children[1];
1135
+ this._firstIndex = -1;
1136
+ this._nodes = [];
1137
+ this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
1138
+ }
1107
1139
  _assignChildrenToParent(children) {
1108
1140
  for (const child of children) {
1109
1141
  child.parent = this;
@@ -1210,6 +1242,10 @@ class InfiniteRepeat {
1210
1242
  const dividerNode = this._nodes.pop();
1211
1243
  cursor.moveTo(dividerNode.firstIndex);
1212
1244
  }
1245
+ // if (this._nodes.length === 0) {
1246
+ // cursor.moveTo(this._firstIndex);
1247
+ // return null;
1248
+ // }
1213
1249
  const lastIndex = this._nodes[this._nodes.length - 1].lastIndex;
1214
1250
  cursor.moveTo(lastIndex);
1215
1251
  return new Node(this._type, this._name, this._firstIndex, lastIndex, this._nodes);
@@ -1297,19 +1333,6 @@ class InfiniteRepeat {
1297
1333
  }
1298
1334
 
1299
1335
  class Repeat {
1300
- constructor(name, pattern, options = {}) {
1301
- this._pattern = pattern;
1302
- this._parent = null;
1303
- this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
1304
- if (this._options.max !== Infinity) {
1305
- this._repeatPattern = new FiniteRepeat(name, pattern, this._options.max, this._options);
1306
- }
1307
- else {
1308
- this._repeatPattern = new InfiniteRepeat(name, pattern, this._options);
1309
- }
1310
- this._children = [this._repeatPattern];
1311
- this._repeatPattern.parent = this;
1312
- }
1313
1336
  get type() {
1314
1337
  return this._repeatPattern.type;
1315
1338
  }
@@ -1328,6 +1351,19 @@ class Repeat {
1328
1351
  get isOptional() {
1329
1352
  return this._repeatPattern.isOptional;
1330
1353
  }
1354
+ constructor(name, pattern, options = {}) {
1355
+ this._pattern = pattern;
1356
+ this._parent = null;
1357
+ this._options = Object.assign(Object.assign({}, options), { min: options.min == null ? 1 : options.min, max: options.max == null ? Infinity : options.max });
1358
+ if (this._options.max !== Infinity) {
1359
+ this._repeatPattern = new FiniteRepeat(name, pattern, this._options.max, this._options);
1360
+ }
1361
+ else {
1362
+ this._repeatPattern = new InfiniteRepeat(name, pattern, this._options);
1363
+ }
1364
+ this._children = [this._repeatPattern];
1365
+ this._repeatPattern.parent = this;
1366
+ }
1331
1367
  parse(cursor) {
1332
1368
  return this._repeatPattern.parse(cursor);
1333
1369
  }
@@ -1397,20 +1433,6 @@ function filterOutNull(nodes) {
1397
1433
  }
1398
1434
 
1399
1435
  class And {
1400
- constructor(name, sequence, isOptional = false) {
1401
- if (sequence.length === 0) {
1402
- throw new Error("Need at least one pattern with an 'and' pattern.");
1403
- }
1404
- const children = clonePatterns(sequence);
1405
- this._assignChildrenToParent(children);
1406
- this._type = "and";
1407
- this._name = name;
1408
- this._isOptional = isOptional;
1409
- this._parent = null;
1410
- this._children = children;
1411
- this._firstIndex = -1;
1412
- this._nodes = [];
1413
- }
1414
1436
  get type() {
1415
1437
  return this._type;
1416
1438
  }
@@ -1429,6 +1451,20 @@ class And {
1429
1451
  get isOptional() {
1430
1452
  return this._isOptional;
1431
1453
  }
1454
+ constructor(name, sequence, isOptional = false) {
1455
+ if (sequence.length === 0) {
1456
+ throw new Error("Need at least one pattern with an 'and' pattern.");
1457
+ }
1458
+ const children = clonePatterns(sequence);
1459
+ this._assignChildrenToParent(children);
1460
+ this._type = "and";
1461
+ this._name = name;
1462
+ this._isOptional = isOptional;
1463
+ this._parent = null;
1464
+ this._children = children;
1465
+ this._firstIndex = -1;
1466
+ this._nodes = [];
1467
+ }
1432
1468
  _assignChildrenToParent(children) {
1433
1469
  for (const child of children) {
1434
1470
  child.parent = this;
@@ -1541,7 +1577,6 @@ class And {
1541
1577
  createNode(cursor) {
1542
1578
  const children = filterOutNull(this._nodes);
1543
1579
  const lastIndex = children[children.length - 1].lastIndex;
1544
- cursor.getChars(this._firstIndex, lastIndex);
1545
1580
  cursor.moveTo(lastIndex);
1546
1581
  return new Node("and", this._name, this._firstIndex, lastIndex, children);
1547
1582
  }
@@ -1583,9 +1618,6 @@ class And {
1583
1618
  let index = -1;
1584
1619
  for (let i = 0; i < this._children.length; i++) {
1585
1620
  if (this._children[i] === childReference) {
1586
- if (i + 1 < this._children.length) {
1587
- this._children[i + 1];
1588
- }
1589
1621
  nextSiblingIndex = i + 1;
1590
1622
  index = i;
1591
1623
  break;
@@ -1627,11 +1659,11 @@ class And {
1627
1659
  }
1628
1660
  }
1629
1661
 
1630
- const name = new Regex("name", "[a-zA-Z_-]+[a-zA-Z0-9_-]*");
1662
+ const name$1 = new Regex("name", "[a-zA-Z_-]+[a-zA-Z0-9_-]*");
1631
1663
 
1632
1664
  const optionalNot = new Literal("not", "!", true);
1633
1665
  const optionalIsOptional$1 = new Literal("is-optional", "?", true);
1634
- const patternName$1 = name.clone("pattern-name");
1666
+ const patternName$1 = name$1.clone("pattern-name");
1635
1667
  const pattern$1 = new And("pattern", [
1636
1668
  optionalNot,
1637
1669
  patternName$1,
@@ -1644,44 +1676,44 @@ const andLiteral = new Repeat("and-literal", pattern$1, { divider: divider$1, mi
1644
1676
 
1645
1677
  const divider = new Regex("or-divider", "\\s*[|]\\s*");
1646
1678
  divider.setTokens([" | "]);
1647
- const orLiteral = new Repeat("or-literal", name.clone("pattern-name"), { divider, min: 2 });
1679
+ const orLiteral = new Repeat("or-literal", name$1.clone("pattern-name"), { divider, min: 2 });
1648
1680
 
1649
1681
  const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1650
1682
 
1651
- const spaces = new Regex("spaces", "[ \\t]+");
1652
- spaces.setTokens([" "]);
1683
+ const spaces$1 = new Regex("spaces", "[ \\t]+");
1684
+ spaces$1.setTokens([" "]);
1653
1685
 
1654
1686
  const optionalIsOptional = new Literal("is-optional", "?", true);
1655
- const patternName = name.clone("pattern-name");
1687
+ const patternName = name$1.clone("pattern-name");
1656
1688
  const pattern = new And("pattern", [
1657
1689
  patternName,
1658
1690
  optionalIsOptional,
1659
1691
  ]);
1660
- const optionalSpaces$1 = spaces.clone("optional-spaces", true);
1661
- const dividerPattern = name.clone("divider-pattern");
1662
- const openBracket = new Literal("open-bracket", "{");
1663
- const closeBracket = new Literal("close-bracket", "}");
1692
+ const optionalSpaces$2 = spaces$1.clone("optional-spaces", true);
1693
+ const dividerPattern = name$1.clone("divider-pattern");
1694
+ const openBracket$1 = new Literal("open-bracket", "{");
1695
+ const closeBracket$1 = new Literal("close-bracket", "}");
1664
1696
  const comma = new Literal("comma", ",");
1665
1697
  const integer = new Regex("integer", "([1-9][0-9]*)|0");
1666
1698
  integer.setTokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
1667
1699
  const optionalInteger = integer.clone("integer", true);
1668
1700
  const bounds = new And("bounds", [
1669
- openBracket,
1670
- optionalSpaces$1,
1701
+ openBracket$1,
1702
+ optionalSpaces$2,
1671
1703
  optionalInteger.clone("min"),
1672
- optionalSpaces$1,
1704
+ optionalSpaces$2,
1673
1705
  comma,
1674
- optionalSpaces$1,
1706
+ optionalSpaces$2,
1675
1707
  optionalInteger.clone("max"),
1676
- optionalSpaces$1,
1677
- closeBracket
1708
+ optionalSpaces$2,
1709
+ closeBracket$1
1678
1710
  ]);
1679
1711
  const exactCount = new And("exact-count", [
1680
- openBracket,
1681
- optionalSpaces$1,
1712
+ openBracket$1,
1713
+ optionalSpaces$2,
1682
1714
  integer,
1683
- optionalSpaces$1,
1684
- closeBracket,
1715
+ optionalSpaces$2,
1716
+ closeBracket$1,
1685
1717
  ]);
1686
1718
  const quantifierShorthand = new Regex("quantifier-shorthand", "\\*|\\+");
1687
1719
  quantifierShorthand.setTokens(["*", "+"]);
@@ -1698,19 +1730,19 @@ const dividerComma = new Regex("divider-comma", "\\s*,\\s*");
1698
1730
  dividerComma.setTokens([", "]);
1699
1731
  const repeatLiteral = new And("repeat-literal", [
1700
1732
  openParen,
1701
- optionalSpaces$1,
1733
+ optionalSpaces$2,
1702
1734
  pattern,
1703
1735
  optional,
1704
1736
  new And("optional-divider-section", [dividerComma, dividerPattern], true),
1705
- optionalSpaces$1,
1737
+ optionalSpaces$2,
1706
1738
  closeParen,
1707
- new And("quantifier-section", [optionalSpaces$1, quantifier]),
1708
- new And("optional-trim-divider-section", [spaces, trimDivider], true)
1739
+ new And("quantifier-section", [optionalSpaces$2, quantifier]),
1740
+ new And("optional-trim-divider-section", [spaces$1, trimDivider], true)
1709
1741
  ]);
1710
1742
 
1711
1743
  const literal = new Regex("literal", "\"(?:\\\\[\"\\\\]|[^\n\"\\\\])*\"");
1712
1744
 
1713
- const optionalSpaces = spaces.clone("optional-spaces", true);
1745
+ const optionalSpaces$1 = spaces$1.clone("optional-spaces", true);
1714
1746
  const assignOperator = new Literal("assign-operator", "=");
1715
1747
  const optionalComment = comment.clone("inline-comment", true);
1716
1748
  const statements = new Or("statements", [
@@ -1719,39 +1751,57 @@ const statements = new Or("statements", [
1719
1751
  orLiteral,
1720
1752
  andLiteral,
1721
1753
  repeatLiteral,
1722
- name.clone("alias-literal"),
1754
+ name$1.clone("alias-literal"),
1723
1755
  ]);
1724
1756
  const statement = new And("statement", [
1725
- optionalSpaces,
1726
- name,
1727
- optionalSpaces,
1757
+ optionalSpaces$1,
1758
+ name$1,
1759
+ optionalSpaces$1,
1728
1760
  assignOperator,
1729
- optionalSpaces,
1761
+ optionalSpaces$1,
1730
1762
  statements,
1731
- optionalSpaces,
1763
+ optionalSpaces$1,
1732
1764
  optionalComment,
1765
+ optionalSpaces$1,
1766
+ ]);
1767
+
1768
+ const spaces = new Regex("spaces", "\\s+", true);
1769
+ const importNameDivider = new Regex("import-name-divider", "(\\s+)?,(\\s+)?");
1770
+ const importKeyword = new Literal("import", "import");
1771
+ const fromKeyword = new Literal("from", "from");
1772
+ const openBracket = new Literal("open-bracket", "{");
1773
+ const closeBracket = new Literal("close-bracket", "}");
1774
+ const name = new Regex("import-name", "[^}\\s,]+");
1775
+ const importedNames = new Repeat("imported-names", name, { divider: importNameDivider });
1776
+ const optionalSpaces = spaces.clone("optional-spaces", true);
1777
+ const importStatement = new And("import-statement", [
1778
+ importKeyword,
1779
+ optionalSpaces,
1780
+ openBracket,
1781
+ optionalSpaces,
1782
+ importedNames,
1733
1783
  optionalSpaces,
1784
+ closeBracket,
1785
+ optionalSpaces,
1786
+ fromKeyword,
1787
+ spaces,
1788
+ literal.clone("url"),
1734
1789
  ]);
1735
1790
 
1736
- const whitespace = new Regex("whitespace", "[ \\t]+");
1791
+ const whitespace = new Regex("whitespace", "[ \\t]+((\\r?\\n)+)?");
1737
1792
  const newLine = new Regex("new-line", "(\\r?\\n)+");
1738
1793
  whitespace.setTokens([" "]);
1739
1794
  newLine.setTokens(["\n"]);
1740
1795
  const line = new Or("line", [
1796
+ newLine,
1797
+ whitespace,
1741
1798
  comment,
1742
- statement,
1743
- whitespace
1744
- ], true);
1745
- const grammar = new Repeat("grammar", line, { divider: newLine });
1799
+ importStatement,
1800
+ statement
1801
+ ]);
1802
+ const grammar = new Repeat("grammer", line);
1746
1803
 
1747
1804
  class Not {
1748
- constructor(name, pattern) {
1749
- this._type = "not";
1750
- this._name = name;
1751
- this._parent = null;
1752
- this._children = [pattern.clone(pattern.name, false)];
1753
- this._children[0].parent = this;
1754
- }
1755
1805
  get type() {
1756
1806
  return this._type;
1757
1807
  }
@@ -1770,6 +1820,13 @@ class Not {
1770
1820
  get isOptional() {
1771
1821
  return false;
1772
1822
  }
1823
+ constructor(name, pattern) {
1824
+ this._type = "not";
1825
+ this._name = name;
1826
+ this._parent = null;
1827
+ this._children = [pattern.clone(pattern.name, false)];
1828
+ this._children[0].parent = this;
1829
+ }
1773
1830
  test(text) {
1774
1831
  const cursor = new Cursor(text);
1775
1832
  this.parse(cursor);
@@ -2039,10 +2096,16 @@ function getFurthestOptions(options) {
2039
2096
  class ParseContext {
2040
2097
  constructor() {
2041
2098
  this.patternsByName = new Map();
2099
+ this.importedPatternsByName = new Map();
2042
2100
  }
2043
2101
  }
2102
+ function defaultImportResolver(_path, _basePath) {
2103
+ throw new Error("No import resolver supplied.");
2104
+ }
2044
2105
  class Grammar {
2045
- constructor() {
2106
+ constructor(options = {}) {
2107
+ this._meta = options.meta == null ? null : options.meta;
2108
+ this._resolveImport = options.resolveImport == null ? defaultImportResolver : options.resolveImport;
2046
2109
  this._parseContext = new ParseContext();
2047
2110
  this._autoComplete = new AutoComplete(grammar, {
2048
2111
  greedyPatternNames: ["spaces", "optional-spaces", "whitespace", "new-line"],
@@ -2054,9 +2117,31 @@ class Grammar {
2054
2117
  }
2055
2118
  });
2056
2119
  }
2120
+ import(path) {
2121
+ return __awaiter(this, void 0, void 0, function* () {
2122
+ const grammarFile = yield this._resolveImport(path, null);
2123
+ const grammar = new Grammar({ resolveImport: this._resolveImport, meta: { originPath: grammarFile.path } });
2124
+ return grammar.parse(grammarFile.expression);
2125
+ });
2126
+ }
2057
2127
  parse(expression) {
2128
+ return __awaiter(this, void 0, void 0, function* () {
2129
+ this._parseContext = new ParseContext();
2130
+ const ast = this._tryToParse(expression);
2131
+ yield this._resolveImports(ast);
2132
+ this._buildPatterns(ast);
2133
+ this._cleanAst(ast);
2134
+ return this._parseContext.patternsByName;
2135
+ });
2136
+ }
2137
+ parseString(expression) {
2058
2138
  this._parseContext = new ParseContext();
2059
- this._tryToParse(expression);
2139
+ const ast = this._tryToParse(expression);
2140
+ if (this._hasImports(ast)) {
2141
+ throw new Error("Cannot use imports on parseString, use parse instead.");
2142
+ }
2143
+ this._buildPatterns(ast);
2144
+ this._cleanAst(ast);
2060
2145
  return this._parseContext.patternsByName;
2061
2146
  }
2062
2147
  _tryToParse(expression) {
@@ -2073,8 +2158,14 @@ class Grammar {
2073
2158
  throw new Error(message);
2074
2159
  }
2075
2160
  // If it is complete it will always have a node. So we have to cast it.
2076
- this._cleanAst(ast);
2077
- this._buildPatterns(ast);
2161
+ return ast;
2162
+ }
2163
+ _hasImports(ast) {
2164
+ const importBlock = ast.find(n => n.name === "import-block");
2165
+ if (importBlock == null) {
2166
+ return false;
2167
+ }
2168
+ return importBlock && importBlock.children.length > 0;
2078
2169
  }
2079
2170
  _cleanAst(ast) {
2080
2171
  ast.findAll(n => n.name === "spaces" ||
@@ -2115,6 +2206,36 @@ class Grammar {
2115
2206
  }
2116
2207
  });
2117
2208
  }
2209
+ _resolveImports(ast) {
2210
+ var _a;
2211
+ return __awaiter(this, void 0, void 0, function* () {
2212
+ const parseContext = this._parseContext;
2213
+ const importStatements = ast.findAll(n => n.name === "import-statement");
2214
+ for (const importStatement of importStatements) {
2215
+ const urlNode = importStatement.find(n => n.name === "url");
2216
+ const url = urlNode.value.slice(1, -1);
2217
+ const grammarFile = yield this._resolveImport(url, ((_a = this._meta) === null || _a === void 0 ? void 0 : _a.originPath) || null);
2218
+ const grammar = new Grammar({ resolveImport: this._resolveImport, meta: { originPath: grammarFile.path } });
2219
+ try {
2220
+ const patterns = yield grammar.parse(grammarFile.expression);
2221
+ const importNames = importStatement.findAll(n => n.name === "import-name").map(n => n.value);
2222
+ importNames.forEach((importName) => {
2223
+ if (parseContext.importedPatternsByName.has(importName)) {
2224
+ throw new Error(`'${importName}' was already used within another import.`);
2225
+ }
2226
+ const pattern = patterns.get(importName);
2227
+ if (pattern == null) {
2228
+ throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${url}.`);
2229
+ }
2230
+ parseContext.importedPatternsByName.set(importName, pattern);
2231
+ });
2232
+ }
2233
+ catch (e) {
2234
+ throw new Error(`Failed loading expression from: "${url}". Error details: "${e.message}"`);
2235
+ }
2236
+ }
2237
+ });
2238
+ }
2118
2239
  _buildLiteral(statementNode) {
2119
2240
  const nameNode = statementNode.find(n => n.name === "name");
2120
2241
  const literalNode = statementNode.find(n => n.name === "literal");
@@ -2134,14 +2255,17 @@ class Grammar {
2134
2255
  _buildOr(statementNode) {
2135
2256
  const nameNode = statementNode.find(n => n.name === "name");
2136
2257
  const orNode = statementNode.find(n => n.name === "or-literal");
2137
- const patternNodes = orNode.children.filter(n => n.name == "pattern-name");
2258
+ const patternNodes = orNode.children.filter(n => n.name === "pattern-name");
2138
2259
  const name = nameNode.value;
2139
2260
  const patterns = patternNodes.map(n => this._getPattern(n.value));
2140
- const or = new Or(name, patterns);
2261
+ const or = new Or(name, patterns, false, true);
2141
2262
  this._parseContext.patternsByName.set(name, or);
2142
2263
  }
2143
2264
  _getPattern(name) {
2144
- const pattern = this._parseContext.patternsByName.get(name);
2265
+ let pattern = this._parseContext.patternsByName.get(name);
2266
+ if (pattern == null) {
2267
+ pattern = this._parseContext.importedPatternsByName.get(name);
2268
+ }
2145
2269
  if (pattern == null) {
2146
2270
  return new Reference(name);
2147
2271
  }
@@ -2150,7 +2274,7 @@ class Grammar {
2150
2274
  _buildAnd(statementNode) {
2151
2275
  const nameNode = statementNode.find(n => n.name === "name");
2152
2276
  const andNode = statementNode.find(n => n.name === "and-literal");
2153
- const patternNodes = andNode.children.filter(n => n.name == "pattern");
2277
+ const patternNodes = andNode.children.filter(n => n.name === "pattern");
2154
2278
  const name = nameNode.value;
2155
2279
  const patterns = patternNodes.map(n => {
2156
2280
  const nameNode = n.find(n => n.name === "pattern-name");
@@ -2169,7 +2293,7 @@ class Grammar {
2169
2293
  _buildRepeat(statementNode) {
2170
2294
  const nameNode = statementNode.find(n => n.name === "name");
2171
2295
  const repeatNode = statementNode.find(n => n.name === "repeat-literal");
2172
- const patternNode = repeatNode.find(n => n.name == "pattern");
2296
+ const patternNode = repeatNode.find(n => n.name === "pattern");
2173
2297
  const patternNameNode = patternNode.find(n => n.name === "pattern-name");
2174
2298
  const dividerNode = repeatNode.find(n => n.name === "divider-pattern");
2175
2299
  const bounds = repeatNode.find(n => n.name === "bounds");
@@ -2226,10 +2350,18 @@ class Grammar {
2226
2350
  const alias = pattern.clone(name);
2227
2351
  this._parseContext.patternsByName.set(name, alias);
2228
2352
  }
2229
- static parse(expression) {
2230
- const grammar = new Grammar();
2353
+ static parse(expression, options) {
2354
+ const grammar = new Grammar(options);
2231
2355
  return grammar.parse(expression);
2232
2356
  }
2357
+ static import(path, options) {
2358
+ const grammar = new Grammar(options);
2359
+ return grammar.import(path);
2360
+ }
2361
+ static parseString(expression) {
2362
+ const grammar = new Grammar();
2363
+ return grammar.parseString(expression);
2364
+ }
2233
2365
  }
2234
2366
 
2235
2367
  export { And, AutoComplete, Cursor, CursorHistory, Grammar, Literal, Node, Not, Or, ParseError, Reference, Regex, Repeat };