clarity-pattern-parser 8.2.1 → 8.3.1

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
@@ -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;
@@ -974,8 +1004,9 @@ class FiniteRepeat {
974
1004
  }
975
1005
  }
976
1006
  if (matchCount < this._min) {
1007
+ const lastIndex = cursor.index;
977
1008
  cursor.moveTo(startIndex);
978
- cursor.recordErrorAt(startIndex, startIndex, this);
1009
+ cursor.recordErrorAt(startIndex, lastIndex, this);
979
1010
  return null;
980
1011
  }
981
1012
  else if (nodes.length === 0) {
@@ -1092,10 +1123,10 @@ class InfiniteRepeat {
1092
1123
  const divider = options.divider;
1093
1124
  let children;
1094
1125
  if (divider != null) {
1095
- children = [pattern.clone(), divider.clone(divider.name, false)];
1126
+ children = [pattern.clone(pattern.name, false), divider.clone(divider.name, false)];
1096
1127
  }
1097
1128
  else {
1098
- children = [pattern.clone()];
1129
+ children = [pattern.clone(pattern.name, false)];
1099
1130
  }
1100
1131
  this._assignChildrenToParent(children);
1101
1132
  this._type = "infinite-repeat";
@@ -1215,6 +1246,10 @@ class InfiniteRepeat {
1215
1246
  const dividerNode = this._nodes.pop();
1216
1247
  cursor.moveTo(dividerNode.firstIndex);
1217
1248
  }
1249
+ // if (this._nodes.length === 0) {
1250
+ // cursor.moveTo(this._firstIndex);
1251
+ // return null;
1252
+ // }
1218
1253
  const lastIndex = this._nodes[this._nodes.length - 1].lastIndex;
1219
1254
  cursor.moveTo(lastIndex);
1220
1255
  return new Node(this._type, this._name, this._firstIndex, lastIndex, this._nodes);
@@ -1546,7 +1581,6 @@ class And {
1546
1581
  createNode(cursor) {
1547
1582
  const children = filterOutNull(this._nodes);
1548
1583
  const lastIndex = children[children.length - 1].lastIndex;
1549
- cursor.getChars(this._firstIndex, lastIndex);
1550
1584
  cursor.moveTo(lastIndex);
1551
1585
  return new Node("and", this._name, this._firstIndex, lastIndex, children);
1552
1586
  }
@@ -1588,9 +1622,6 @@ class And {
1588
1622
  let index = -1;
1589
1623
  for (let i = 0; i < this._children.length; i++) {
1590
1624
  if (this._children[i] === childReference) {
1591
- if (i + 1 < this._children.length) {
1592
- this._children[i + 1];
1593
- }
1594
1625
  nextSiblingIndex = i + 1;
1595
1626
  index = i;
1596
1627
  break;
@@ -1632,11 +1663,11 @@ class And {
1632
1663
  }
1633
1664
  }
1634
1665
 
1635
- 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_-]*");
1636
1667
 
1637
1668
  const optionalNot = new Literal("not", "!", true);
1638
1669
  const optionalIsOptional$1 = new Literal("is-optional", "?", true);
1639
- const patternName$1 = name.clone("pattern-name");
1670
+ const patternName$1 = name$1.clone("pattern-name");
1640
1671
  const pattern$1 = new And("pattern", [
1641
1672
  optionalNot,
1642
1673
  patternName$1,
@@ -1649,44 +1680,44 @@ const andLiteral = new Repeat("and-literal", pattern$1, { divider: divider$1, mi
1649
1680
 
1650
1681
  const divider = new Regex("or-divider", "\\s*[|]\\s*");
1651
1682
  divider.setTokens([" | "]);
1652
- 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 });
1653
1684
 
1654
1685
  const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1655
1686
 
1656
- const spaces = new Regex("spaces", "[ \\t]+");
1657
- spaces.setTokens([" "]);
1687
+ const spaces$1 = new Regex("spaces", "[ \\t]+");
1688
+ spaces$1.setTokens([" "]);
1658
1689
 
1659
1690
  const optionalIsOptional = new Literal("is-optional", "?", true);
1660
- const patternName = name.clone("pattern-name");
1691
+ const patternName = name$1.clone("pattern-name");
1661
1692
  const pattern = new And("pattern", [
1662
1693
  patternName,
1663
1694
  optionalIsOptional,
1664
1695
  ]);
1665
- const optionalSpaces$1 = spaces.clone("optional-spaces", true);
1666
- const dividerPattern = name.clone("divider-pattern");
1667
- const openBracket = new Literal("open-bracket", "{");
1668
- 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", "}");
1669
1700
  const comma = new Literal("comma", ",");
1670
1701
  const integer = new Regex("integer", "([1-9][0-9]*)|0");
1671
1702
  integer.setTokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
1672
1703
  const optionalInteger = integer.clone("integer", true);
1673
1704
  const bounds = new And("bounds", [
1674
- openBracket,
1675
- optionalSpaces$1,
1705
+ openBracket$1,
1706
+ optionalSpaces$2,
1676
1707
  optionalInteger.clone("min"),
1677
- optionalSpaces$1,
1708
+ optionalSpaces$2,
1678
1709
  comma,
1679
- optionalSpaces$1,
1710
+ optionalSpaces$2,
1680
1711
  optionalInteger.clone("max"),
1681
- optionalSpaces$1,
1682
- closeBracket
1712
+ optionalSpaces$2,
1713
+ closeBracket$1
1683
1714
  ]);
1684
1715
  const exactCount = new And("exact-count", [
1685
- openBracket,
1686
- optionalSpaces$1,
1716
+ openBracket$1,
1717
+ optionalSpaces$2,
1687
1718
  integer,
1688
- optionalSpaces$1,
1689
- closeBracket,
1719
+ optionalSpaces$2,
1720
+ closeBracket$1,
1690
1721
  ]);
1691
1722
  const quantifierShorthand = new Regex("quantifier-shorthand", "\\*|\\+");
1692
1723
  quantifierShorthand.setTokens(["*", "+"]);
@@ -1703,19 +1734,19 @@ const dividerComma = new Regex("divider-comma", "\\s*,\\s*");
1703
1734
  dividerComma.setTokens([", "]);
1704
1735
  const repeatLiteral = new And("repeat-literal", [
1705
1736
  openParen,
1706
- optionalSpaces$1,
1737
+ optionalSpaces$2,
1707
1738
  pattern,
1708
1739
  optional,
1709
1740
  new And("optional-divider-section", [dividerComma, dividerPattern], true),
1710
- optionalSpaces$1,
1741
+ optionalSpaces$2,
1711
1742
  closeParen,
1712
- new And("quantifier-section", [optionalSpaces$1, quantifier]),
1713
- 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)
1714
1745
  ]);
1715
1746
 
1716
1747
  const literal = new Regex("literal", "\"(?:\\\\[\"\\\\]|[^\n\"\\\\])*\"");
1717
1748
 
1718
- const optionalSpaces = spaces.clone("optional-spaces", true);
1749
+ const optionalSpaces$1 = spaces$1.clone("optional-spaces", true);
1719
1750
  const assignOperator = new Literal("assign-operator", "=");
1720
1751
  const optionalComment = comment.clone("inline-comment", true);
1721
1752
  const statements = new Or("statements", [
@@ -1724,30 +1755,55 @@ const statements = new Or("statements", [
1724
1755
  orLiteral,
1725
1756
  andLiteral,
1726
1757
  repeatLiteral,
1727
- name.clone("alias-literal"),
1758
+ name$1.clone("alias-literal"),
1728
1759
  ]);
1729
1760
  const statement = new And("statement", [
1730
- optionalSpaces,
1731
- name,
1732
- optionalSpaces,
1761
+ optionalSpaces$1,
1762
+ name$1,
1763
+ optionalSpaces$1,
1733
1764
  assignOperator,
1734
- optionalSpaces,
1765
+ optionalSpaces$1,
1735
1766
  statements,
1736
- optionalSpaces,
1767
+ optionalSpaces$1,
1737
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,
1738
1785
  optionalSpaces,
1786
+ importedNames,
1787
+ optionalSpaces,
1788
+ closeBracket,
1789
+ optionalSpaces,
1790
+ fromKeyword,
1791
+ spaces,
1792
+ literal.clone("url"),
1739
1793
  ]);
1740
1794
 
1741
- const whitespace = new Regex("whitespace", "[ \\t]+");
1795
+ const whitespace = new Regex("whitespace", "[ \\t]+((\\r?\\n)+)?");
1742
1796
  const newLine = new Regex("new-line", "(\\r?\\n)+");
1743
1797
  whitespace.setTokens([" "]);
1744
1798
  newLine.setTokens(["\n"]);
1745
1799
  const line = new Or("line", [
1800
+ newLine,
1801
+ whitespace,
1746
1802
  comment,
1747
- statement,
1748
- whitespace
1749
- ], true);
1750
- const grammar = new Repeat("grammar", line, { divider: newLine });
1803
+ importStatement,
1804
+ statement
1805
+ ]);
1806
+ const grammar = new Repeat("grammer", line);
1751
1807
 
1752
1808
  class Not {
1753
1809
  get type() {
@@ -2044,10 +2100,16 @@ function getFurthestOptions(options) {
2044
2100
  class ParseContext {
2045
2101
  constructor() {
2046
2102
  this.patternsByName = new Map();
2103
+ this.importedPatternsByName = new Map();
2047
2104
  }
2048
2105
  }
2106
+ function defaultImportResolver(_path, _basePath) {
2107
+ throw new Error("No import resolver supplied.");
2108
+ }
2049
2109
  class Grammar {
2050
- constructor() {
2110
+ constructor(options = {}) {
2111
+ this._meta = options.meta == null ? null : options.meta;
2112
+ this._resolveImport = options.resolveImport == null ? defaultImportResolver : options.resolveImport;
2051
2113
  this._parseContext = new ParseContext();
2052
2114
  this._autoComplete = new AutoComplete(grammar, {
2053
2115
  greedyPatternNames: ["spaces", "optional-spaces", "whitespace", "new-line"],
@@ -2059,9 +2121,31 @@ class Grammar {
2059
2121
  }
2060
2122
  });
2061
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
+ }
2062
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) {
2063
2142
  this._parseContext = new ParseContext();
2064
- 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);
2065
2149
  return this._parseContext.patternsByName;
2066
2150
  }
2067
2151
  _tryToParse(expression) {
@@ -2078,8 +2162,14 @@ class Grammar {
2078
2162
  throw new Error(message);
2079
2163
  }
2080
2164
  // If it is complete it will always have a node. So we have to cast it.
2081
- this._cleanAst(ast);
2082
- 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;
2083
2173
  }
2084
2174
  _cleanAst(ast) {
2085
2175
  ast.findAll(n => n.name === "spaces" ||
@@ -2120,6 +2210,36 @@ class Grammar {
2120
2210
  }
2121
2211
  });
2122
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
+ }
2123
2243
  _buildLiteral(statementNode) {
2124
2244
  const nameNode = statementNode.find(n => n.name === "name");
2125
2245
  const literalNode = statementNode.find(n => n.name === "literal");
@@ -2146,7 +2266,10 @@ class Grammar {
2146
2266
  this._parseContext.patternsByName.set(name, or);
2147
2267
  }
2148
2268
  _getPattern(name) {
2149
- 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
+ }
2150
2273
  if (pattern == null) {
2151
2274
  return new Reference(name);
2152
2275
  }
@@ -2231,10 +2354,18 @@ class Grammar {
2231
2354
  const alias = pattern.clone(name);
2232
2355
  this._parseContext.patternsByName.set(name, alias);
2233
2356
  }
2234
- static parse(expression) {
2235
- const grammar = new Grammar();
2357
+ static parse(expression, options) {
2358
+ const grammar = new Grammar(options);
2236
2359
  return grammar.parse(expression);
2237
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
+ }
2238
2369
  }
2239
2370
 
2240
2371
  exports.And = And;
@@ -2250,4 +2381,5 @@ exports.ParseError = ParseError;
2250
2381
  exports.Reference = Reference;
2251
2382
  exports.Regex = Regex;
2252
2383
  exports.Repeat = Repeat;
2384
+ exports.grammar = grammar;
2253
2385
  //# sourceMappingURL=index.js.map