clarity-pattern-parser 3.0.15 → 4.0.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/README.md +0 -191
- package/dist/ast/Node.d.ts +4 -5
- package/dist/index.browser.js +476 -731
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +10 -18
- package/dist/index.esm.js +469 -716
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +476 -731
- package/dist/index.js.map +1 -1
- package/dist/patterns/And.d.ts +24 -0
- package/dist/patterns/Literal.d.ts +19 -0
- package/dist/patterns/LookAhead.d.ts +8 -0
- package/dist/patterns/Not.d.ts +11 -0
- package/dist/patterns/Or.d.ts +22 -0
- package/dist/patterns/Pattern.d.ts +6 -7
- package/dist/patterns/{RecursivePattern.d.ts → Recursive.d.ts} +4 -4
- package/dist/patterns/Reference.d.ts +14 -0
- package/dist/patterns/Regex.d.ts +21 -0
- package/dist/patterns/Repeat.d.ts +20 -0
- package/package.json +1 -1
- package/src/CursorHistory.ts +1 -1
- package/src/ast/Node.ts +20 -17
- package/src/ast/Visitor.ts +14 -18
- package/src/index.ts +17 -33
- package/src/patterns/And.ts +178 -0
- package/src/patterns/Literal.ts +91 -0
- package/src/patterns/LookAhead.ts +32 -0
- package/src/patterns/Not.ts +50 -0
- package/src/patterns/Or.ts +132 -0
- package/src/patterns/Pattern.ts +31 -47
- package/src/patterns/Recursive.ts +92 -0
- package/src/patterns/Reference.ts +127 -0
- package/src/patterns/Regex.ts +123 -0
- package/src/patterns/Repeat.ts +155 -0
- package/src/tests/{AndValue.test.ts → And.test.ts} +31 -41
- package/src/tests/CursorHistory.test.ts +6 -6
- package/src/tests/Cusor.test.ts +7 -10
- package/src/tests/Literal.test.ts +3 -5
- package/src/tests/LookAhead.test.ts +44 -0
- package/src/tests/Not.test.ts +51 -0
- package/src/tests/Or.test.ts +113 -0
- package/src/tests/Pattern.test.ts +41 -141
- package/src/tests/{RecursivePattern.test.ts → Recursive.test.ts} +10 -8
- package/src/tests/Reference.test.ts +16 -0
- package/src/tests/{RepeatValue.test.ts → Repeat.test.ts} +10 -42
- package/src/tests/TextSuggester.test.ts +20 -28
- package/src/tests/{NodeVisitor.test.ts → Visitor.test.ts} +42 -21
- package/src/tests/cssPatterns/cssValue.ts +2 -2
- package/src/tests/cssPatterns/divider.ts +2 -2
- package/src/tests/cssPatterns/hex.ts +2 -2
- package/src/tests/cssPatterns/method.ts +7 -9
- package/src/tests/cssPatterns/name.ts +2 -2
- package/src/tests/cssPatterns/number.ts +2 -2
- package/src/tests/cssPatterns/optionalSpaces.ts +1 -2
- package/src/tests/cssPatterns/spaces.ts +2 -2
- package/src/tests/cssPatterns/unit.ts +3 -3
- package/src/tests/cssPatterns/value.ts +2 -2
- package/src/tests/cssPatterns/values.ts +2 -2
- package/src/tests/htmlPatterns/element.ts +18 -33
- package/src/tests/javascriptPatterns/boolean.ts +2 -3
- package/src/tests/javascriptPatterns/json.ts +14 -24
- package/src/tests/javascriptPatterns/name.ts +3 -20
- package/src/tests/javascriptPatterns/number.ts +2 -2
- package/src/tests/javascriptPatterns/objectLiteral.ts +9 -16
- package/src/tests/javascriptPatterns/string.ts +26 -24
- package/src/tests/javascriptPatterns/unit.ts +3 -6
- package/src/tests/javascriptPatterns/whitespace.ts +8 -12
- package/src/tests/naturalLanguage/filter.ts +16 -33
- package/src/tests/patterns/sentence.ts +8 -8
- package/dist/Cursor.js +0 -105
- package/dist/Cursor.js.map +0 -1
- package/dist/CursorHistory.js +0 -104
- package/dist/CursorHistory.js.map +0 -1
- package/dist/Permutor.d.ts +0 -13
- package/dist/Permutor.js +0 -52
- package/dist/Permutor.js.map +0 -1
- package/dist/TextSuggester.js +0 -244
- package/dist/TextSuggester.js.map +0 -1
- package/dist/ast/CompositeNode.d.ts +0 -6
- package/dist/ast/CompositeNode.js +0 -17
- package/dist/ast/CompositeNode.js.map +0 -1
- package/dist/ast/Node.js +0 -16
- package/dist/ast/Node.js.map +0 -1
- package/dist/ast/NodeVisitor.d.ts +0 -31
- package/dist/ast/ValueNode.d.ts +0 -6
- package/dist/ast/ValueNode.js +0 -14
- package/dist/ast/ValueNode.js.map +0 -1
- package/dist/ast/Visitor.js +0 -209
- package/dist/ast/Visitor.js.map +0 -1
- package/dist/patterns/ParseError.js +0 -9
- package/dist/patterns/ParseError.js.map +0 -1
- package/dist/patterns/Pattern.js +0 -127
- package/dist/patterns/Pattern.js.map +0 -1
- package/dist/patterns/RecursivePattern.js +0 -65
- package/dist/patterns/RecursivePattern.js.map +0 -1
- package/dist/patterns/composite/AndComposite.d.ts +0 -22
- package/dist/patterns/composite/AndComposite.js +0 -117
- package/dist/patterns/composite/AndComposite.js.map +0 -1
- package/dist/patterns/composite/CompositePattern.d.ts +0 -4
- package/dist/patterns/composite/CompositePattern.js +0 -7
- package/dist/patterns/composite/CompositePattern.js.map +0 -1
- package/dist/patterns/composite/OptionalComposite.d.ts +0 -10
- package/dist/patterns/composite/OptionalComposite.js +0 -29
- package/dist/patterns/composite/OptionalComposite.js.map +0 -1
- package/dist/patterns/composite/OrComposite.d.ts +0 -16
- package/dist/patterns/composite/OrComposite.js +0 -69
- package/dist/patterns/composite/OrComposite.js.map +0 -1
- package/dist/patterns/composite/RepeatComposite.d.ts +0 -21
- package/dist/patterns/composite/RepeatComposite.js +0 -88
- package/dist/patterns/composite/RepeatComposite.js.map +0 -1
- package/dist/patterns/value/AndValue.d.ts +0 -21
- package/dist/patterns/value/AndValue.js +0 -118
- package/dist/patterns/value/AndValue.js.map +0 -1
- package/dist/patterns/value/AnyOfThese.d.ts +0 -18
- package/dist/patterns/value/AnyOfThese.js +0 -59
- package/dist/patterns/value/AnyOfThese.js.map +0 -1
- package/dist/patterns/value/Literal.d.ts +0 -20
- package/dist/patterns/value/Literal.js +0 -63
- package/dist/patterns/value/Literal.js.map +0 -1
- package/dist/patterns/value/NotValue.d.ts +0 -17
- package/dist/patterns/value/NotValue.js +0 -70
- package/dist/patterns/value/NotValue.js.map +0 -1
- package/dist/patterns/value/OptionalValue.d.ts +0 -9
- package/dist/patterns/value/OptionalValue.js +0 -32
- package/dist/patterns/value/OptionalValue.js.map +0 -1
- package/dist/patterns/value/OrValue.d.ts +0 -19
- package/dist/patterns/value/OrValue.js +0 -73
- package/dist/patterns/value/OrValue.js.map +0 -1
- package/dist/patterns/value/RegexValue.d.ts +0 -19
- package/dist/patterns/value/RegexValue.js +0 -69
- package/dist/patterns/value/RegexValue.js.map +0 -1
- package/dist/patterns/value/RepeatValue.d.ts +0 -19
- package/dist/patterns/value/RepeatValue.js +0 -89
- package/dist/patterns/value/RepeatValue.js.map +0 -1
- package/dist/patterns/value/ValuePattern.d.ts +0 -5
- package/dist/patterns/value/ValuePattern.js +0 -7
- package/dist/patterns/value/ValuePattern.js.map +0 -1
- package/src/Permutor.ts +0 -64
- package/src/ast/CompositeNode.ts +0 -26
- package/src/ast/ValueNode.ts +0 -28
- package/src/patterns/RecursivePattern.ts +0 -86
- package/src/patterns/composite/AndComposite.ts +0 -159
- package/src/patterns/composite/CompositePattern.ts +0 -7
- package/src/patterns/composite/OptionalComposite.ts +0 -37
- package/src/patterns/composite/OrComposite.ts +0 -96
- package/src/patterns/composite/RepeatComposite.ts +0 -130
- package/src/patterns/value/AndValue.ts +0 -153
- package/src/patterns/value/AnyOfThese.ts +0 -81
- package/src/patterns/value/Literal.ts +0 -92
- package/src/patterns/value/NotValue.ts +0 -95
- package/src/patterns/value/OptionalValue.ts +0 -39
- package/src/patterns/value/OrValue.ts +0 -103
- package/src/patterns/value/RegexValue.ts +0 -103
- package/src/patterns/value/RepeatValue.ts +0 -131
- package/src/patterns/value/ValuePattern.ts +0 -8
- package/src/tests/AndComposite.test.ts +0 -102
- package/src/tests/AnyOfThese.test.ts +0 -74
- package/src/tests/CompositeNode.test.ts +0 -33
- package/src/tests/NotValue.test.ts +0 -69
- package/src/tests/OptionalValue.test.ts +0 -50
- package/src/tests/OrComposite.test.ts +0 -75
- package/src/tests/OrValue.test.ts +0 -171
- package/src/tests/Permutor.test.ts +0 -30
- package/src/tests/RegexValue.test.ts +0 -22
- package/src/tests/RepeatComposite.test.ts +0 -58
- package/src/tests/ValueNode.test.ts +0 -24
- package/src/tests/javascriptPatterns/varStatement.ts +0 -0
- package/src/tests/readmeDemo.test.ts +0 -124
package/dist/index.esm.js
CHANGED
|
@@ -1,42 +1,14 @@
|
|
|
1
1
|
class Node {
|
|
2
|
-
constructor(type, name, startIndex, endIndex,
|
|
3
|
-
this.children = [];
|
|
4
|
-
this.value = "";
|
|
2
|
+
constructor(type, name, startIndex, endIndex, children = [], value = "") {
|
|
5
3
|
this.type = type;
|
|
6
4
|
this.name = name;
|
|
7
5
|
this.startIndex = startIndex;
|
|
8
6
|
this.endIndex = endIndex;
|
|
9
|
-
this.
|
|
10
|
-
if (typeof this.startIndex !== "number" ||
|
|
11
|
-
typeof this.endIndex !== "number") {
|
|
12
|
-
throw new Error("Invalid Arguments: startIndex and endIndex need to be number.");
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
class CompositeNode extends Node {
|
|
18
|
-
constructor(type, name, startIndex = 0, endIndex = 0) {
|
|
19
|
-
super(type, name, startIndex, endIndex, true);
|
|
20
|
-
}
|
|
21
|
-
clone() {
|
|
22
|
-
const node = new CompositeNode(this.type, this.name, this.startIndex, this.endIndex);
|
|
23
|
-
node.children = this.children.map((child) => {
|
|
24
|
-
return child.clone();
|
|
25
|
-
});
|
|
26
|
-
return node;
|
|
27
|
-
}
|
|
28
|
-
toString() {
|
|
29
|
-
return this.children.map((child) => child.toString()).join("");
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
class ValueNode extends Node {
|
|
34
|
-
constructor(type, name, value, startIndex = 0, endIndex = 0) {
|
|
35
|
-
super(type, name, startIndex, endIndex);
|
|
7
|
+
this.children = children;
|
|
36
8
|
this.value = value;
|
|
37
9
|
}
|
|
38
10
|
clone() {
|
|
39
|
-
return new
|
|
11
|
+
return new Node(this.type, this.name, this.startIndex, this.endIndex, this.children.map((c) => c.clone()), this.value);
|
|
40
12
|
}
|
|
41
13
|
toString() {
|
|
42
14
|
return this.value;
|
|
@@ -261,19 +233,17 @@ class ParseError {
|
|
|
261
233
|
}
|
|
262
234
|
|
|
263
235
|
class Pattern {
|
|
264
|
-
constructor(type
|
|
236
|
+
constructor(type, name, children = [], isOptional = false) {
|
|
237
|
+
this._isOptional = false;
|
|
265
238
|
this._type = type;
|
|
266
239
|
this._name = name;
|
|
267
240
|
this._children = [];
|
|
268
241
|
this._parent = null;
|
|
269
|
-
this.
|
|
270
|
-
this._assertName();
|
|
242
|
+
this._isOptional = isOptional;
|
|
271
243
|
this.children = children;
|
|
272
244
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
throw new Error("Invalid Argument: Patterns needs to have a name that's a string.");
|
|
276
|
-
}
|
|
245
|
+
get isOptional() {
|
|
246
|
+
return this._isOptional;
|
|
277
247
|
}
|
|
278
248
|
exec(text) {
|
|
279
249
|
const cursor = new Cursor(text);
|
|
@@ -298,38 +268,21 @@ class Pattern {
|
|
|
298
268
|
return this._parent;
|
|
299
269
|
}
|
|
300
270
|
set parent(value) {
|
|
301
|
-
|
|
302
|
-
this._parent = value;
|
|
303
|
-
}
|
|
271
|
+
this._parent = value;
|
|
304
272
|
}
|
|
305
273
|
get children() {
|
|
306
274
|
return this._children;
|
|
307
275
|
}
|
|
308
276
|
set children(value) {
|
|
309
277
|
this._children = value;
|
|
310
|
-
this.
|
|
311
|
-
this.
|
|
312
|
-
this._assignAsParent();
|
|
278
|
+
this.cloneChildren();
|
|
279
|
+
this.assignAsParent();
|
|
313
280
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
_cloneChildren() {
|
|
318
|
-
// We need to clone the patterns so nested patterns can be parsed.
|
|
319
|
-
this._children = this._children.map((pattern) => {
|
|
320
|
-
if (!(pattern instanceof Pattern)) {
|
|
321
|
-
throw new Error(`The ${this.name} pattern has an invalid child pattern.`);
|
|
322
|
-
}
|
|
323
|
-
return pattern.clone();
|
|
324
|
-
});
|
|
325
|
-
// We need to freeze the children so they aren't modified.
|
|
326
|
-
Object.freeze(this._children);
|
|
327
|
-
}
|
|
328
|
-
_assignAsParent() {
|
|
329
|
-
this._children.forEach((child) => (child.parent = this));
|
|
281
|
+
getTokenValue() {
|
|
282
|
+
return null;
|
|
330
283
|
}
|
|
331
284
|
getNextTokens() {
|
|
332
|
-
var _a, _b
|
|
285
|
+
var _a, _b;
|
|
333
286
|
const parent = this._parent;
|
|
334
287
|
if (parent != null) {
|
|
335
288
|
const siblings = parent.children;
|
|
@@ -351,11 +304,11 @@ class Pattern {
|
|
|
351
304
|
// Another thing I don't like.
|
|
352
305
|
if (((_b = (_a = this._parent) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.indexOf("and")) === 0 &&
|
|
353
306
|
nextSibling != null &&
|
|
354
|
-
|
|
307
|
+
nextSibling.isOptional) {
|
|
355
308
|
let tokens = [];
|
|
356
309
|
for (let x = index + 1; x < siblings.length; x++) {
|
|
357
310
|
const child = siblings[x];
|
|
358
|
-
if (child.
|
|
311
|
+
if (child.isOptional) {
|
|
359
312
|
tokens = tokens.concat(child.getTokens());
|
|
360
313
|
}
|
|
361
314
|
else {
|
|
@@ -381,30 +334,28 @@ class Pattern {
|
|
|
381
334
|
}
|
|
382
335
|
return [];
|
|
383
336
|
}
|
|
384
|
-
|
|
385
|
-
|
|
337
|
+
cloneChildren() {
|
|
338
|
+
this._children = this._children.map((pattern) => {
|
|
339
|
+
return pattern.clone();
|
|
340
|
+
});
|
|
341
|
+
Object.freeze(this._children);
|
|
386
342
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
class ValuePattern extends Pattern {
|
|
390
|
-
constructor(type, name, children = []) {
|
|
391
|
-
super(type, name, children);
|
|
343
|
+
assignAsParent() {
|
|
344
|
+
this._children.forEach((child) => (child.parent = this));
|
|
392
345
|
}
|
|
393
346
|
}
|
|
394
347
|
|
|
395
|
-
class
|
|
396
|
-
constructor(name, regex) {
|
|
397
|
-
super("regex
|
|
348
|
+
class Regex extends Pattern {
|
|
349
|
+
constructor(name, regex, isOptional = false) {
|
|
350
|
+
super("regex", name, [], isOptional);
|
|
398
351
|
this.node = null;
|
|
352
|
+
this.cursor = null;
|
|
399
353
|
this.substring = "";
|
|
400
354
|
this.regexString = regex;
|
|
401
355
|
this.regex = new RegExp(`^${regex}`, "g");
|
|
402
|
-
this.
|
|
356
|
+
this.assertArguments();
|
|
403
357
|
}
|
|
404
|
-
|
|
405
|
-
if (typeof this.regexString !== "string") {
|
|
406
|
-
throw new Error("Invalid Arguments: The regex argument needs to be a string of regex.");
|
|
407
|
-
}
|
|
358
|
+
assertArguments() {
|
|
408
359
|
if (this.regexString.length < 1) {
|
|
409
360
|
throw new Error("Invalid Arguments: The regex string argument needs to be at least one character long.");
|
|
410
361
|
}
|
|
@@ -416,39 +367,57 @@ class RegexValue extends ValuePattern {
|
|
|
416
367
|
}
|
|
417
368
|
}
|
|
418
369
|
parse(cursor) {
|
|
419
|
-
this.
|
|
420
|
-
this.
|
|
370
|
+
this.resetState(cursor);
|
|
371
|
+
this.tryToParse();
|
|
421
372
|
return this.node;
|
|
422
373
|
}
|
|
423
|
-
|
|
374
|
+
resetState(cursor) {
|
|
424
375
|
this.cursor = cursor;
|
|
425
376
|
this.regex.lastIndex = 0;
|
|
426
377
|
this.substring = this.cursor.text.substr(this.cursor.getIndex());
|
|
427
378
|
this.node = null;
|
|
428
379
|
}
|
|
429
|
-
|
|
380
|
+
tryToParse() {
|
|
430
381
|
const result = this.regex.exec(this.substring);
|
|
431
382
|
if (result != null && result.index === 0) {
|
|
432
|
-
|
|
433
|
-
const newIndex = currentIndex + result[0].length - 1;
|
|
434
|
-
this.node = new ValueNode("regex-value", this.name, result[0], currentIndex, newIndex);
|
|
435
|
-
this.cursor.index = newIndex;
|
|
436
|
-
this.cursor.addMatch(this, this.node);
|
|
383
|
+
this.processResult(result);
|
|
437
384
|
}
|
|
438
385
|
else {
|
|
439
|
-
this.
|
|
386
|
+
this.processError();
|
|
440
387
|
}
|
|
441
388
|
}
|
|
442
|
-
|
|
443
|
-
const
|
|
444
|
-
const
|
|
445
|
-
|
|
389
|
+
processResult(result) {
|
|
390
|
+
const cursor = this.safelyGetCursor();
|
|
391
|
+
const currentIndex = cursor.getIndex();
|
|
392
|
+
const newIndex = currentIndex + result[0].length - 1;
|
|
393
|
+
this.node = new Node("regex", this.name, currentIndex, newIndex, [], result[0]);
|
|
394
|
+
cursor.moveToMark(newIndex);
|
|
395
|
+
cursor.addMatch(this, this.node);
|
|
446
396
|
}
|
|
447
|
-
|
|
448
|
-
|
|
397
|
+
processError() {
|
|
398
|
+
const cursor = this.safelyGetCursor();
|
|
399
|
+
if (!this._isOptional) {
|
|
400
|
+
const message = `ParseError: Expected regex pattern of '${this.regexString}' but found '${this.substring}'.`;
|
|
401
|
+
const parseError = new ParseError(message, cursor.getIndex(), this);
|
|
402
|
+
cursor.throwError(parseError);
|
|
403
|
+
}
|
|
404
|
+
this.node = null;
|
|
405
|
+
}
|
|
406
|
+
safelyGetCursor() {
|
|
407
|
+
const cursor = this.cursor;
|
|
408
|
+
if (cursor == null) {
|
|
409
|
+
throw new Error("Couldn't find cursor.");
|
|
410
|
+
}
|
|
411
|
+
return cursor;
|
|
412
|
+
}
|
|
413
|
+
clone(name, isOptional) {
|
|
414
|
+
if (name == null) {
|
|
449
415
|
name = this.name;
|
|
450
416
|
}
|
|
451
|
-
|
|
417
|
+
if (isOptional == null) {
|
|
418
|
+
isOptional = this._isOptional;
|
|
419
|
+
}
|
|
420
|
+
return new Regex(name, this.regexString, isOptional);
|
|
452
421
|
}
|
|
453
422
|
getTokenValue() {
|
|
454
423
|
return this.name;
|
|
@@ -458,712 +427,371 @@ class RegexValue extends ValuePattern {
|
|
|
458
427
|
}
|
|
459
428
|
}
|
|
460
429
|
|
|
461
|
-
class
|
|
462
|
-
constructor(
|
|
463
|
-
super("
|
|
464
|
-
this.
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
}
|
|
430
|
+
class And extends Pattern {
|
|
431
|
+
constructor(name, patterns, isOptional = false) {
|
|
432
|
+
super("and", name, patterns, isOptional);
|
|
433
|
+
this.onPatternIndex = 0;
|
|
434
|
+
this.nodes = [];
|
|
435
|
+
this.node = null;
|
|
436
|
+
this.cursor = null;
|
|
437
|
+
this.mark = 0;
|
|
470
438
|
}
|
|
471
439
|
parse(cursor) {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
440
|
+
this.resetState(cursor);
|
|
441
|
+
this.tryToParse();
|
|
442
|
+
return this.node;
|
|
443
|
+
}
|
|
444
|
+
clone(name, isOptional) {
|
|
445
|
+
if (name == null) {
|
|
446
|
+
name = this.name;
|
|
478
447
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
return node;
|
|
448
|
+
if (isOptional == null) {
|
|
449
|
+
isOptional = this._isOptional;
|
|
482
450
|
}
|
|
483
|
-
|
|
484
|
-
clone() {
|
|
485
|
-
return new OptionalValue(this.children[0]);
|
|
451
|
+
return new And(name, this._children, isOptional);
|
|
486
452
|
}
|
|
487
453
|
getTokens() {
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
this.mark = 0;
|
|
499
|
-
this._assertArguments();
|
|
500
|
-
}
|
|
501
|
-
_assertArguments() {
|
|
502
|
-
if (this._children.length < 2) {
|
|
503
|
-
throw new Error("Invalid Argument: AndValue needs to have more than one value pattern.");
|
|
454
|
+
let tokens = [];
|
|
455
|
+
for (let x = 0; x < this._children.length; x++) {
|
|
456
|
+
const child = this._children[x];
|
|
457
|
+
if (child.isOptional) {
|
|
458
|
+
tokens = tokens.concat(child.getTokens());
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
tokens = tokens.concat(child.getTokens());
|
|
462
|
+
break;
|
|
463
|
+
}
|
|
504
464
|
}
|
|
465
|
+
return tokens;
|
|
505
466
|
}
|
|
506
|
-
|
|
507
|
-
this.
|
|
467
|
+
resetState(cursor) {
|
|
468
|
+
this.onPatternIndex = 0;
|
|
508
469
|
this.nodes = [];
|
|
509
470
|
this.node = null;
|
|
510
471
|
this.cursor = cursor;
|
|
511
472
|
this.mark = this.cursor.mark();
|
|
512
473
|
}
|
|
513
|
-
|
|
514
|
-
this.
|
|
515
|
-
this._tryPatterns();
|
|
516
|
-
return this.node;
|
|
517
|
-
}
|
|
518
|
-
_tryPatterns() {
|
|
474
|
+
tryToParse() {
|
|
475
|
+
const cursor = this.safelyGetCursor();
|
|
519
476
|
while (true) {
|
|
520
|
-
const pattern = this._children[this.
|
|
521
|
-
const node = pattern.parse(
|
|
522
|
-
if (
|
|
477
|
+
const pattern = this._children[this.onPatternIndex];
|
|
478
|
+
const node = pattern.parse(cursor);
|
|
479
|
+
if (cursor.hasUnresolvedError()) {
|
|
480
|
+
this.processError();
|
|
523
481
|
break;
|
|
524
482
|
}
|
|
525
483
|
else {
|
|
526
484
|
this.nodes.push(node);
|
|
527
485
|
}
|
|
528
|
-
if (!this.
|
|
529
|
-
this.
|
|
486
|
+
if (!this.shouldProceed()) {
|
|
487
|
+
this.processResult();
|
|
530
488
|
break;
|
|
531
489
|
}
|
|
532
490
|
}
|
|
533
491
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
492
|
+
safelyGetCursor() {
|
|
493
|
+
const cursor = this.cursor;
|
|
494
|
+
if (cursor == null) {
|
|
495
|
+
throw new Error("Couldn't find cursor.");
|
|
496
|
+
}
|
|
497
|
+
return cursor;
|
|
498
|
+
}
|
|
499
|
+
processResult() {
|
|
500
|
+
const cursor = this.safelyGetCursor();
|
|
501
|
+
if (cursor.hasUnresolvedError()) {
|
|
502
|
+
this.processError();
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
this.processSuccess();
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
processError() {
|
|
509
|
+
const cursor = this.safelyGetCursor();
|
|
510
|
+
if (this.isOptional) {
|
|
511
|
+
cursor.moveToMark(this.mark);
|
|
512
|
+
cursor.resolveError();
|
|
513
|
+
}
|
|
514
|
+
this.node = null;
|
|
515
|
+
}
|
|
516
|
+
shouldProceed() {
|
|
517
|
+
const cursor = this.safelyGetCursor();
|
|
518
|
+
if (this.hasMorePatterns()) {
|
|
519
|
+
const lastNode = this.nodes[this.nodes.length - 1];
|
|
520
|
+
const wasOptional = lastNode == null;
|
|
521
|
+
if (cursor.hasNext()) {
|
|
522
|
+
if (!wasOptional) {
|
|
523
|
+
cursor.next();
|
|
540
524
|
}
|
|
541
|
-
this.
|
|
525
|
+
this.onPatternIndex++;
|
|
542
526
|
return true;
|
|
543
527
|
}
|
|
544
|
-
else if (
|
|
545
|
-
this.
|
|
528
|
+
else if (wasOptional) {
|
|
529
|
+
this.onPatternIndex++;
|
|
546
530
|
return true;
|
|
547
531
|
}
|
|
548
|
-
this.
|
|
532
|
+
this.assertRestOfPatternsAreOptional();
|
|
549
533
|
return false;
|
|
550
534
|
}
|
|
551
535
|
else {
|
|
552
536
|
return false;
|
|
553
537
|
}
|
|
554
538
|
}
|
|
555
|
-
|
|
556
|
-
return this.
|
|
539
|
+
hasMorePatterns() {
|
|
540
|
+
return this.onPatternIndex + 1 < this._children.length;
|
|
557
541
|
}
|
|
558
|
-
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
});
|
|
542
|
+
assertRestOfPatternsAreOptional() {
|
|
543
|
+
const cursor = this.safelyGetCursor();
|
|
544
|
+
const areTheRestOptional = this.areTheRemainingPatternsOptional();
|
|
562
545
|
if (!areTheRestOptional) {
|
|
563
|
-
const parseError = new ParseError(`Could not match ${this.name} before string ran out.`, this.
|
|
564
|
-
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
this.
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
name = this.name;
|
|
585
|
-
}
|
|
586
|
-
return new AndValue(name, this._children);
|
|
587
|
-
}
|
|
588
|
-
getTokens() {
|
|
589
|
-
let tokens = [];
|
|
590
|
-
for (let x = 0; x < this._children.length; x++) {
|
|
591
|
-
const child = this._children[x];
|
|
592
|
-
if (child instanceof OptionalValue) {
|
|
593
|
-
tokens = tokens.concat(child.getTokens());
|
|
594
|
-
}
|
|
595
|
-
else {
|
|
596
|
-
tokens = tokens.concat(child.getTokens());
|
|
597
|
-
break;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
return tokens;
|
|
546
|
+
const parseError = new ParseError(`Could not match ${this.name} before string ran out.`, this.onPatternIndex, this);
|
|
547
|
+
cursor.throwError(parseError);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
areTheRemainingPatternsOptional() {
|
|
551
|
+
return this.children
|
|
552
|
+
.slice(this.onPatternIndex + 1)
|
|
553
|
+
.map((p) => p.isOptional)
|
|
554
|
+
.every((r) => r);
|
|
555
|
+
}
|
|
556
|
+
processSuccess() {
|
|
557
|
+
const cursor = this.safelyGetCursor();
|
|
558
|
+
const nodes = this.nodes.filter((node) => node != null);
|
|
559
|
+
this.nodes = nodes;
|
|
560
|
+
const lastNode = nodes[this.nodes.length - 1];
|
|
561
|
+
const startIndex = this.mark;
|
|
562
|
+
const endIndex = lastNode.endIndex;
|
|
563
|
+
const value = nodes.map((node) => node.value).join("");
|
|
564
|
+
this.node = new Node("and", this.name, startIndex, endIndex, nodes, value);
|
|
565
|
+
cursor.index = this.node.endIndex;
|
|
566
|
+
cursor.addMatch(this, this.node);
|
|
601
567
|
}
|
|
602
568
|
}
|
|
603
569
|
|
|
604
|
-
class
|
|
605
|
-
constructor(name,
|
|
606
|
-
super("
|
|
570
|
+
class Literal extends Pattern {
|
|
571
|
+
constructor(name, literal, isOptional = false) {
|
|
572
|
+
super("literal", name, [], isOptional);
|
|
607
573
|
this.node = null;
|
|
608
574
|
this.mark = 0;
|
|
609
|
-
this.
|
|
610
|
-
this.
|
|
611
|
-
|
|
612
|
-
_assertArguments() {
|
|
613
|
-
if (typeof this.characters !== "string") {
|
|
614
|
-
throw new Error("Invalid Arguments: The characters argument needs to be a string of characters.");
|
|
615
|
-
}
|
|
616
|
-
if (this.characters.length < 1) {
|
|
617
|
-
throw new Error("Invalid Arguments: The characters argument needs to be at least one character long.");
|
|
618
|
-
}
|
|
575
|
+
this.substring = "";
|
|
576
|
+
this.literal = literal;
|
|
577
|
+
this.assertArguments();
|
|
619
578
|
}
|
|
620
579
|
parse(cursor) {
|
|
621
|
-
this.
|
|
622
|
-
this.
|
|
580
|
+
this.resetState(cursor);
|
|
581
|
+
this.tryToParse();
|
|
623
582
|
return this.node;
|
|
624
583
|
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
this.mark = this.cursor.mark();
|
|
628
|
-
this.node = null;
|
|
629
|
-
}
|
|
630
|
-
_tryPattern() {
|
|
631
|
-
if (this._isMatch()) {
|
|
632
|
-
const value = this.cursor.getChar();
|
|
633
|
-
const index = this.cursor.getIndex();
|
|
634
|
-
this.node = new ValueNode("any-of-these", this.name, value, index, index);
|
|
635
|
-
this.cursor.addMatch(this, this.node);
|
|
636
|
-
}
|
|
637
|
-
else {
|
|
638
|
-
this._processError();
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
_isMatch() {
|
|
642
|
-
return this.characters.indexOf(this.cursor.getChar()) > -1;
|
|
643
|
-
}
|
|
644
|
-
_processError() {
|
|
645
|
-
const message = `ParseError: Expected one of these characters, '${this.characters}' but found '${this.cursor.getChar()}' while parsing for '${this.name}'.`;
|
|
646
|
-
const parseError = new ParseError(message, this.cursor.getIndex(), this);
|
|
647
|
-
this.cursor.throwError(parseError);
|
|
648
|
-
}
|
|
649
|
-
clone(name) {
|
|
650
|
-
if (typeof name !== "string") {
|
|
584
|
+
clone(name, isOptional) {
|
|
585
|
+
if (name == null) {
|
|
651
586
|
name = this.name;
|
|
652
587
|
}
|
|
653
|
-
|
|
588
|
+
if (isOptional == null) {
|
|
589
|
+
isOptional = this._isOptional;
|
|
590
|
+
}
|
|
591
|
+
return new Literal(name, this.literal, isOptional);
|
|
654
592
|
}
|
|
655
593
|
getTokens() {
|
|
656
|
-
return this.
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
class Literal extends ValuePattern {
|
|
661
|
-
constructor(name, literal) {
|
|
662
|
-
super("literal", name);
|
|
663
|
-
this.node = null;
|
|
664
|
-
this.mark = 0;
|
|
665
|
-
this.substring = "";
|
|
666
|
-
this.literal = literal;
|
|
667
|
-
this._assertArguments();
|
|
594
|
+
return [this.literal];
|
|
668
595
|
}
|
|
669
|
-
|
|
670
|
-
if (typeof this.literal !== "string") {
|
|
671
|
-
throw new Error("Invalid Arguments: The literal argument needs to be a string of characters.");
|
|
672
|
-
}
|
|
596
|
+
assertArguments() {
|
|
673
597
|
if (this.literal.length < 1) {
|
|
674
|
-
throw new Error("Invalid Arguments: The
|
|
598
|
+
throw new Error("Invalid Arguments: The `literal` argument needs to be at least one character long.");
|
|
675
599
|
}
|
|
676
600
|
}
|
|
677
|
-
|
|
678
|
-
this._reset(cursor);
|
|
679
|
-
this._tryPattern();
|
|
680
|
-
return this.node;
|
|
681
|
-
}
|
|
682
|
-
_reset(cursor) {
|
|
601
|
+
resetState(cursor) {
|
|
683
602
|
this.cursor = cursor;
|
|
684
603
|
this.mark = this.cursor.mark();
|
|
685
604
|
this.substring = this.cursor.text.substring(this.mark, this.mark + this.literal.length);
|
|
686
605
|
this.node = null;
|
|
687
606
|
}
|
|
688
|
-
|
|
607
|
+
tryToParse() {
|
|
689
608
|
if (this.substring === this.literal) {
|
|
690
|
-
this.
|
|
609
|
+
this.processResult();
|
|
691
610
|
}
|
|
692
611
|
else {
|
|
693
|
-
this.
|
|
612
|
+
this.processError();
|
|
694
613
|
}
|
|
695
614
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
615
|
+
processError() {
|
|
616
|
+
this.node = null;
|
|
617
|
+
if (!this._isOptional) {
|
|
618
|
+
const message = `ParseError: Expected '${this.literal}' but found '${this.substring}'.`;
|
|
619
|
+
const parseError = new ParseError(message, this.cursor.getIndex(), this);
|
|
620
|
+
this.cursor.throwError(parseError);
|
|
621
|
+
}
|
|
700
622
|
}
|
|
701
|
-
|
|
702
|
-
this.node = new
|
|
623
|
+
processResult() {
|
|
624
|
+
this.node = new Node("literal", this.name, this.mark, this.mark + this.literal.length - 1, [], this.substring);
|
|
703
625
|
this.cursor.index = this.node.endIndex;
|
|
704
626
|
this.cursor.addMatch(this, this.node);
|
|
705
627
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
class LookAhead extends Pattern {
|
|
631
|
+
constructor(pattern) {
|
|
632
|
+
super("look-ahead", "look-ahead", [pattern]);
|
|
633
|
+
}
|
|
634
|
+
parse(cursor) {
|
|
635
|
+
const mark = cursor.mark();
|
|
636
|
+
const node = this.children[0].parse(cursor);
|
|
637
|
+
if (cursor.hasUnresolvedError() || node == null) {
|
|
638
|
+
cursor.resolveError();
|
|
639
|
+
cursor.throwError(new ParseError("Couldn't find look ahead pattern.", mark, this.children[0]));
|
|
640
|
+
cursor.moveToMark(mark);
|
|
709
641
|
}
|
|
710
|
-
return
|
|
642
|
+
return null;
|
|
711
643
|
}
|
|
712
|
-
|
|
713
|
-
return this.
|
|
644
|
+
clone() {
|
|
645
|
+
return new LookAhead(this.children[0].clone());
|
|
714
646
|
}
|
|
715
647
|
getTokens() {
|
|
716
|
-
return [
|
|
648
|
+
return [];
|
|
717
649
|
}
|
|
718
650
|
}
|
|
719
651
|
|
|
720
|
-
class
|
|
721
|
-
constructor(
|
|
722
|
-
super("not
|
|
723
|
-
this.match = "";
|
|
724
|
-
this.node = null;
|
|
652
|
+
class Not extends Pattern {
|
|
653
|
+
constructor(pattern) {
|
|
654
|
+
super("not", `not-${pattern.name}`, [pattern]);
|
|
725
655
|
this.mark = 0;
|
|
726
|
-
this.
|
|
727
|
-
}
|
|
728
|
-
_assertArguments() {
|
|
729
|
-
if (!(this.children[0] instanceof Pattern)) {
|
|
730
|
-
throw new Error("Invalid Arguments: Expected the pattern to be a ValuePattern.");
|
|
731
|
-
}
|
|
732
|
-
if (typeof this.name !== "string") {
|
|
733
|
-
throw new Error("Invalid Arguments: Expected name to be a string.");
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
_reset(cursor) {
|
|
737
|
-
this.match = "";
|
|
738
|
-
this.node = null;
|
|
739
|
-
this.cursor = cursor;
|
|
740
|
-
this.mark = this.cursor.mark();
|
|
656
|
+
this._isOptional = true;
|
|
741
657
|
}
|
|
742
658
|
parse(cursor) {
|
|
743
|
-
this.
|
|
744
|
-
this.
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
_tryPattern() {
|
|
748
|
-
while (true) {
|
|
749
|
-
const mark = this.cursor.mark();
|
|
750
|
-
this.children[0].parse(this.cursor);
|
|
751
|
-
if (this.cursor.hasUnresolvedError()) {
|
|
752
|
-
this.cursor.resolveError();
|
|
753
|
-
this.cursor.moveToMark(mark);
|
|
754
|
-
this.match += this.cursor.getChar();
|
|
755
|
-
break;
|
|
756
|
-
}
|
|
757
|
-
else {
|
|
758
|
-
this.cursor.moveToMark(mark);
|
|
759
|
-
break;
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
this._processMatch();
|
|
659
|
+
this.cursor = cursor;
|
|
660
|
+
this.mark = cursor.mark();
|
|
661
|
+
this.tryToParse();
|
|
662
|
+
return null;
|
|
763
663
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
664
|
+
tryToParse() {
|
|
665
|
+
const mark = this.cursor.mark();
|
|
666
|
+
this.children[0].parse(this.cursor);
|
|
667
|
+
if (this.cursor.hasUnresolvedError()) {
|
|
668
|
+
this.cursor.resolveError();
|
|
669
|
+
this.cursor.moveToMark(mark);
|
|
768
670
|
}
|
|
769
671
|
else {
|
|
770
|
-
this.
|
|
771
|
-
this.
|
|
772
|
-
this.cursor.
|
|
672
|
+
this.cursor.moveToMark(mark);
|
|
673
|
+
const parseError = new ParseError(`Match invalid pattern: ${this.children[0].name}.`, this.mark, this);
|
|
674
|
+
this.cursor.throwError(parseError);
|
|
773
675
|
}
|
|
774
676
|
}
|
|
775
677
|
clone(name) {
|
|
776
|
-
if (
|
|
678
|
+
if (name == null) {
|
|
777
679
|
name = this.name;
|
|
778
680
|
}
|
|
779
|
-
return new
|
|
681
|
+
return new Not(this.children[0]);
|
|
780
682
|
}
|
|
781
683
|
getTokens() {
|
|
782
684
|
return [];
|
|
783
685
|
}
|
|
784
686
|
}
|
|
785
687
|
|
|
786
|
-
class
|
|
787
|
-
constructor(name, patterns) {
|
|
788
|
-
super("or
|
|
789
|
-
this.
|
|
688
|
+
class Or extends Pattern {
|
|
689
|
+
constructor(name, patterns, isOptional = false) {
|
|
690
|
+
super("or", name, patterns, isOptional);
|
|
691
|
+
this.patternIndex = 0;
|
|
790
692
|
this.errors = [];
|
|
791
693
|
this.node = null;
|
|
694
|
+
this.cursor = null;
|
|
792
695
|
this.mark = 0;
|
|
793
696
|
this.parseError = null;
|
|
794
|
-
this.
|
|
697
|
+
this.assertArguments();
|
|
795
698
|
}
|
|
796
|
-
|
|
699
|
+
assertArguments() {
|
|
797
700
|
if (this._children.length < 2) {
|
|
798
701
|
throw new Error("Invalid Argument: OrValue needs to have more than one value pattern.");
|
|
799
702
|
}
|
|
800
|
-
const hasOptionalChildren = this._children.some((pattern) => pattern
|
|
703
|
+
const hasOptionalChildren = this._children.some((pattern) => pattern.isOptional);
|
|
801
704
|
if (hasOptionalChildren) {
|
|
802
|
-
throw new Error("OrValues cannot have optional
|
|
705
|
+
throw new Error("OrValues cannot have optional patterns.");
|
|
803
706
|
}
|
|
804
707
|
}
|
|
805
|
-
|
|
806
|
-
this.
|
|
708
|
+
resetState(cursor) {
|
|
709
|
+
this.patternIndex = 0;
|
|
807
710
|
this.errors = [];
|
|
808
711
|
this.node = null;
|
|
809
712
|
this.cursor = cursor;
|
|
810
713
|
this.mark = cursor.mark();
|
|
811
714
|
}
|
|
812
|
-
|
|
813
|
-
this.
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
}
|
|
817
|
-
_tryPattern() {
|
|
818
|
-
while (true) {
|
|
819
|
-
const pattern = this._children[this.index];
|
|
820
|
-
const node = pattern.parse(this.cursor);
|
|
821
|
-
if (this.cursor.hasUnresolvedError()) {
|
|
822
|
-
if (this.index + 1 < this._children.length) {
|
|
823
|
-
this.cursor.resolveError();
|
|
824
|
-
this.index++;
|
|
825
|
-
this.cursor.moveToMark(this.mark);
|
|
826
|
-
}
|
|
827
|
-
else {
|
|
828
|
-
this.node = null;
|
|
829
|
-
break;
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
else {
|
|
833
|
-
this.node = new ValueNode("or-value", this.name, node.value, node.startIndex, node.endIndex);
|
|
834
|
-
this.cursor.index = this.node.endIndex;
|
|
835
|
-
this.cursor.addMatch(this, this.node);
|
|
836
|
-
break;
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
clone(name) {
|
|
841
|
-
if (typeof name !== "string") {
|
|
842
|
-
name = this.name;
|
|
843
|
-
}
|
|
844
|
-
return new OrValue(name, this._children);
|
|
845
|
-
}
|
|
846
|
-
getTokens() {
|
|
847
|
-
const tokens = this._children.map((c) => c.getTokens());
|
|
848
|
-
const hasPrimitiveTokens = tokens.every((t) => t.every((value) => typeof value === "string"));
|
|
849
|
-
if (hasPrimitiveTokens && tokens.length > 0) {
|
|
850
|
-
return tokens.reduce((acc, t) => acc.concat(t), []);
|
|
851
|
-
}
|
|
852
|
-
return this._children[0].getTokens();
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
class RepeatValue extends ValuePattern {
|
|
857
|
-
constructor(name, pattern, divider) {
|
|
858
|
-
super("repeat-value", name, divider != null ? [pattern, divider] : [pattern]);
|
|
859
|
-
this.nodes = [];
|
|
860
|
-
this.mark = 0;
|
|
861
|
-
this.node = null;
|
|
862
|
-
this._pattern = this.children[0];
|
|
863
|
-
this._divider = this.children[1];
|
|
864
|
-
this._assertArguments();
|
|
865
|
-
}
|
|
866
|
-
_assertArguments() {
|
|
867
|
-
if (this._pattern instanceof OptionalValue) {
|
|
868
|
-
throw new Error("Invalid Arguments: The pattern cannot be a optional pattern.");
|
|
715
|
+
safelyGetCursor() {
|
|
716
|
+
const cursor = this.cursor;
|
|
717
|
+
if (cursor == null) {
|
|
718
|
+
throw new Error("Couldn't find cursor.");
|
|
869
719
|
}
|
|
870
|
-
|
|
871
|
-
_reset(cursor) {
|
|
872
|
-
this.nodes = [];
|
|
873
|
-
this.cursor = cursor;
|
|
874
|
-
this.mark = this.cursor.mark();
|
|
720
|
+
return cursor;
|
|
875
721
|
}
|
|
876
722
|
parse(cursor) {
|
|
877
|
-
this.
|
|
878
|
-
this.
|
|
723
|
+
this.resetState(cursor);
|
|
724
|
+
this.tryToParse();
|
|
879
725
|
return this.node;
|
|
880
726
|
}
|
|
881
|
-
|
|
727
|
+
tryToParse() {
|
|
728
|
+
const cursor = this.safelyGetCursor();
|
|
882
729
|
while (true) {
|
|
883
|
-
const
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
this.nodes.push(node);
|
|
890
|
-
if (node.endIndex === this.cursor.lastIndex()) {
|
|
891
|
-
this._processMatch();
|
|
730
|
+
const pattern = this._children[this.patternIndex];
|
|
731
|
+
const node = pattern.parse(cursor);
|
|
732
|
+
const hasError = cursor.hasUnresolvedError();
|
|
733
|
+
if (hasError) {
|
|
734
|
+
const shouldBreak = this.processError();
|
|
735
|
+
if (shouldBreak) {
|
|
892
736
|
break;
|
|
893
737
|
}
|
|
894
|
-
this.cursor.next();
|
|
895
|
-
if (this._divider != null) {
|
|
896
|
-
const mark = this.cursor.mark();
|
|
897
|
-
const node = this._divider.parse(this.cursor);
|
|
898
|
-
if (this.cursor.hasUnresolvedError()) {
|
|
899
|
-
this.cursor.moveToMark(mark);
|
|
900
|
-
this._processMatch();
|
|
901
|
-
break;
|
|
902
|
-
}
|
|
903
|
-
else {
|
|
904
|
-
this.nodes.push(node);
|
|
905
|
-
if (node.endIndex === this.cursor.lastIndex()) {
|
|
906
|
-
this._processMatch();
|
|
907
|
-
break;
|
|
908
|
-
}
|
|
909
|
-
this.cursor.next();
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
_processMatch() {
|
|
916
|
-
const endsOnDivider = this.nodes.length % 2 === 0;
|
|
917
|
-
const noMatch = this.nodes.length === 0;
|
|
918
|
-
const hasDivider = this._divider != null;
|
|
919
|
-
this.cursor.resolveError();
|
|
920
|
-
if ((hasDivider && endsOnDivider) || noMatch) {
|
|
921
|
-
const parseError = new ParseError(`Did not find a repeating match of ${this.name}.`, this.mark, this);
|
|
922
|
-
this.cursor.throwError(parseError);
|
|
923
|
-
this.node = null;
|
|
924
|
-
}
|
|
925
|
-
else {
|
|
926
|
-
const value = this.nodes.map((node) => node.value).join("");
|
|
927
|
-
this.node = new ValueNode("repeat-value", this.name, value, this.nodes[0].startIndex, this.nodes[this.nodes.length - 1].endIndex);
|
|
928
|
-
this.cursor.index = this.node.endIndex;
|
|
929
|
-
this.cursor.addMatch(this, this.node);
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
clone(name) {
|
|
933
|
-
if (typeof name !== "string") {
|
|
934
|
-
name = this.name;
|
|
935
|
-
}
|
|
936
|
-
return new RepeatValue(name, this._pattern, this._divider);
|
|
937
|
-
}
|
|
938
|
-
getTokens() {
|
|
939
|
-
return this._pattern.getTokens();
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
class CompositePattern extends Pattern {
|
|
944
|
-
constructor(type, name, children = []) {
|
|
945
|
-
super(type, name, children);
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
class OptionalComposite extends CompositePattern {
|
|
950
|
-
constructor(pattern) {
|
|
951
|
-
super("optional-composite", "optional-composite", [pattern]);
|
|
952
|
-
}
|
|
953
|
-
parse(cursor) {
|
|
954
|
-
const mark = cursor.mark();
|
|
955
|
-
this.mark = mark;
|
|
956
|
-
const node = this.children[0].parse(cursor);
|
|
957
|
-
if (cursor.hasUnresolvedError()) {
|
|
958
|
-
cursor.resolveError();
|
|
959
|
-
cursor.moveToMark(mark);
|
|
960
|
-
return null;
|
|
961
|
-
}
|
|
962
|
-
else {
|
|
963
|
-
if (node != null) {
|
|
964
|
-
cursor.addMatch(this, node);
|
|
965
|
-
}
|
|
966
|
-
return node;
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
clone() {
|
|
970
|
-
return new OptionalComposite(this.children[0]);
|
|
971
|
-
}
|
|
972
|
-
getTokens() {
|
|
973
|
-
return this._children[0].getTokens();
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
class AndComposite extends CompositePattern {
|
|
978
|
-
constructor(name, patterns = []) {
|
|
979
|
-
super("and-composite", name, patterns);
|
|
980
|
-
this._assertArguments();
|
|
981
|
-
}
|
|
982
|
-
_assertArguments() {
|
|
983
|
-
if (this._children.length < 2) {
|
|
984
|
-
throw new Error("Invalid Argument: AndValue needs to have more than one value pattern.");
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
_reset(cursor) {
|
|
988
|
-
this.index = 0;
|
|
989
|
-
this.nodes = [];
|
|
990
|
-
this.node = null;
|
|
991
|
-
this.cursor = cursor;
|
|
992
|
-
this.mark = this.cursor.mark();
|
|
993
|
-
}
|
|
994
|
-
parse(cursor) {
|
|
995
|
-
this._reset(cursor);
|
|
996
|
-
this._tryPatterns();
|
|
997
|
-
return this.node;
|
|
998
|
-
}
|
|
999
|
-
_tryPatterns() {
|
|
1000
|
-
while (true) {
|
|
1001
|
-
const pattern = this._children[this.index];
|
|
1002
|
-
const node = pattern.parse(this.cursor);
|
|
1003
|
-
if (this.cursor.hasUnresolvedError()) {
|
|
1004
|
-
this.cursor.moveToMark(this.mark);
|
|
1005
|
-
break;
|
|
1006
|
-
}
|
|
1007
|
-
else {
|
|
1008
|
-
this.nodes.push(node);
|
|
1009
738
|
}
|
|
1010
|
-
if (
|
|
1011
|
-
this.
|
|
739
|
+
else if (node != null) {
|
|
740
|
+
this.processResult(node);
|
|
1012
741
|
break;
|
|
1013
742
|
}
|
|
1014
743
|
}
|
|
1015
744
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
this.index++;
|
|
1024
|
-
return true;
|
|
1025
|
-
}
|
|
1026
|
-
else if (this.nodes[this.nodes.length - 1] == null) {
|
|
1027
|
-
this.index++;
|
|
1028
|
-
return true;
|
|
1029
|
-
}
|
|
1030
|
-
this._assertRestOfPatternsAreOptional();
|
|
1031
|
-
return false;
|
|
1032
|
-
}
|
|
1033
|
-
else {
|
|
745
|
+
processError() {
|
|
746
|
+
const cursor = this.safelyGetCursor();
|
|
747
|
+
const isLastPattern = this.patternIndex + 1 === this._children.length;
|
|
748
|
+
if (!isLastPattern) {
|
|
749
|
+
this.patternIndex++;
|
|
750
|
+
cursor.resolveError();
|
|
751
|
+
cursor.moveToMark(this.mark);
|
|
1034
752
|
return false;
|
|
1035
753
|
}
|
|
1036
|
-
}
|
|
1037
|
-
_hasMorePatterns() {
|
|
1038
|
-
return this.index + 1 < this._children.length;
|
|
1039
|
-
}
|
|
1040
|
-
_assertRestOfPatternsAreOptional() {
|
|
1041
|
-
const areTheRestOptional = this.children.every((pattern, index) => {
|
|
1042
|
-
return (index <= this.index ||
|
|
1043
|
-
pattern instanceof OptionalValue ||
|
|
1044
|
-
pattern instanceof OptionalComposite);
|
|
1045
|
-
});
|
|
1046
|
-
if (!areTheRestOptional) {
|
|
1047
|
-
const parseError = new ParseError(`Could not match ${this.name} before string ran out.`, this.index, this);
|
|
1048
|
-
this.cursor.throwError(parseError);
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
_processValue() {
|
|
1052
|
-
if (!this.cursor.hasUnresolvedError()) {
|
|
1053
|
-
this.nodes = this.nodes.filter((node) => node != null);
|
|
1054
|
-
const lastNode = this.nodes[this.nodes.length - 1];
|
|
1055
|
-
const startIndex = this.mark;
|
|
1056
|
-
const endIndex = lastNode.endIndex;
|
|
1057
|
-
this.node = new CompositeNode("and-composite", this.name, startIndex, endIndex);
|
|
1058
|
-
this.node.children = this.nodes;
|
|
1059
|
-
this.cursor.index = this.node.endIndex;
|
|
1060
|
-
this.cursor.addMatch(this, this.node);
|
|
1061
|
-
}
|
|
1062
754
|
else {
|
|
1063
|
-
this.
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
clone(name) {
|
|
1067
|
-
if (typeof name !== "string") {
|
|
1068
|
-
name = this.name;
|
|
1069
|
-
}
|
|
1070
|
-
return new AndComposite(name, this._children);
|
|
1071
|
-
}
|
|
1072
|
-
getTokens() {
|
|
1073
|
-
let tokens = [];
|
|
1074
|
-
for (let x = 0; x < this._children.length; x++) {
|
|
1075
|
-
const child = this._children[x];
|
|
1076
|
-
if (child instanceof OptionalValue ||
|
|
1077
|
-
child instanceof OptionalComposite) {
|
|
1078
|
-
tokens = tokens.concat(child.getTokens());
|
|
1079
|
-
}
|
|
1080
|
-
else {
|
|
1081
|
-
tokens = tokens.concat(child.getTokens());
|
|
1082
|
-
break;
|
|
755
|
+
if (this._isOptional) {
|
|
756
|
+
cursor.resolveError();
|
|
757
|
+
cursor.moveToMark(this.mark);
|
|
1083
758
|
}
|
|
759
|
+
this.node = null;
|
|
760
|
+
return true;
|
|
1084
761
|
}
|
|
1085
|
-
return tokens;
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
class OrComposite extends CompositePattern {
|
|
1090
|
-
constructor(name, patterns) {
|
|
1091
|
-
super("or-composite", name, patterns);
|
|
1092
|
-
this._assertArguments();
|
|
1093
|
-
}
|
|
1094
|
-
_assertArguments() {
|
|
1095
|
-
if (this._children.length < 2) {
|
|
1096
|
-
throw new Error("Invalid Argument: OrValue needs to have more than one value pattern.");
|
|
1097
|
-
}
|
|
1098
|
-
const hasOptionalChildren = this._children.some((pattern) => pattern instanceof OptionalValue || pattern instanceof OptionalComposite);
|
|
1099
|
-
if (hasOptionalChildren) {
|
|
1100
|
-
throw new Error("OrComposite cannot have optional values.");
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
_reset(cursor) {
|
|
1104
|
-
this.cursor = cursor;
|
|
1105
|
-
this.mark = null;
|
|
1106
|
-
this.index = 0;
|
|
1107
|
-
this.node = null;
|
|
1108
|
-
this.mark = cursor.mark();
|
|
1109
|
-
}
|
|
1110
|
-
parse(cursor) {
|
|
1111
|
-
this._reset(cursor);
|
|
1112
|
-
this._tryPattern();
|
|
1113
|
-
if (this.node != null) {
|
|
1114
|
-
this.cursor.addMatch(this, this.node);
|
|
1115
|
-
}
|
|
1116
|
-
return this.node;
|
|
1117
762
|
}
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
if (this.index + 1 < this._children.length) {
|
|
1124
|
-
this.cursor.resolveError();
|
|
1125
|
-
this.index++;
|
|
1126
|
-
this.cursor.moveToMark(this.mark);
|
|
1127
|
-
}
|
|
1128
|
-
else {
|
|
1129
|
-
this.node = null;
|
|
1130
|
-
break;
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
else {
|
|
1134
|
-
this.cursor.index = this.node.endIndex;
|
|
1135
|
-
break;
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
763
|
+
processResult(node) {
|
|
764
|
+
const cursor = this.safelyGetCursor();
|
|
765
|
+
this.node = new Node("or", this.name, node.startIndex, node.endIndex, [node], node.value);
|
|
766
|
+
cursor.index = this.node.endIndex;
|
|
767
|
+
cursor.addMatch(this, this.node);
|
|
1138
768
|
}
|
|
1139
|
-
clone(name) {
|
|
1140
|
-
if (
|
|
769
|
+
clone(name, isOptional) {
|
|
770
|
+
if (name == null) {
|
|
1141
771
|
name = this.name;
|
|
1142
772
|
}
|
|
1143
|
-
|
|
773
|
+
if (isOptional == null) {
|
|
774
|
+
isOptional = this._isOptional;
|
|
775
|
+
}
|
|
776
|
+
return new Or(name, this._children, isOptional);
|
|
1144
777
|
}
|
|
1145
778
|
getTokens() {
|
|
1146
|
-
|
|
1147
|
-
const hasPrimitiveTokens = tokens.every((t) => t.every((value) => typeof value === "string"));
|
|
1148
|
-
if (hasPrimitiveTokens && tokens.length > 0) {
|
|
1149
|
-
return tokens.reduce((acc, t) => acc.concat(t), []);
|
|
1150
|
-
}
|
|
1151
|
-
return this._children[0].getTokens();
|
|
779
|
+
return this._children.reduce((acc, c) => acc.concat(c.getTokens()), []);
|
|
1152
780
|
}
|
|
1153
781
|
}
|
|
1154
782
|
|
|
1155
|
-
class
|
|
1156
|
-
constructor(name, pattern, divider) {
|
|
1157
|
-
super("repeat
|
|
783
|
+
class Repeat extends Pattern {
|
|
784
|
+
constructor(name, pattern, divider, isOptional = false) {
|
|
785
|
+
super("repeat", name, divider != null ? [pattern, divider] : [pattern], isOptional);
|
|
1158
786
|
this.nodes = [];
|
|
1159
787
|
this.mark = 0;
|
|
1160
788
|
this.node = null;
|
|
1161
789
|
this._pattern = this.children[0];
|
|
1162
790
|
this._divider = this.children[1];
|
|
1163
|
-
this.
|
|
791
|
+
this.assertArguments();
|
|
1164
792
|
}
|
|
1165
|
-
|
|
1166
|
-
if (this._pattern
|
|
793
|
+
assertArguments() {
|
|
794
|
+
if (this._pattern.isOptional) {
|
|
1167
795
|
throw new Error("Invalid Arguments: The pattern cannot be a optional pattern.");
|
|
1168
796
|
}
|
|
1169
797
|
}
|
|
@@ -1174,91 +802,108 @@ class RepeatComposite extends CompositePattern {
|
|
|
1174
802
|
}
|
|
1175
803
|
parse(cursor) {
|
|
1176
804
|
this._reset(cursor);
|
|
1177
|
-
this.
|
|
805
|
+
this.tryToParse();
|
|
1178
806
|
return this.node;
|
|
1179
807
|
}
|
|
1180
|
-
|
|
808
|
+
tryToParse() {
|
|
809
|
+
const cursor = this.safelyGetCursor();
|
|
1181
810
|
while (true) {
|
|
1182
|
-
const node = this._pattern.parse(
|
|
1183
|
-
if (
|
|
1184
|
-
this.
|
|
811
|
+
const node = this._pattern.parse(cursor);
|
|
812
|
+
if (cursor.hasUnresolvedError()) {
|
|
813
|
+
this.processResult();
|
|
1185
814
|
break;
|
|
1186
815
|
}
|
|
1187
|
-
else {
|
|
816
|
+
else if (node != null) {
|
|
1188
817
|
this.nodes.push(node);
|
|
1189
|
-
if (node.endIndex ===
|
|
1190
|
-
this.
|
|
818
|
+
if (node.endIndex === cursor.lastIndex()) {
|
|
819
|
+
this.processResult();
|
|
1191
820
|
break;
|
|
1192
821
|
}
|
|
1193
|
-
|
|
822
|
+
cursor.next();
|
|
1194
823
|
if (this._divider != null) {
|
|
1195
|
-
const mark =
|
|
1196
|
-
const node = this._divider.parse(
|
|
1197
|
-
if (
|
|
1198
|
-
|
|
1199
|
-
this.
|
|
824
|
+
const mark = cursor.mark();
|
|
825
|
+
const node = this._divider.parse(cursor);
|
|
826
|
+
if (cursor.hasUnresolvedError()) {
|
|
827
|
+
cursor.moveToMark(mark);
|
|
828
|
+
this.processResult();
|
|
1200
829
|
break;
|
|
1201
830
|
}
|
|
1202
|
-
else {
|
|
831
|
+
else if (node != null) {
|
|
1203
832
|
this.nodes.push(node);
|
|
1204
|
-
if (node.endIndex ===
|
|
1205
|
-
this.
|
|
833
|
+
if (node.endIndex === cursor.lastIndex()) {
|
|
834
|
+
this.processResult();
|
|
1206
835
|
break;
|
|
1207
836
|
}
|
|
1208
|
-
|
|
837
|
+
cursor.next();
|
|
1209
838
|
}
|
|
1210
839
|
}
|
|
1211
840
|
}
|
|
1212
841
|
}
|
|
1213
842
|
}
|
|
1214
|
-
|
|
843
|
+
processResult() {
|
|
1215
844
|
const endsOnDivider = this.nodes.length % 2 === 0;
|
|
1216
845
|
const noMatch = this.nodes.length === 0;
|
|
1217
846
|
const hasDivider = this._divider != null;
|
|
1218
847
|
this.cursor.resolveError();
|
|
1219
848
|
if ((hasDivider && endsOnDivider) || noMatch) {
|
|
1220
|
-
|
|
849
|
+
if (this._isOptional) {
|
|
850
|
+
this.cursor.moveToMark(this.mark);
|
|
851
|
+
}
|
|
852
|
+
else {
|
|
853
|
+
const parseError = new ParseError(`Did not find a repeating match of ${this.name}.`, this.mark, this);
|
|
854
|
+
this.cursor.throwError(parseError);
|
|
855
|
+
}
|
|
1221
856
|
this.node = null;
|
|
1222
857
|
}
|
|
1223
858
|
else {
|
|
1224
|
-
|
|
1225
|
-
this.node
|
|
859
|
+
const value = this.nodes.map((node) => node.value).join("");
|
|
860
|
+
this.node = new Node("repeat", this.name, this.nodes[0].startIndex, this.nodes[this.nodes.length - 1].endIndex, this.nodes, value);
|
|
1226
861
|
this.cursor.index = this.node.endIndex;
|
|
1227
862
|
this.cursor.addMatch(this, this.node);
|
|
1228
863
|
}
|
|
1229
864
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
865
|
+
safelyGetCursor() {
|
|
866
|
+
const cursor = this.cursor;
|
|
867
|
+
if (cursor == null) {
|
|
868
|
+
throw new Error("Couldn't find cursor.");
|
|
869
|
+
}
|
|
870
|
+
return cursor;
|
|
871
|
+
}
|
|
872
|
+
clone(name, isOptional) {
|
|
873
|
+
if (name == null) {
|
|
1232
874
|
name = this.name;
|
|
1233
875
|
}
|
|
1234
|
-
|
|
876
|
+
if (isOptional == null) {
|
|
877
|
+
isOptional = this._isOptional;
|
|
878
|
+
}
|
|
879
|
+
return new Repeat(name, this._pattern, this._divider, isOptional);
|
|
1235
880
|
}
|
|
1236
881
|
getTokens() {
|
|
1237
882
|
return this._pattern.getTokens();
|
|
1238
883
|
}
|
|
1239
884
|
}
|
|
1240
885
|
|
|
1241
|
-
class
|
|
1242
|
-
constructor(name) {
|
|
1243
|
-
super("recursive", name);
|
|
886
|
+
class Recursive extends Pattern {
|
|
887
|
+
constructor(name, isOptional = false) {
|
|
888
|
+
super("recursive", name, [], isOptional);
|
|
1244
889
|
this.pattern = null;
|
|
1245
890
|
this.isRecursing = false;
|
|
1246
891
|
}
|
|
1247
892
|
getPattern() {
|
|
1248
|
-
return this.
|
|
893
|
+
return this.climb(this.parent, (pattern) => {
|
|
1249
894
|
if (pattern == null) {
|
|
1250
895
|
return false;
|
|
1251
896
|
}
|
|
1252
897
|
return pattern.name === this.name;
|
|
1253
898
|
});
|
|
1254
899
|
}
|
|
1255
|
-
|
|
900
|
+
climb(pattern, isMatch) {
|
|
1256
901
|
if (isMatch(pattern)) {
|
|
1257
902
|
return pattern;
|
|
1258
903
|
}
|
|
1259
904
|
else {
|
|
1260
905
|
if (pattern && pattern.parent != null) {
|
|
1261
|
-
return this.
|
|
906
|
+
return this.climb(pattern.parent, isMatch);
|
|
1262
907
|
}
|
|
1263
908
|
return null;
|
|
1264
909
|
}
|
|
@@ -1267,23 +912,33 @@ class RecursivePattern extends Pattern {
|
|
|
1267
912
|
if (this.pattern == null) {
|
|
1268
913
|
const pattern = this.getPattern();
|
|
1269
914
|
if (pattern == null) {
|
|
1270
|
-
|
|
915
|
+
if (!this._isOptional) {
|
|
916
|
+
cursor.throwError(new ParseError(`Couldn't find parent pattern to recursively parse, with the name ${this.name}.`, cursor.index, this));
|
|
917
|
+
}
|
|
1271
918
|
return null;
|
|
1272
919
|
}
|
|
1273
920
|
this.pattern = pattern.clone();
|
|
1274
921
|
this.pattern.parent = this;
|
|
1275
922
|
}
|
|
923
|
+
const mark = cursor.mark();
|
|
1276
924
|
const node = this.pattern.parse(cursor);
|
|
1277
925
|
if (!cursor.hasUnresolvedError() && node != null) {
|
|
1278
926
|
cursor.addMatch(this, node);
|
|
1279
927
|
}
|
|
928
|
+
if (cursor.hasUnresolvedError() && this._isOptional) {
|
|
929
|
+
cursor.resolveError();
|
|
930
|
+
cursor.moveToMark(mark);
|
|
931
|
+
}
|
|
1280
932
|
return node;
|
|
1281
933
|
}
|
|
1282
|
-
clone(name) {
|
|
1283
|
-
if (
|
|
934
|
+
clone(name, isOptional) {
|
|
935
|
+
if (name == null) {
|
|
1284
936
|
name = this.name;
|
|
1285
937
|
}
|
|
1286
|
-
|
|
938
|
+
if (isOptional == null) {
|
|
939
|
+
isOptional = this._isOptional;
|
|
940
|
+
}
|
|
941
|
+
return new Recursive(name, isOptional);
|
|
1287
942
|
}
|
|
1288
943
|
getTokenValue() {
|
|
1289
944
|
var _a;
|
|
@@ -1301,6 +956,108 @@ class RecursivePattern extends Pattern {
|
|
|
1301
956
|
}
|
|
1302
957
|
}
|
|
1303
958
|
|
|
959
|
+
class Reference extends Pattern {
|
|
960
|
+
constructor(name, isOptional = false) {
|
|
961
|
+
super("reference", name, [], isOptional);
|
|
962
|
+
this.isRecursing = false;
|
|
963
|
+
}
|
|
964
|
+
getRoot() {
|
|
965
|
+
let node = this.parent;
|
|
966
|
+
while (node != null) {
|
|
967
|
+
if (node.parent == null) {
|
|
968
|
+
return node;
|
|
969
|
+
}
|
|
970
|
+
node = node.parent;
|
|
971
|
+
}
|
|
972
|
+
return node;
|
|
973
|
+
}
|
|
974
|
+
findPattern() {
|
|
975
|
+
const root = this.getRoot();
|
|
976
|
+
let result = null;
|
|
977
|
+
if (root == null) {
|
|
978
|
+
return null;
|
|
979
|
+
}
|
|
980
|
+
this.walkTheTree(root, (pattern) => {
|
|
981
|
+
if (pattern.name === this.name &&
|
|
982
|
+
pattern != this &&
|
|
983
|
+
pattern.type != "reference") {
|
|
984
|
+
result = pattern;
|
|
985
|
+
return false;
|
|
986
|
+
}
|
|
987
|
+
return true;
|
|
988
|
+
});
|
|
989
|
+
return result;
|
|
990
|
+
}
|
|
991
|
+
walkTheTree(pattern, callback) {
|
|
992
|
+
for (let x = 0; x < pattern.children.length; x++) {
|
|
993
|
+
const p = pattern.children[x];
|
|
994
|
+
const continueWalking = this.walkTheTree(p, callback);
|
|
995
|
+
if (!continueWalking) {
|
|
996
|
+
return false;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
return callback(pattern);
|
|
1000
|
+
}
|
|
1001
|
+
parse(cursor) {
|
|
1002
|
+
const mark = cursor.mark();
|
|
1003
|
+
try {
|
|
1004
|
+
const node = this.safelyGetPattern().parse(cursor);
|
|
1005
|
+
if (!cursor.hasUnresolvedError() && node != null) {
|
|
1006
|
+
cursor.addMatch(this, node);
|
|
1007
|
+
}
|
|
1008
|
+
if (cursor.hasUnresolvedError() && this._isOptional) {
|
|
1009
|
+
cursor.resolveError();
|
|
1010
|
+
cursor.moveToMark(mark);
|
|
1011
|
+
}
|
|
1012
|
+
return node;
|
|
1013
|
+
}
|
|
1014
|
+
catch (error) {
|
|
1015
|
+
if (this._isOptional) {
|
|
1016
|
+
cursor.moveToMark(mark);
|
|
1017
|
+
}
|
|
1018
|
+
else {
|
|
1019
|
+
cursor.throwError(new ParseError(`Couldn't find reference pattern to parse, with the name ${this.name}.`, cursor.index, this));
|
|
1020
|
+
}
|
|
1021
|
+
return null;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
clone(name, isOptional) {
|
|
1025
|
+
if (name == null) {
|
|
1026
|
+
name = this.name;
|
|
1027
|
+
}
|
|
1028
|
+
if (isOptional == null) {
|
|
1029
|
+
isOptional = this._isOptional;
|
|
1030
|
+
}
|
|
1031
|
+
return new Reference(name, isOptional);
|
|
1032
|
+
}
|
|
1033
|
+
getTokenValue() {
|
|
1034
|
+
return this.safelyGetPattern().getTokenValue();
|
|
1035
|
+
}
|
|
1036
|
+
safelyGetPattern() {
|
|
1037
|
+
let pattern = this.children[0];
|
|
1038
|
+
const hasNoPattern = pattern == null;
|
|
1039
|
+
if (hasNoPattern) {
|
|
1040
|
+
const reference = this.findPattern();
|
|
1041
|
+
if (reference == null) {
|
|
1042
|
+
throw new Error(`Couldn't find reference pattern, with the name ${this.name}.`);
|
|
1043
|
+
}
|
|
1044
|
+
pattern = reference;
|
|
1045
|
+
this.children = [pattern];
|
|
1046
|
+
}
|
|
1047
|
+
return pattern;
|
|
1048
|
+
}
|
|
1049
|
+
getTokens() {
|
|
1050
|
+
if (!this.isRecursing) {
|
|
1051
|
+
this.isRecursing = true;
|
|
1052
|
+
let pattern = this.safelyGetPattern();
|
|
1053
|
+
const tokens = pattern.getTokens();
|
|
1054
|
+
this.isRecursing = false;
|
|
1055
|
+
return tokens;
|
|
1056
|
+
}
|
|
1057
|
+
return [];
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1304
1061
|
class TextSuggester {
|
|
1305
1062
|
constructor() {
|
|
1306
1063
|
this.cursor = null;
|
|
@@ -1552,10 +1309,10 @@ class Visitor {
|
|
|
1552
1309
|
}
|
|
1553
1310
|
flatten() {
|
|
1554
1311
|
this.selectedNodes.forEach((node) => {
|
|
1555
|
-
if (node.
|
|
1312
|
+
if (node.children.length > 0) {
|
|
1556
1313
|
const children = [];
|
|
1557
1314
|
Visitor.walkUp(node, (descendant) => {
|
|
1558
|
-
if (
|
|
1315
|
+
if (descendant.children.length === 0) {
|
|
1559
1316
|
children.push(descendant);
|
|
1560
1317
|
}
|
|
1561
1318
|
});
|
|
@@ -1573,15 +1330,13 @@ class Visitor {
|
|
|
1573
1330
|
}
|
|
1574
1331
|
recursiveRemove(node) {
|
|
1575
1332
|
const nodesToRemove = this.selectedNodes;
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
this.recursiveRemove(node.children[x]);
|
|
1584
|
-
}
|
|
1333
|
+
for (let x = 0; x < node.children.length; x++) {
|
|
1334
|
+
if (nodesToRemove.indexOf(node.children[x]) > -1) {
|
|
1335
|
+
node.children.splice(x, 1);
|
|
1336
|
+
x--;
|
|
1337
|
+
}
|
|
1338
|
+
else {
|
|
1339
|
+
this.recursiveRemove(node.children[x]);
|
|
1585
1340
|
}
|
|
1586
1341
|
}
|
|
1587
1342
|
}
|
|
@@ -1654,11 +1409,9 @@ class Visitor {
|
|
|
1654
1409
|
return this;
|
|
1655
1410
|
}
|
|
1656
1411
|
recursiveTransform(node, callback) {
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
node.children[x] = this.recursiveTransform(node.children[x], callback);
|
|
1661
|
-
}
|
|
1412
|
+
const length = node.children.length;
|
|
1413
|
+
for (let x = 0; x < length; x++) {
|
|
1414
|
+
node.children[x] = this.recursiveTransform(node.children[x], callback);
|
|
1662
1415
|
}
|
|
1663
1416
|
return callback(node);
|
|
1664
1417
|
}
|
|
@@ -1678,7 +1431,7 @@ class Visitor {
|
|
|
1678
1431
|
}
|
|
1679
1432
|
const node = this.root;
|
|
1680
1433
|
const selectedNodes = [];
|
|
1681
|
-
if (node.
|
|
1434
|
+
if (node.children.length > 0) {
|
|
1682
1435
|
Visitor.walkDown(node, (descendant) => {
|
|
1683
1436
|
if (callback(descendant)) {
|
|
1684
1437
|
selectedNodes.push(descendant);
|
|
@@ -1734,7 +1487,7 @@ class Visitor {
|
|
|
1734
1487
|
}
|
|
1735
1488
|
static walkUp(node, callback, ancestors = []) {
|
|
1736
1489
|
ancestors.push(node);
|
|
1737
|
-
if (node.
|
|
1490
|
+
if (node.children.length > 0) {
|
|
1738
1491
|
const children = node.children.slice();
|
|
1739
1492
|
children.forEach((c) => this.walkUp(c, callback, ancestors));
|
|
1740
1493
|
}
|
|
@@ -1745,7 +1498,7 @@ class Visitor {
|
|
|
1745
1498
|
static walkDown(node, callback, ancestors = []) {
|
|
1746
1499
|
callback(node, ancestors);
|
|
1747
1500
|
ancestors.push(node);
|
|
1748
|
-
if (node.
|
|
1501
|
+
if (node.children.length > 0) {
|
|
1749
1502
|
const children = node.children.slice();
|
|
1750
1503
|
children.forEach((c) => this.walkDown(c, callback, ancestors));
|
|
1751
1504
|
}
|
|
@@ -1754,5 +1507,5 @@ class Visitor {
|
|
|
1754
1507
|
}
|
|
1755
1508
|
}
|
|
1756
1509
|
|
|
1757
|
-
export {
|
|
1510
|
+
export { And, Cursor, Literal, LookAhead, Node, Not, Or, ParseError, Pattern, Recursive, Reference, Regex, Repeat, TextSuggester, Visitor };
|
|
1758
1511
|
//# sourceMappingURL=index.esm.js.map
|