clarity-pattern-parser 11.0.26 → 11.0.27

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/TODO.md CHANGED
@@ -1,7 +1,4 @@
1
- * Fix infinite repeat recursion with a reference
2
-
3
-
4
- * Generate typescript files from cpat
1
+ * Fix Grammar with alias reference, by adding an additional parameter to the constructor of Reference to be the name and then the cloned name of the pattern eventually found.
5
2
 
6
3
  * We should make a Block, Segments Pattern. These will be breadth first patterns. It look something like this.
7
4
 
@@ -852,10 +852,11 @@
852
852
  get startedOnIndex() {
853
853
  return this._firstIndex;
854
854
  }
855
- constructor(name) {
855
+ constructor(name, referencePatternName) {
856
856
  this._id = `reference-${idIndex$7++}`;
857
857
  this._type = "reference";
858
858
  this._name = name;
859
+ this._referencePatternName = referencePatternName || name;
859
860
  this._parent = null;
860
861
  this._pattern = null;
861
862
  this._cachedPattern = null;
@@ -914,7 +915,7 @@
914
915
  pattern = this._cachedPattern;
915
916
  }
916
917
  if (pattern === null) {
917
- throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
918
+ throw new Error(`Couldn't find '${this._referencePatternName}' pattern within tree.`);
918
919
  }
919
920
  const clonedPattern = pattern.clone();
920
921
  clonedPattern.parent = this;
@@ -930,7 +931,7 @@
930
931
  pattern = pattern.parent;
931
932
  continue;
932
933
  }
933
- const foundPattern = pattern.getPatternWithinContext(this.name);
934
+ const foundPattern = pattern.getPatternWithinContext(this._referencePatternName);
934
935
  if (foundPattern != null && this._isValidPattern(foundPattern)) {
935
936
  return foundPattern;
936
937
  }
@@ -938,7 +939,7 @@
938
939
  }
939
940
  const root = this._getRoot();
940
941
  return findPattern(root, (pattern) => {
941
- return pattern.name === this._name && this._isValidPattern(pattern);
942
+ return pattern.name === this._referencePatternName && this._isValidPattern(pattern);
942
943
  });
943
944
  }
944
945
  _isValidPattern(pattern) {
@@ -997,7 +998,7 @@
997
998
  return null;
998
999
  }
999
1000
  clone(name = this._name) {
1000
- const clone = new Reference(name);
1001
+ const clone = new Reference(name, this._referencePatternName);
1001
1002
  clone._id = this._id;
1002
1003
  // Optimize future clones, by caching the pattern we already found.
1003
1004
  if (this._pattern != null) {
@@ -1619,6 +1620,12 @@
1619
1620
  get startedOnIndex() {
1620
1621
  return this._repeatPattern.startedOnIndex;
1621
1622
  }
1623
+ get pattern() {
1624
+ return this._pattern;
1625
+ }
1626
+ get options() {
1627
+ return this._options;
1628
+ }
1622
1629
  constructor(name, pattern, options = {}) {
1623
1630
  this._id = `repeat-${idIndex$3++}`;
1624
1631
  this._pattern = pattern;
@@ -2680,6 +2687,9 @@
2680
2687
  get binaryPatterns() {
2681
2688
  return this._binaryPatterns;
2682
2689
  }
2690
+ get originalPatterns() {
2691
+ return this._originalPatterns;
2692
+ }
2683
2693
  get startedOnIndex() {
2684
2694
  return this._firstIndex;
2685
2695
  }
@@ -3591,8 +3601,8 @@
3591
3601
  const aliasPattern = this._getPattern(aliasName);
3592
3602
  // This solves the problem for an alias pointing to a reference.
3593
3603
  if (aliasPattern.type === "reference") {
3594
- const sequence = new Sequence(name, [aliasPattern]);
3595
- this._parseContext.patternsByName.set(name, sequence);
3604
+ const reference = new Reference(name, aliasName);
3605
+ this._parseContext.patternsByName.set(name, reference);
3596
3606
  }
3597
3607
  else {
3598
3608
  const alias = aliasPattern.clone(name);
@@ -3860,6 +3870,435 @@
3860
3870
  return result;
3861
3871
  }
3862
3872
 
3873
+ const { expression } = patterns `
3874
+ number = /[+-]?(\\d+(\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?/
3875
+ spaces = /\\s+/
3876
+ single-quote-string-literal = /'(?:\\\\.|[^'\\\\])*'/
3877
+ name = /[a-zA-Z_-]+[a-zA-Z0-9_-]*/
3878
+ comma = /\\s*,\\s*/
3879
+ wild-card = "*"
3880
+ equal = "="
3881
+ not-equal = "!="
3882
+ starts-with = "^="
3883
+ ends-with = "$="
3884
+ contains = "*="
3885
+ greater-than-or-equal = ">="
3886
+ less-than-or-equal = "<="
3887
+ greater-than = ">"
3888
+ less-than = "<"
3889
+ operators = equal |
3890
+ not-equal |
3891
+ starts-with |
3892
+ ends-with |
3893
+ contains |
3894
+ greater-than-or-equal |
3895
+ less-than-or-equal |
3896
+ greater-than |
3897
+ less-than
3898
+
3899
+ attribute-name = name
3900
+ value = name
3901
+ attribute-value = single-quote-string-literal | number | value
3902
+ attribute-selector = "[" + spaces? + attribute-name + spaces? + operators + spaces? + attribute-value + "]"
3903
+
3904
+ adjacent = spaces? + "+" + spaces?
3905
+ after = spaces? + "~" + spaces?
3906
+ direct-child = spaces? + ">" + spaces?
3907
+ descendant = spaces
3908
+
3909
+ combinators = adjacent | after | direct-child | descendant
3910
+ name-selector = name-selector-expression + attribute-selector
3911
+ name-selector-expression = name-selector | name
3912
+ node-selector = wild-card | attribute-selector | name-selector-expression
3913
+ or-selector = (node-selector, comma){2}
3914
+
3915
+ selector-expression = expression + combinators + expression
3916
+ expression = selector-expression | or-selector | node-selector
3917
+ `;
3918
+ const selectorParser = expression;
3919
+
3920
+ const combinatorMap = {
3921
+ "adjacent": true,
3922
+ "after": true,
3923
+ "descendant": true,
3924
+ "direct-child": true
3925
+ };
3926
+ const operatorMap = {
3927
+ "equal": true,
3928
+ "not-equal": true,
3929
+ "starts-with": true,
3930
+ "ends-with": true,
3931
+ "contains": true,
3932
+ "greater-than-or-equal": true,
3933
+ "less-than-or-equal": true,
3934
+ "greater-than": true,
3935
+ "less-than": true
3936
+ };
3937
+ class Selector {
3938
+ constructor(selector) {
3939
+ this._selectedNodes = [];
3940
+ this._combinator = null;
3941
+ const result = selectorParser.exec(selector);
3942
+ if (result.ast == null) {
3943
+ const message = generateErrorMessage(selectorParser, result.cursor);
3944
+ throw new Error(`[Invalid Selector] ${message}`);
3945
+ }
3946
+ this._selectorAst = result.ast;
3947
+ }
3948
+ find(nodes) {
3949
+ this._selectedNodes = nodes;
3950
+ const ast = this._selectorAst;
3951
+ ast.walkUp((node) => {
3952
+ this._process(node);
3953
+ });
3954
+ return this._selectedNodes;
3955
+ }
3956
+ filter(nodes) {
3957
+ if (nodes.length < 1) {
3958
+ return [];
3959
+ }
3960
+ const nodeMap = new Map();
3961
+ nodes.forEach(n => nodeMap.set(n, n));
3962
+ this._selectedNodes = [nodes[0].findRoot()];
3963
+ const ast = this._selectorAst;
3964
+ ast.walkUp((node) => {
3965
+ this._process(node);
3966
+ });
3967
+ return this._selectedNodes.filter(n => nodeMap.has(n));
3968
+ }
3969
+ not(nodes) {
3970
+ if (nodes.length < 1) {
3971
+ return [];
3972
+ }
3973
+ this._selectedNodes = [nodes[0].findRoot()];
3974
+ const ast = this._selectorAst;
3975
+ ast.walkUp((node) => {
3976
+ this._process(node);
3977
+ });
3978
+ const selectedNodeMap = new Map();
3979
+ this._selectedNodes.forEach(n => selectedNodeMap.set(n, n));
3980
+ return nodes.filter(n => !selectedNodeMap.has(n));
3981
+ }
3982
+ parents(nodes) {
3983
+ if (nodes.length < 1) {
3984
+ return [];
3985
+ }
3986
+ this._selectedNodes = [nodes[0].findRoot()];
3987
+ const ast = this._selectorAst;
3988
+ ast.walkUp((node) => {
3989
+ this._process(node);
3990
+ });
3991
+ const result = new Set();
3992
+ const ancestorMap = new Map();
3993
+ this._selectedNodes.forEach(n => ancestorMap.set(n, true));
3994
+ nodes.forEach(n => {
3995
+ const ancestor = n.findAncestor(a => ancestorMap.has(a));
3996
+ if (ancestor != null) {
3997
+ result.add(ancestor);
3998
+ }
3999
+ });
4000
+ return Array.from(result);
4001
+ }
4002
+ _process(ast) {
4003
+ const nodeName = ast.name;
4004
+ if (nodeName === "wild-card") {
4005
+ this._selectedNodes = this._processWildCard();
4006
+ }
4007
+ else if (nodeName === "or-selector") {
4008
+ this._selectedNodes = this._processOrSelector(ast);
4009
+ }
4010
+ else if (nodeName === "name-selector" || (nodeName === "name" && (ast.parent == null || ast.parent.name === "selector-expression"))) {
4011
+ this._selectedNodes = this._processNameSelector(ast);
4012
+ }
4013
+ else if (nodeName === "attribute-selector" && (ast.parent == null || ast.parent.name === "selector-expression")) {
4014
+ this._selectedNodes = this._processAttributeSelector(ast);
4015
+ }
4016
+ else if (combinatorMap[nodeName]) {
4017
+ this._combinator = nodeName;
4018
+ }
4019
+ else if (nodeName === "selector-expression") {
4020
+ this._combinator = null;
4021
+ }
4022
+ }
4023
+ _processWildCard() {
4024
+ return this._selectedNodes.map(n => {
4025
+ return this._selectWithCombinator(n, () => true);
4026
+ }).flat();
4027
+ }
4028
+ _processOrSelector(ast) {
4029
+ const selectorNodes = ast.children.filter(n => n.name !== "comma");
4030
+ const set = new Set();
4031
+ const selectors = selectorNodes.map(n => new Selector(n.toString()));
4032
+ selectors.map(s => {
4033
+ return s.find(this._selectedNodes.slice());
4034
+ }).flat().forEach((node) => {
4035
+ set.add(node);
4036
+ });
4037
+ return Array.from(set);
4038
+ }
4039
+ _processNameSelector(ast) {
4040
+ if (ast.children.length > 1) {
4041
+ return this._selectedNodes.map(n => {
4042
+ const name = ast.children[0].value;
4043
+ return this._selectWithCombinator(n, (node) => {
4044
+ return node.name === name && this._isAttributeMatch(node, ast);
4045
+ });
4046
+ }).flat();
4047
+ }
4048
+ else {
4049
+ return this._selectedNodes.map(n => {
4050
+ return this._selectWithCombinator(n, (node) => node.name === ast.value);
4051
+ }).flat();
4052
+ }
4053
+ }
4054
+ _processAttributeSelector(ast) {
4055
+ return this._selectedNodes.map(n => {
4056
+ return this._selectWithCombinator(n, (node) => {
4057
+ return this._isAttributeMatch(node, ast);
4058
+ });
4059
+ }).flat();
4060
+ }
4061
+ _selectWithCombinator(node, predicate) {
4062
+ if (this._combinator === "adjacent") {
4063
+ const sibling = node.nextSibling();
4064
+ if (sibling == null) {
4065
+ return [];
4066
+ }
4067
+ if (predicate(sibling)) {
4068
+ return [sibling];
4069
+ }
4070
+ else {
4071
+ return [];
4072
+ }
4073
+ }
4074
+ else if (this._combinator === "after") {
4075
+ const parent = node.parent;
4076
+ if (parent == null) {
4077
+ return [];
4078
+ }
4079
+ const index = parent.findChildIndex(node);
4080
+ const after = parent.children.slice(index + 1);
4081
+ return after.filter(predicate);
4082
+ }
4083
+ else if (this._combinator === "direct-child") {
4084
+ return node.children.filter(predicate);
4085
+ }
4086
+ else if (this._combinator === "descendant" || this._combinator == null) {
4087
+ return node.findAll(predicate);
4088
+ }
4089
+ else {
4090
+ return [];
4091
+ }
4092
+ }
4093
+ _isAttributeMatch(node, ast) {
4094
+ const name = this._getAttributeName(ast);
4095
+ const operator = this._getAttributeOperator(ast);
4096
+ const value = this._getAttributeValue(ast);
4097
+ const anyNode = node;
4098
+ if (anyNode[name] == null) {
4099
+ return false;
4100
+ }
4101
+ if (operator === "equal") {
4102
+ return anyNode[name] === value;
4103
+ }
4104
+ else if (operator === "not-equal") {
4105
+ return anyNode[name] !== value;
4106
+ }
4107
+ else if (operator === "starts-with") {
4108
+ return anyNode[name].toString().startsWith(value);
4109
+ }
4110
+ else if (operator === "ends-with") {
4111
+ return anyNode[name].toString().endsWith(value);
4112
+ }
4113
+ else if (operator === "contains") {
4114
+ return anyNode[name].toString().includes(value);
4115
+ }
4116
+ else if (operator === "greater-than-or-equal") {
4117
+ return anyNode[name] >= value;
4118
+ }
4119
+ else if (operator === "less-than-or-equal") {
4120
+ return anyNode[name] <= value;
4121
+ }
4122
+ else if (operator === "greater-than") {
4123
+ return anyNode[name] > value;
4124
+ }
4125
+ else if (operator === "less-than") {
4126
+ return anyNode[name] < value;
4127
+ }
4128
+ return false;
4129
+ }
4130
+ _getAttributeName(ast) {
4131
+ return ast.find(n => n.name === "attribute-name").value;
4132
+ }
4133
+ _getAttributeValue(ast) {
4134
+ let valueNode = ast.find(n => n.name === "single-quote-string-literal");
4135
+ if (valueNode != null) {
4136
+ return valueNode.value.slice(1, -1);
4137
+ }
4138
+ else {
4139
+ valueNode = ast.find(n => n.name === "value");
4140
+ }
4141
+ if (valueNode != null) {
4142
+ return valueNode.value;
4143
+ }
4144
+ else {
4145
+ valueNode = ast.find(n => n.name === "number");
4146
+ }
4147
+ return valueNode.value;
4148
+ }
4149
+ _getAttributeOperator(ast) {
4150
+ return ast.find(n => operatorMap[n.name]).name;
4151
+ }
4152
+ }
4153
+
4154
+ class Query {
4155
+ constructor(context, prevQuery = null) {
4156
+ this._context = context;
4157
+ this._prevQuery = prevQuery;
4158
+ }
4159
+ toArray() {
4160
+ return this._context.slice();
4161
+ }
4162
+ // Modifiers
4163
+ append(visitor) {
4164
+ this._context.forEach(n => {
4165
+ const parent = n.parent;
4166
+ if (parent == null) {
4167
+ return;
4168
+ }
4169
+ const newNode = visitor(n);
4170
+ n.appendChild(newNode);
4171
+ });
4172
+ return this;
4173
+ }
4174
+ prepend(visitor) {
4175
+ this._context.forEach(n => {
4176
+ const parent = n.parent;
4177
+ if (parent == null) {
4178
+ return;
4179
+ }
4180
+ const newNode = visitor(n);
4181
+ n.insertBefore(newNode, n.children[0]);
4182
+ });
4183
+ return this;
4184
+ }
4185
+ after(visitor) {
4186
+ this._context.forEach(n => {
4187
+ const parent = n.parent;
4188
+ if (parent == null) {
4189
+ return;
4190
+ }
4191
+ const index = parent.findChildIndex(n);
4192
+ const newNode = visitor(n);
4193
+ parent.spliceChildren(index + 1, 0, newNode);
4194
+ });
4195
+ return this;
4196
+ }
4197
+ before(visitor) {
4198
+ this._context.forEach(n => {
4199
+ const parent = n.parent;
4200
+ if (parent == null) {
4201
+ return;
4202
+ }
4203
+ const index = parent.findChildIndex(n);
4204
+ const newNode = visitor(n);
4205
+ parent.spliceChildren(index, 0, newNode);
4206
+ });
4207
+ return this;
4208
+ }
4209
+ replaceWith(visitor) {
4210
+ this._context.forEach(n => {
4211
+ const newNode = visitor(n);
4212
+ n.replaceWith(newNode);
4213
+ });
4214
+ return this;
4215
+ }
4216
+ compact() {
4217
+ this._context.forEach(n => {
4218
+ n.compact();
4219
+ });
4220
+ return this;
4221
+ }
4222
+ setValue(value) {
4223
+ this.replaceWith((n) => {
4224
+ return Node.createValueNode(n.type, n.name, value);
4225
+ });
4226
+ return this;
4227
+ }
4228
+ normalize() {
4229
+ const first = this._context[0];
4230
+ if (first != null) {
4231
+ first.findRoot().normalize();
4232
+ }
4233
+ }
4234
+ remove() {
4235
+ this._context.forEach(n => {
4236
+ n.remove();
4237
+ });
4238
+ return this;
4239
+ }
4240
+ // Filters from the currently matched nodes
4241
+ slice(start, end) {
4242
+ return new Query(this._context.slice(start, end));
4243
+ }
4244
+ filter(selectorString) {
4245
+ const selector = new Selector(selectorString);
4246
+ const newContext = selector.filter(this._context);
4247
+ return new Query(newContext, this);
4248
+ }
4249
+ // Selects out of all descedants of currently matched nodes
4250
+ find(selectorString) {
4251
+ const selector = new Selector(selectorString);
4252
+ const newContext = selector.find(this._context);
4253
+ return new Query(newContext, this);
4254
+ }
4255
+ // Remove nodes from the set of matched nodes.
4256
+ not(selectorString) {
4257
+ const selector = new Selector(selectorString);
4258
+ const newContext = selector.not(this._context);
4259
+ return new Query(newContext, this);
4260
+ }
4261
+ // Select the parent of currently matched nodes
4262
+ parent() {
4263
+ const parents = this._context.map(n => n.parent);
4264
+ const result = new Set();
4265
+ parents.forEach((n) => {
4266
+ if (n != null) {
4267
+ result.add(n);
4268
+ }
4269
+ });
4270
+ return new Query(Array.from(result), this);
4271
+ }
4272
+ // Select the ancestors of currently matched nodes
4273
+ parents(selectorString) {
4274
+ const selector = new Selector(selectorString);
4275
+ const newContext = selector.parents(this._context);
4276
+ const result = new Set();
4277
+ newContext.forEach((n) => {
4278
+ if (n != null) {
4279
+ result.add(n);
4280
+ }
4281
+ });
4282
+ return new Query(Array.from(result), this);
4283
+ }
4284
+ first() {
4285
+ return new Query(this._context.slice(0, 1), this);
4286
+ }
4287
+ last() {
4288
+ return new Query(this._context.slice(-1), this);
4289
+ }
4290
+ // Pop query stack
4291
+ end() {
4292
+ if (this._prevQuery) {
4293
+ return this._prevQuery;
4294
+ }
4295
+ return this;
4296
+ }
4297
+ length() {
4298
+ return this._context.length;
4299
+ }
4300
+ }
4301
+
3863
4302
  exports.AutoComplete = AutoComplete;
3864
4303
  exports.Context = Context;
3865
4304
  exports.Cursor = Cursor;
@@ -3872,10 +4311,12 @@
3872
4311
  exports.Optional = Optional;
3873
4312
  exports.Options = Options;
3874
4313
  exports.ParseError = ParseError;
4314
+ exports.Query = Query;
3875
4315
  exports.Reference = Reference;
3876
4316
  exports.Regex = Regex;
3877
4317
  exports.Repeat = Repeat;
3878
4318
  exports.RightAssociated = RightAssociated;
4319
+ exports.Selector = Selector;
3879
4320
  exports.Sequence = Sequence;
3880
4321
  exports.compact = compact;
3881
4322
  exports.grammar = grammar;