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