clarity-pattern-parser 3.0.15 → 3.0.16

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.
@@ -0,0 +1,123 @@
1
+ import Pattern from "./Pattern";
2
+ import ParserError from "./ParseError";
3
+ import Cursor from "../Cursor";
4
+
5
+ export default class ReferencePattern extends Pattern {
6
+ private isRecursing: boolean;
7
+
8
+ constructor(name: string) {
9
+ super("reference", name);
10
+ this.isRecursing = false;
11
+ }
12
+
13
+ private getRoot() {
14
+ let node = this.parent;
15
+ while (node != null) {
16
+ if (node.parent == null) {
17
+ return node;
18
+ }
19
+ node = node.parent;
20
+ }
21
+ return node;
22
+ }
23
+
24
+ private findPattern(): Pattern | null {
25
+ const root = this.getRoot();
26
+ let result: Pattern | null = null;
27
+
28
+ if (root == null) {
29
+ return null;
30
+ }
31
+
32
+ this.walkTheTree(root, (pattern) => {
33
+ if (
34
+ pattern.name === this.name &&
35
+ pattern != this &&
36
+ pattern.type != "reference"
37
+ ) {
38
+ result = pattern;
39
+ return false;
40
+ }
41
+ return true;
42
+ });
43
+
44
+ return result;
45
+ }
46
+
47
+ private walkTheTree(
48
+ pattern: Pattern,
49
+ callback: (pattern: Pattern) => boolean
50
+ ) {
51
+ for (let x = 0; x < pattern.children.length; x++) {
52
+ const p = pattern.children[x];
53
+ const continueWalking = this.walkTheTree(p, callback);
54
+
55
+ if (!continueWalking) {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ return callback(pattern);
61
+ }
62
+
63
+ parse(cursor: Cursor) {
64
+ try {
65
+ const node = this.safelyGetPattern().parse(cursor);
66
+
67
+ if (!cursor.hasUnresolvedError() && node != null) {
68
+ cursor.addMatch(this, node);
69
+ }
70
+
71
+ return node;
72
+ } catch (error) {
73
+ cursor.throwError(
74
+ new ParserError(
75
+ `Couldn't find reference pattern to parse, with the name ${this.name}.`,
76
+ cursor.index,
77
+ this as Pattern
78
+ )
79
+ );
80
+
81
+ return null;
82
+ }
83
+ }
84
+
85
+ clone(name?: string): Pattern {
86
+ if (typeof name !== "string") {
87
+ name = this.name;
88
+ }
89
+ return new ReferencePattern(name);
90
+ }
91
+
92
+ getTokenValue() {
93
+ return this.safelyGetPattern().getTokenValue();
94
+ }
95
+
96
+ private safelyGetPattern() {
97
+ let pattern = this.children[0];
98
+ const hasNoPattern = pattern == null;
99
+
100
+ if (hasNoPattern) {
101
+ const reference = this.findPattern();
102
+ if (reference == null) {
103
+ throw new Error(
104
+ `Couldn't find reference pattern, with the name ${this.name}.`
105
+ );
106
+ }
107
+
108
+ return reference;
109
+ }
110
+ return pattern;
111
+ }
112
+
113
+ getTokens() {
114
+ if (!this.isRecursing) {
115
+ this.isRecursing = true;
116
+ let pattern = this.safelyGetPattern();
117
+ const tokens = pattern.getTokens();
118
+ this.isRecursing = false;
119
+ return tokens;
120
+ }
121
+ return [];
122
+ }
123
+ }
@@ -3,7 +3,6 @@ import ValueNode from "../../ast/ValueNode";
3
3
  import ParseError from "../../patterns/ParseError";
4
4
  import OptionalValue from "./OptionalValue";
5
5
  import Permutor from "../../Permutor";
6
- import Pattern from "../Pattern";
7
6
  import Cursor from "../../Cursor";
8
7
 
9
8
  const permutor = new Permutor();
@@ -0,0 +1,93 @@
1
+ /** @jest-environment node */
2
+ import Literal from "../patterns/value/Literal";
3
+ import Cursor from "../Cursor";
4
+ import LookAhead from "../patterns/LookAhead";
5
+ import NotValue from "../patterns/value/NotValue";
6
+ import OrValue from "../patterns/value/OrValue";
7
+ import RegexValue from "../patterns/value/RegexValue";
8
+ import AndValue from "../patterns/value/AndValue";
9
+
10
+ describe("LookAheadValue", () => {
11
+ test("Look for pattern.", () => {
12
+ const john = new Literal("john", "John");
13
+ const lookAheadValue = new LookAhead(john);
14
+ const cursor = new Cursor("John");
15
+ const node = lookAheadValue.parse(cursor);
16
+
17
+ expect(node).toBe(null);
18
+ expect(cursor.hasUnresolvedError()).toBe(false);
19
+ });
20
+
21
+ test("Look for a not pattern.", () => {
22
+ const john = new Literal("john", "John");
23
+ const lookAheadValue = new LookAhead(new NotValue("not-john", john));
24
+ const cursor = new Cursor("Joel");
25
+ const node = lookAheadValue.parse(cursor);
26
+
27
+ expect(node).toBe(null);
28
+ expect(cursor.hasUnresolvedError()).toBe(false);
29
+ });
30
+
31
+ test("Fail looking for a pattern.", () => {
32
+ const john = new Literal("john", "John");
33
+ const lookAheadValue = new LookAhead(john);
34
+ const cursor = new Cursor("Joel");
35
+ const node = lookAheadValue.parse(cursor);
36
+
37
+ expect(node).toBe(null);
38
+ expect(cursor.hasUnresolvedError()).toBe(true);
39
+ });
40
+
41
+ test("And a look ahead together.", () => {
42
+ const john = new Literal("john", "John");
43
+ const lookAheadValue = new LookAhead(john);
44
+ const cursor = new Cursor("Joel");
45
+ const node = lookAheadValue.parse(cursor);
46
+
47
+ expect(node).toBe(null);
48
+ expect(cursor.hasUnresolvedError()).toBe(true);
49
+ });
50
+
51
+ test("Negate pattern with literal.", () => {
52
+ const greaterThan = new Literal("greater-than", ">");
53
+ const lessThan = new Literal("less-than", "<");
54
+ const from = new Literal("from", "FROM");
55
+ const table = new Literal("table", "Table");
56
+ const operator = new OrValue("operator", [lessThan, greaterThan]);
57
+ const keywords = new AndValue("keywords-with-space", [
58
+ new OrValue("keywords", [from, table]),
59
+ new Literal("space", " "),
60
+ ]);
61
+ const identFirstPart = new RegexValue(
62
+ "ident-first-part",
63
+ "[a-zA-Z_$][a-zA-Z0-9_]*"
64
+ );
65
+ const identity = new AndValue("identity", [
66
+ new LookAhead(new NotValue("not-keywords", keywords)),
67
+ new LookAhead(new NotValue("not-operator", operator)),
68
+ identFirstPart,
69
+ ]);
70
+
71
+ const result = identity.parse(new Cursor("_goodName"));
72
+
73
+ expect(result).not.toBeNull();
74
+
75
+ const cursor1 = new Cursor("<badName");
76
+ const result1 = identity.parse(cursor1);
77
+
78
+ expect(result1).toBe(null);
79
+ expect(cursor1.hasUnresolvedError()).toBe(true);
80
+
81
+ const cursor2 = new Cursor("FROM_IS_OKAY");
82
+ const result2 = identity.parse(cursor2);
83
+
84
+ expect(result2).not.toBe(null);
85
+ expect(cursor2.hasUnresolvedError()).toBe(false);
86
+
87
+ const cursor3 = new Cursor("FROM ISBAD");
88
+ const result3 = identity.parse(cursor3);
89
+
90
+ expect(result3).toBe(null);
91
+ expect(cursor3.hasUnresolvedError()).toBe(true);
92
+ });
93
+ });
@@ -2,6 +2,10 @@
2
2
  import NotValue from "../patterns/value/NotValue";
3
3
  import Literal from "../patterns/value/Literal";
4
4
  import Cursor from "../Cursor";
5
+ import OrValue from "../patterns/value/OrValue";
6
+ import AndValue from "../patterns/value/AndValue";
7
+ import RepeatValue from "../patterns/value/RepeatValue";
8
+ import RegexValue from "../patterns/value/RegexValue";
5
9
 
6
10
  describe("NotValue", () => {
7
11
  test("Empty Constructor.", () => {
@@ -66,4 +70,7 @@ describe("NotValue", () => {
66
70
 
67
71
  expect(notJohn.name).toBe(clone.name);
68
72
  });
73
+
74
+
75
+
69
76
  });
@@ -211,9 +211,8 @@ describe("ValuePattern", () => {
211
211
  expect(tokens[1]).toBe("Doe");
212
212
 
213
213
  tokens = fullName.children[1].children[1].getNextTokens();
214
- expect(tokens.length).toBe(2);
214
+ expect(tokens.length).toBe(1);
215
215
  expect(tokens[0]).toBe("Edward");
216
- expect(tokens[1]).toBe("Doe");
217
216
  });
218
217
 
219
218
  test("getNextTokens, has child and at the beginning.", () => {
@@ -0,0 +1,24 @@
1
+ import Cursor from "../Cursor";
2
+ import ReferencePattern from "../patterns/ReferencePattern";
3
+ import AndValue from "../patterns/value/AndValue";
4
+ import Literal from "../patterns/value/Literal";
5
+ import OrValue from "../patterns/value/OrValue";
6
+
7
+ describe("ReferencePattern", () => {
8
+ test("Reference to node in different branch.", () => {
9
+ const a = new Literal("a", "a");
10
+ const b = new Literal("b", "b");
11
+ const c = new Literal("c", "c");
12
+ const a_b_c = new AndValue("a-and-b-and-c", [
13
+ a,
14
+ b,
15
+ new ReferencePattern("c"),
16
+ ]);
17
+ const b_c = new AndValue("b-and-c", [b, c]);
18
+ const main = new OrValue("main", [a_b_c, b_c]);
19
+
20
+ const result = main.parse(new Cursor("abc"));
21
+
22
+ expect(result).not.toBeNull();
23
+ });
24
+ });
@@ -75,3 +75,5 @@ const json = new OrComposite("literals", [
75
75
  ]);
76
76
 
77
77
  export default json;
78
+
79
+