clarity-pattern-parser 8.2.1 → 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
@@ -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;
@@ -970,8 +1000,9 @@ class FiniteRepeat {
970
1000
  }
971
1001
  }
972
1002
  if (matchCount < this._min) {
1003
+ const lastIndex = cursor.index;
973
1004
  cursor.moveTo(startIndex);
974
- cursor.recordErrorAt(startIndex, startIndex, this);
1005
+ cursor.recordErrorAt(startIndex, lastIndex, this);
975
1006
  return null;
976
1007
  }
977
1008
  else if (nodes.length === 0) {
@@ -1088,10 +1119,10 @@ class InfiniteRepeat {
1088
1119
  const divider = options.divider;
1089
1120
  let children;
1090
1121
  if (divider != null) {
1091
- children = [pattern.clone(), divider.clone(divider.name, false)];
1122
+ children = [pattern.clone(pattern.name, false), divider.clone(divider.name, false)];
1092
1123
  }
1093
1124
  else {
1094
- children = [pattern.clone()];
1125
+ children = [pattern.clone(pattern.name, false)];
1095
1126
  }
1096
1127
  this._assignChildrenToParent(children);
1097
1128
  this._type = "infinite-repeat";
@@ -1211,6 +1242,10 @@ class InfiniteRepeat {
1211
1242
  const dividerNode = this._nodes.pop();
1212
1243
  cursor.moveTo(dividerNode.firstIndex);
1213
1244
  }
1245
+ // if (this._nodes.length === 0) {
1246
+ // cursor.moveTo(this._firstIndex);
1247
+ // return null;
1248
+ // }
1214
1249
  const lastIndex = this._nodes[this._nodes.length - 1].lastIndex;
1215
1250
  cursor.moveTo(lastIndex);
1216
1251
  return new Node(this._type, this._name, this._firstIndex, lastIndex, this._nodes);
@@ -1542,7 +1577,6 @@ class And {
1542
1577
  createNode(cursor) {
1543
1578
  const children = filterOutNull(this._nodes);
1544
1579
  const lastIndex = children[children.length - 1].lastIndex;
1545
- cursor.getChars(this._firstIndex, lastIndex);
1546
1580
  cursor.moveTo(lastIndex);
1547
1581
  return new Node("and", this._name, this._firstIndex, lastIndex, children);
1548
1582
  }
@@ -1584,9 +1618,6 @@ class And {
1584
1618
  let index = -1;
1585
1619
  for (let i = 0; i < this._children.length; i++) {
1586
1620
  if (this._children[i] === childReference) {
1587
- if (i + 1 < this._children.length) {
1588
- this._children[i + 1];
1589
- }
1590
1621
  nextSiblingIndex = i + 1;
1591
1622
  index = i;
1592
1623
  break;
@@ -1628,11 +1659,11 @@ class And {
1628
1659
  }
1629
1660
  }
1630
1661
 
1631
- 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_-]*");
1632
1663
 
1633
1664
  const optionalNot = new Literal("not", "!", true);
1634
1665
  const optionalIsOptional$1 = new Literal("is-optional", "?", true);
1635
- const patternName$1 = name.clone("pattern-name");
1666
+ const patternName$1 = name$1.clone("pattern-name");
1636
1667
  const pattern$1 = new And("pattern", [
1637
1668
  optionalNot,
1638
1669
  patternName$1,
@@ -1645,44 +1676,44 @@ const andLiteral = new Repeat("and-literal", pattern$1, { divider: divider$1, mi
1645
1676
 
1646
1677
  const divider = new Regex("or-divider", "\\s*[|]\\s*");
1647
1678
  divider.setTokens([" | "]);
1648
- 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 });
1649
1680
 
1650
1681
  const regexLiteral = new Regex("regex-literal", "/(\\\\/|[^/\\n\\r])*/");
1651
1682
 
1652
- const spaces = new Regex("spaces", "[ \\t]+");
1653
- spaces.setTokens([" "]);
1683
+ const spaces$1 = new Regex("spaces", "[ \\t]+");
1684
+ spaces$1.setTokens([" "]);
1654
1685
 
1655
1686
  const optionalIsOptional = new Literal("is-optional", "?", true);
1656
- const patternName = name.clone("pattern-name");
1687
+ const patternName = name$1.clone("pattern-name");
1657
1688
  const pattern = new And("pattern", [
1658
1689
  patternName,
1659
1690
  optionalIsOptional,
1660
1691
  ]);
1661
- const optionalSpaces$1 = spaces.clone("optional-spaces", true);
1662
- const dividerPattern = name.clone("divider-pattern");
1663
- const openBracket = new Literal("open-bracket", "{");
1664
- 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", "}");
1665
1696
  const comma = new Literal("comma", ",");
1666
1697
  const integer = new Regex("integer", "([1-9][0-9]*)|0");
1667
1698
  integer.setTokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
1668
1699
  const optionalInteger = integer.clone("integer", true);
1669
1700
  const bounds = new And("bounds", [
1670
- openBracket,
1671
- optionalSpaces$1,
1701
+ openBracket$1,
1702
+ optionalSpaces$2,
1672
1703
  optionalInteger.clone("min"),
1673
- optionalSpaces$1,
1704
+ optionalSpaces$2,
1674
1705
  comma,
1675
- optionalSpaces$1,
1706
+ optionalSpaces$2,
1676
1707
  optionalInteger.clone("max"),
1677
- optionalSpaces$1,
1678
- closeBracket
1708
+ optionalSpaces$2,
1709
+ closeBracket$1
1679
1710
  ]);
1680
1711
  const exactCount = new And("exact-count", [
1681
- openBracket,
1682
- optionalSpaces$1,
1712
+ openBracket$1,
1713
+ optionalSpaces$2,
1683
1714
  integer,
1684
- optionalSpaces$1,
1685
- closeBracket,
1715
+ optionalSpaces$2,
1716
+ closeBracket$1,
1686
1717
  ]);
1687
1718
  const quantifierShorthand = new Regex("quantifier-shorthand", "\\*|\\+");
1688
1719
  quantifierShorthand.setTokens(["*", "+"]);
@@ -1699,19 +1730,19 @@ const dividerComma = new Regex("divider-comma", "\\s*,\\s*");
1699
1730
  dividerComma.setTokens([", "]);
1700
1731
  const repeatLiteral = new And("repeat-literal", [
1701
1732
  openParen,
1702
- optionalSpaces$1,
1733
+ optionalSpaces$2,
1703
1734
  pattern,
1704
1735
  optional,
1705
1736
  new And("optional-divider-section", [dividerComma, dividerPattern], true),
1706
- optionalSpaces$1,
1737
+ optionalSpaces$2,
1707
1738
  closeParen,
1708
- new And("quantifier-section", [optionalSpaces$1, quantifier]),
1709
- 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)
1710
1741
  ]);
1711
1742
 
1712
1743
  const literal = new Regex("literal", "\"(?:\\\\[\"\\\\]|[^\n\"\\\\])*\"");
1713
1744
 
1714
- const optionalSpaces = spaces.clone("optional-spaces", true);
1745
+ const optionalSpaces$1 = spaces$1.clone("optional-spaces", true);
1715
1746
  const assignOperator = new Literal("assign-operator", "=");
1716
1747
  const optionalComment = comment.clone("inline-comment", true);
1717
1748
  const statements = new Or("statements", [
@@ -1720,30 +1751,55 @@ const statements = new Or("statements", [
1720
1751
  orLiteral,
1721
1752
  andLiteral,
1722
1753
  repeatLiteral,
1723
- name.clone("alias-literal"),
1754
+ name$1.clone("alias-literal"),
1724
1755
  ]);
1725
1756
  const statement = new And("statement", [
1726
- optionalSpaces,
1727
- name,
1728
- optionalSpaces,
1757
+ optionalSpaces$1,
1758
+ name$1,
1759
+ optionalSpaces$1,
1729
1760
  assignOperator,
1730
- optionalSpaces,
1761
+ optionalSpaces$1,
1731
1762
  statements,
1732
- optionalSpaces,
1763
+ optionalSpaces$1,
1733
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,
1734
1781
  optionalSpaces,
1782
+ importedNames,
1783
+ optionalSpaces,
1784
+ closeBracket,
1785
+ optionalSpaces,
1786
+ fromKeyword,
1787
+ spaces,
1788
+ literal.clone("url"),
1735
1789
  ]);
1736
1790
 
1737
- const whitespace = new Regex("whitespace", "[ \\t]+");
1791
+ const whitespace = new Regex("whitespace", "[ \\t]+((\\r?\\n)+)?");
1738
1792
  const newLine = new Regex("new-line", "(\\r?\\n)+");
1739
1793
  whitespace.setTokens([" "]);
1740
1794
  newLine.setTokens(["\n"]);
1741
1795
  const line = new Or("line", [
1796
+ newLine,
1797
+ whitespace,
1742
1798
  comment,
1743
- statement,
1744
- whitespace
1745
- ], true);
1746
- const grammar = new Repeat("grammar", line, { divider: newLine });
1799
+ importStatement,
1800
+ statement
1801
+ ]);
1802
+ const grammar = new Repeat("grammer", line);
1747
1803
 
1748
1804
  class Not {
1749
1805
  get type() {
@@ -2040,10 +2096,16 @@ function getFurthestOptions(options) {
2040
2096
  class ParseContext {
2041
2097
  constructor() {
2042
2098
  this.patternsByName = new Map();
2099
+ this.importedPatternsByName = new Map();
2043
2100
  }
2044
2101
  }
2102
+ function defaultImportResolver(_path, _basePath) {
2103
+ throw new Error("No import resolver supplied.");
2104
+ }
2045
2105
  class Grammar {
2046
- constructor() {
2106
+ constructor(options = {}) {
2107
+ this._meta = options.meta == null ? null : options.meta;
2108
+ this._resolveImport = options.resolveImport == null ? defaultImportResolver : options.resolveImport;
2047
2109
  this._parseContext = new ParseContext();
2048
2110
  this._autoComplete = new AutoComplete(grammar, {
2049
2111
  greedyPatternNames: ["spaces", "optional-spaces", "whitespace", "new-line"],
@@ -2055,9 +2117,31 @@ class Grammar {
2055
2117
  }
2056
2118
  });
2057
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
+ }
2058
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) {
2059
2138
  this._parseContext = new ParseContext();
2060
- 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);
2061
2145
  return this._parseContext.patternsByName;
2062
2146
  }
2063
2147
  _tryToParse(expression) {
@@ -2074,8 +2158,14 @@ class Grammar {
2074
2158
  throw new Error(message);
2075
2159
  }
2076
2160
  // If it is complete it will always have a node. So we have to cast it.
2077
- this._cleanAst(ast);
2078
- 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;
2079
2169
  }
2080
2170
  _cleanAst(ast) {
2081
2171
  ast.findAll(n => n.name === "spaces" ||
@@ -2116,6 +2206,36 @@ class Grammar {
2116
2206
  }
2117
2207
  });
2118
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
+ }
2119
2239
  _buildLiteral(statementNode) {
2120
2240
  const nameNode = statementNode.find(n => n.name === "name");
2121
2241
  const literalNode = statementNode.find(n => n.name === "literal");
@@ -2142,7 +2262,10 @@ class Grammar {
2142
2262
  this._parseContext.patternsByName.set(name, or);
2143
2263
  }
2144
2264
  _getPattern(name) {
2145
- 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
+ }
2146
2269
  if (pattern == null) {
2147
2270
  return new Reference(name);
2148
2271
  }
@@ -2227,10 +2350,18 @@ class Grammar {
2227
2350
  const alias = pattern.clone(name);
2228
2351
  this._parseContext.patternsByName.set(name, alias);
2229
2352
  }
2230
- static parse(expression) {
2231
- const grammar = new Grammar();
2353
+ static parse(expression, options) {
2354
+ const grammar = new Grammar(options);
2232
2355
  return grammar.parse(expression);
2233
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
+ }
2234
2365
  }
2235
2366
 
2236
2367
  export { And, AutoComplete, Cursor, CursorHistory, Grammar, Literal, Node, Not, Or, ParseError, Reference, Regex, Repeat };