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