clarity-pattern-parser 10.3.7 → 11.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/dist/ast/Node.d.ts +2 -2
- package/dist/ast/compact.d.ts +2 -0
- package/dist/ast/remove.d.ts +2 -0
- package/dist/index.browser.js +417 -487
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.esm.js +416 -488
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +417 -487
- package/dist/index.js.map +1 -1
- package/dist/patterns/ExpressionPattern.d.ts +27 -25
- package/dist/patterns/FiniteRepeat.d.ts +1 -2
- package/dist/patterns/InfiniteRepeat.d.ts +1 -2
- package/dist/patterns/Literal.d.ts +0 -1
- package/dist/patterns/Not.d.ts +1 -2
- package/dist/patterns/Optional.d.ts +0 -1
- package/dist/patterns/Options.d.ts +1 -2
- package/dist/patterns/Pattern.d.ts +0 -1
- package/dist/patterns/PrecedenceTree.d.ts +28 -0
- package/dist/patterns/Reference.d.ts +1 -2
- package/dist/patterns/Regex.d.ts +1 -2
- package/dist/patterns/Repeat.d.ts +0 -3
- package/dist/patterns/Sequence.d.ts +3 -6
- package/dist/patterns/execPattern.d.ts +3 -0
- package/dist/patterns/testPattern.d.ts +2 -0
- package/package.json +1 -1
- package/src/ast/Node.test.ts +17 -17
- package/src/ast/Node.ts +7 -5
- package/src/ast/compact.ts +11 -0
- package/src/ast/remove.ts +11 -0
- package/src/grammar/Grammar.test.ts +0 -50
- package/src/grammar/Grammar.ts +0 -20
- package/src/grammar/patterns/statement.ts +1 -6
- package/src/index.ts +4 -0
- package/src/patterns/ExpressionPattern.test.ts +1 -1
- package/src/patterns/ExpressionPattern.ts +235 -384
- package/src/patterns/FiniteRepeat.ts +5 -22
- package/src/patterns/InfiniteRepeat.ts +6 -21
- package/src/patterns/Literal.ts +5 -19
- package/src/patterns/Not.ts +5 -16
- package/src/patterns/Optional.ts +0 -7
- package/src/patterns/Options.ts +5 -21
- package/src/patterns/Pattern.ts +0 -1
- package/src/patterns/PrecedenceTree.test.ts +162 -0
- package/src/patterns/PrecedenceTree.ts +207 -0
- package/src/patterns/Reference.ts +5 -17
- package/src/patterns/Regex.ts +5 -17
- package/src/patterns/Repeat.ts +1 -13
- package/src/patterns/Sequence.ts +7 -22
- package/src/patterns/execPattern.ts +16 -0
- package/src/patterns/testPattern.ts +11 -0
|
@@ -3,6 +3,8 @@ import { Cursor } from "./Cursor";
|
|
|
3
3
|
import { findPattern } from "./findPattern";
|
|
4
4
|
import { ParseResult } from "./ParseResult";
|
|
5
5
|
import { Pattern } from "./Pattern";
|
|
6
|
+
import { testPattern } from './testPattern';
|
|
7
|
+
import { execPattern } from "./execPattern";
|
|
6
8
|
|
|
7
9
|
let idIndex = 0;
|
|
8
10
|
|
|
@@ -25,8 +27,6 @@ export class FiniteRepeat implements Pattern {
|
|
|
25
27
|
private _trimDivider: boolean;
|
|
26
28
|
private _firstIndex: number;
|
|
27
29
|
|
|
28
|
-
shouldCompactAst = false;
|
|
29
|
-
|
|
30
30
|
get id() {
|
|
31
31
|
return this._id;
|
|
32
32
|
}
|
|
@@ -152,30 +152,15 @@ export class FiniteRepeat implements Pattern {
|
|
|
152
152
|
|
|
153
153
|
const node = new Node(this._type, this.name, firstIndex, lastIndex, nodes);
|
|
154
154
|
|
|
155
|
-
if (this.shouldCompactAst) {
|
|
156
|
-
node.compact();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
155
|
return node;
|
|
160
156
|
}
|
|
161
157
|
|
|
162
|
-
test(text: string): boolean {
|
|
163
|
-
|
|
164
|
-
const ast = this.parse(cursor);
|
|
165
|
-
|
|
166
|
-
return ast?.value === text;
|
|
158
|
+
test(text: string, record = false): boolean {
|
|
159
|
+
return testPattern(this, text, record);
|
|
167
160
|
}
|
|
168
161
|
|
|
169
162
|
exec(text: string, record = false): ParseResult {
|
|
170
|
-
|
|
171
|
-
record && cursor.startRecording();
|
|
172
|
-
|
|
173
|
-
const ast = this.parse(cursor);
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
ast: ast?.value === text ? ast : null,
|
|
177
|
-
cursor
|
|
178
|
-
};
|
|
163
|
+
return execPattern(this, text, record);
|
|
179
164
|
}
|
|
180
165
|
|
|
181
166
|
clone(name = this._name): Pattern {
|
|
@@ -194,8 +179,6 @@ export class FiniteRepeat implements Pattern {
|
|
|
194
179
|
);
|
|
195
180
|
|
|
196
181
|
clone._id = this._id;
|
|
197
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
198
|
-
|
|
199
182
|
return clone;
|
|
200
183
|
}
|
|
201
184
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Node } from "../ast/Node";
|
|
2
2
|
import { Cursor } from "./Cursor";
|
|
3
3
|
import { Pattern } from "./Pattern";
|
|
4
|
-
import { clonePatterns } from "./clonePatterns";
|
|
5
4
|
import { findPattern } from "./findPattern";
|
|
6
5
|
import { ParseResult } from "./ParseResult";
|
|
6
|
+
import { execPattern } from "./execPattern";
|
|
7
|
+
import { testPattern } from "./testPattern";
|
|
7
8
|
|
|
8
9
|
let idIndex = 0;
|
|
9
10
|
|
|
@@ -26,8 +27,6 @@ export class InfiniteRepeat implements Pattern {
|
|
|
26
27
|
private _min: number;
|
|
27
28
|
private _trimDivider: boolean;
|
|
28
29
|
|
|
29
|
-
shouldCompactAst = false;
|
|
30
|
-
|
|
31
30
|
get id(): string {
|
|
32
31
|
return this._id;
|
|
33
32
|
}
|
|
@@ -56,7 +55,7 @@ export class InfiniteRepeat implements Pattern {
|
|
|
56
55
|
return this._min;
|
|
57
56
|
}
|
|
58
57
|
|
|
59
|
-
get startedOnIndex(){
|
|
58
|
+
get startedOnIndex() {
|
|
60
59
|
return this._firstIndex;
|
|
61
60
|
}
|
|
62
61
|
|
|
@@ -92,23 +91,13 @@ export class InfiniteRepeat implements Pattern {
|
|
|
92
91
|
}
|
|
93
92
|
}
|
|
94
93
|
|
|
95
|
-
test(text: string) {
|
|
96
|
-
const cursor = new Cursor(text);
|
|
97
|
-
const ast = this.parse(cursor);
|
|
98
94
|
|
|
99
|
-
|
|
95
|
+
test(text: string, record = false): boolean {
|
|
96
|
+
return testPattern(this, text, record);
|
|
100
97
|
}
|
|
101
98
|
|
|
102
99
|
exec(text: string, record = false): ParseResult {
|
|
103
|
-
|
|
104
|
-
record && cursor.startRecording();
|
|
105
|
-
|
|
106
|
-
const ast = this.parse(cursor);
|
|
107
|
-
|
|
108
|
-
return {
|
|
109
|
-
ast: ast?.value === text ? ast : null,
|
|
110
|
-
cursor
|
|
111
|
-
};
|
|
100
|
+
return execPattern(this, text, record);
|
|
112
101
|
}
|
|
113
102
|
|
|
114
103
|
parse(cursor: Cursor): Node | null {
|
|
@@ -125,9 +114,6 @@ export class InfiniteRepeat implements Pattern {
|
|
|
125
114
|
cursor.moveTo(node.lastIndex);
|
|
126
115
|
cursor.recordMatch(this, node);
|
|
127
116
|
|
|
128
|
-
if (this.shouldCompactAst) {
|
|
129
|
-
node.compact();
|
|
130
|
-
}
|
|
131
117
|
}
|
|
132
118
|
|
|
133
119
|
return node;
|
|
@@ -362,7 +348,6 @@ export class InfiniteRepeat implements Pattern {
|
|
|
362
348
|
);
|
|
363
349
|
|
|
364
350
|
clone._id = this._id;
|
|
365
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
366
351
|
|
|
367
352
|
return clone;
|
|
368
353
|
}
|
package/src/patterns/Literal.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { Node } from "../ast/Node";
|
|
|
2
2
|
import { Cursor } from "./Cursor";
|
|
3
3
|
import { ParseResult } from "./ParseResult";
|
|
4
4
|
import { Pattern } from "./Pattern";
|
|
5
|
+
import { execPattern } from "./execPattern";
|
|
6
|
+
import { testPattern } from "./testPattern";
|
|
5
7
|
|
|
6
8
|
let idIndex = 0;
|
|
7
9
|
|
|
@@ -16,8 +18,6 @@ export class Literal implements Pattern {
|
|
|
16
18
|
private _lastIndex: number;
|
|
17
19
|
private _endIndex: number;
|
|
18
20
|
|
|
19
|
-
shouldCompactAst = false;
|
|
20
|
-
|
|
21
21
|
get id(): string {
|
|
22
22
|
return this._id;
|
|
23
23
|
}
|
|
@@ -66,25 +66,12 @@ export class Literal implements Pattern {
|
|
|
66
66
|
this._endIndex = 0;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
test(text: string, record = false) {
|
|
70
|
-
|
|
71
|
-
record && cursor.startRecording();
|
|
72
|
-
|
|
73
|
-
const ast = this.parse(cursor);
|
|
74
|
-
|
|
75
|
-
return ast?.value === text;
|
|
69
|
+
test(text: string, record = false): boolean {
|
|
70
|
+
return testPattern(this, text, record);
|
|
76
71
|
}
|
|
77
72
|
|
|
78
73
|
exec(text: string, record = false): ParseResult {
|
|
79
|
-
|
|
80
|
-
record && cursor.startRecording();
|
|
81
|
-
|
|
82
|
-
const ast = this.parse(cursor);
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
ast: ast?.value === text ? ast : null,
|
|
86
|
-
cursor
|
|
87
|
-
};
|
|
74
|
+
return execPattern(this, text, record);
|
|
88
75
|
}
|
|
89
76
|
|
|
90
77
|
parse(cursor: Cursor): Node | null {
|
|
@@ -147,7 +134,6 @@ export class Literal implements Pattern {
|
|
|
147
134
|
clone(name = this._name): Pattern {
|
|
148
135
|
const clone = new Literal(name, this._token);
|
|
149
136
|
clone._id = this._id;
|
|
150
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
151
137
|
return clone;
|
|
152
138
|
}
|
|
153
139
|
|
package/src/patterns/Not.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { Node } from "../ast/Node";
|
|
|
2
2
|
import { Cursor } from "./Cursor";
|
|
3
3
|
import { ParseResult } from "./ParseResult";
|
|
4
4
|
import { Pattern } from "./Pattern";
|
|
5
|
+
import { execPattern } from "./execPattern";
|
|
6
|
+
import { testPattern } from "./testPattern";
|
|
5
7
|
|
|
6
8
|
let idIndex = 0;
|
|
7
9
|
|
|
@@ -12,8 +14,6 @@ export class Not implements Pattern {
|
|
|
12
14
|
private _parent: Pattern | null;
|
|
13
15
|
private _children: Pattern[];
|
|
14
16
|
|
|
15
|
-
shouldCompactAst = false;
|
|
16
|
-
|
|
17
17
|
get id(): string {
|
|
18
18
|
return this._id;
|
|
19
19
|
}
|
|
@@ -51,23 +51,12 @@ export class Not implements Pattern {
|
|
|
51
51
|
this._children[0].parent = this;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
test(text: string) {
|
|
55
|
-
|
|
56
|
-
this.parse(cursor);
|
|
57
|
-
|
|
58
|
-
return !cursor.hasError;
|
|
54
|
+
test(text: string, record = false): boolean {
|
|
55
|
+
return testPattern(this, text, record);
|
|
59
56
|
}
|
|
60
57
|
|
|
61
58
|
exec(text: string, record = false): ParseResult {
|
|
62
|
-
|
|
63
|
-
record && cursor.startRecording();
|
|
64
|
-
|
|
65
|
-
const ast = this.parse(cursor);
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
ast: ast?.value === text ? ast : null,
|
|
69
|
-
cursor
|
|
70
|
-
};
|
|
59
|
+
return execPattern(this, text, record);
|
|
71
60
|
}
|
|
72
61
|
|
|
73
62
|
parse(cursor: Cursor): Node | null {
|
package/src/patterns/Optional.ts
CHANGED
|
@@ -12,8 +12,6 @@ export class Optional implements Pattern {
|
|
|
12
12
|
private _parent: Pattern | null;
|
|
13
13
|
private _children: Pattern[];
|
|
14
14
|
|
|
15
|
-
shouldCompactAst = false;
|
|
16
|
-
|
|
17
15
|
get id(): string {
|
|
18
16
|
return this._id;
|
|
19
17
|
}
|
|
@@ -80,10 +78,6 @@ export class Optional implements Pattern {
|
|
|
80
78
|
|
|
81
79
|
return null;
|
|
82
80
|
} else {
|
|
83
|
-
if (node != null && this.shouldCompactAst) {
|
|
84
|
-
node.compact();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
81
|
return node;
|
|
88
82
|
}
|
|
89
83
|
|
|
@@ -92,7 +86,6 @@ export class Optional implements Pattern {
|
|
|
92
86
|
clone(name = this._name): Pattern {
|
|
93
87
|
const clone = new Optional(name, this._children[0]);
|
|
94
88
|
clone._id = this._id;
|
|
95
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
96
89
|
return clone;
|
|
97
90
|
}
|
|
98
91
|
|
package/src/patterns/Options.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { clonePatterns } from "./clonePatterns";
|
|
|
5
5
|
import { findPattern } from "./findPattern";
|
|
6
6
|
import { ParseResult } from "./ParseResult";
|
|
7
7
|
import { isRecursivePattern } from "./isRecursivePattern";
|
|
8
|
+
import { execPattern } from "./execPattern";
|
|
9
|
+
import { testPattern } from "./testPattern";
|
|
8
10
|
|
|
9
11
|
let idIndex = 0;
|
|
10
12
|
|
|
@@ -17,8 +19,6 @@ export class Options implements Pattern {
|
|
|
17
19
|
private _isGreedy: boolean;
|
|
18
20
|
private _firstIndex: number;
|
|
19
21
|
|
|
20
|
-
shouldCompactAst = false;
|
|
21
|
-
|
|
22
22
|
get id(): string {
|
|
23
23
|
return this._id;
|
|
24
24
|
}
|
|
@@ -70,23 +70,12 @@ export class Options implements Pattern {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
test(text: string) {
|
|
74
|
-
|
|
75
|
-
const ast = this.parse(cursor);
|
|
76
|
-
|
|
77
|
-
return ast?.value === text;
|
|
73
|
+
test(text: string, record = false): boolean {
|
|
74
|
+
return testPattern(this, text, record);
|
|
78
75
|
}
|
|
79
76
|
|
|
80
77
|
exec(text: string, record = false): ParseResult {
|
|
81
|
-
|
|
82
|
-
record && cursor.startRecording();
|
|
83
|
-
|
|
84
|
-
const ast = this.parse(cursor);
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
ast: ast?.value === text ? ast : null,
|
|
88
|
-
cursor
|
|
89
|
-
};
|
|
78
|
+
return execPattern(this, text, record);
|
|
90
79
|
}
|
|
91
80
|
|
|
92
81
|
parse(cursor: Cursor): Node | null {
|
|
@@ -97,10 +86,6 @@ export class Options implements Pattern {
|
|
|
97
86
|
cursor.moveTo(node.lastIndex);
|
|
98
87
|
cursor.resolveError();
|
|
99
88
|
|
|
100
|
-
if (this.shouldCompactAst) {
|
|
101
|
-
node.compact();
|
|
102
|
-
}
|
|
103
|
-
|
|
104
89
|
return node;
|
|
105
90
|
}
|
|
106
91
|
|
|
@@ -221,7 +206,6 @@ export class Options implements Pattern {
|
|
|
221
206
|
clone(name = this._name): Pattern {
|
|
222
207
|
const clone = new Options(name, this._children, this._isGreedy);
|
|
223
208
|
clone._id = this._id;
|
|
224
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
225
209
|
return clone;
|
|
226
210
|
}
|
|
227
211
|
|
package/src/patterns/Pattern.ts
CHANGED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { PrecedenceTree } from "./PrecedenceTree";
|
|
2
|
+
import { Node } from "../ast/Node";
|
|
3
|
+
|
|
4
|
+
describe("Precedence Tree", () => {
|
|
5
|
+
test("add Binary", () => {
|
|
6
|
+
const tree = new PrecedenceTree({
|
|
7
|
+
mul: 0,
|
|
8
|
+
add: 1,
|
|
9
|
+
bool: 2
|
|
10
|
+
}, {});
|
|
11
|
+
|
|
12
|
+
tree.addAtom(Node.createValueNode("literal", "a", "a"));
|
|
13
|
+
tree.addBinary("add", Node.createValueNode("literal", "+", "+"));
|
|
14
|
+
tree.addAtom(Node.createValueNode("literal", "b", "b"));
|
|
15
|
+
tree.addBinary("mul", Node.createValueNode("literal", "*", "*"));
|
|
16
|
+
tree.addAtom(Node.createValueNode("literal", "c", "c"));
|
|
17
|
+
tree.addBinary("bool", Node.createValueNode("literal", "||", "||"));
|
|
18
|
+
tree.addAtom(Node.createValueNode("literal", "d", "d"));
|
|
19
|
+
tree.addBinary("add", Node.createValueNode("literal", "+", "+"));
|
|
20
|
+
tree.addAtom(Node.createValueNode("literal", "e", "e"));
|
|
21
|
+
|
|
22
|
+
const result = tree.commit();
|
|
23
|
+
const expected = Node.createNode("expression", "bool", [
|
|
24
|
+
Node.createNode("expression", "add", [
|
|
25
|
+
Node.createValueNode("literal", "a", "a"),
|
|
26
|
+
Node.createValueNode("literal", "+", "+"),
|
|
27
|
+
Node.createNode("expression", "mul", [
|
|
28
|
+
Node.createValueNode("literal", "b", "b"),
|
|
29
|
+
Node.createValueNode("literal", "*", "*"),
|
|
30
|
+
Node.createValueNode("literal", "c", "c"),
|
|
31
|
+
]),
|
|
32
|
+
]),
|
|
33
|
+
Node.createValueNode("literal", "||", "||"),
|
|
34
|
+
Node.createNode("expression", "add", [
|
|
35
|
+
Node.createValueNode("literal", "d", "d"),
|
|
36
|
+
Node.createValueNode("literal", "+", "+"),
|
|
37
|
+
Node.createValueNode("literal", "e", "e"),
|
|
38
|
+
]),
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
expect(result?.toString()).toBe("a+b*c||d+e");
|
|
43
|
+
expect(result?.toCycleFreeObject()).toEqual(expected.toCycleFreeObject());
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("add Prefix", () => {
|
|
47
|
+
const tree = new PrecedenceTree();
|
|
48
|
+
|
|
49
|
+
tree.addPrefix("negate", Node.createValueNode("literal", "!", "!"));
|
|
50
|
+
tree.addPrefix("increment", Node.createValueNode("literal", "++", "++"));
|
|
51
|
+
tree.addPrefix("plus", Node.createValueNode("literal", "+", "+"));
|
|
52
|
+
tree.addAtom(Node.createValueNode("literal", "a", "a"));
|
|
53
|
+
|
|
54
|
+
let result = tree.commit();
|
|
55
|
+
const expected = Node.createNode("expression", "negate", [
|
|
56
|
+
Node.createValueNode("literal", "!", "!"),
|
|
57
|
+
Node.createNode("expression", "increment", [
|
|
58
|
+
Node.createValueNode("literal", "++", "++"),
|
|
59
|
+
Node.createNode("expression", "plus", [
|
|
60
|
+
Node.createValueNode("literal", "+", "+"),
|
|
61
|
+
Node.createValueNode("literal", "a", "a"),
|
|
62
|
+
]),
|
|
63
|
+
]),
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
expect(result?.toString()).toBe("!+++a");
|
|
67
|
+
expect(result?.toCycleFreeObject()).toEqual(expected.toCycleFreeObject());
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("add Postfix", () => {
|
|
71
|
+
const tree = new PrecedenceTree();
|
|
72
|
+
|
|
73
|
+
tree.addPostfix("decrement", Node.createValueNode("literal", "--", "--"));
|
|
74
|
+
tree.addPostfix("increment", Node.createValueNode("literal", "++", "++"));
|
|
75
|
+
tree.addAtom(Node.createValueNode("literal", "a", "a"));
|
|
76
|
+
|
|
77
|
+
const expected = Node.createNode("expression", "increment", [
|
|
78
|
+
Node.createNode("expression", "decrement", [
|
|
79
|
+
Node.createValueNode("literal", "a", "a"),
|
|
80
|
+
Node.createValueNode("literal", "--", "--"),
|
|
81
|
+
]),
|
|
82
|
+
Node.createValueNode("literal", "++", "++"),
|
|
83
|
+
]);
|
|
84
|
+
|
|
85
|
+
const result = tree.commit();
|
|
86
|
+
expect(result?.toString()).toBe("a--++");
|
|
87
|
+
expect(result?.toCycleFreeObject()).toEqual(expected.toCycleFreeObject());
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("all", () => {
|
|
91
|
+
const tree = new PrecedenceTree({
|
|
92
|
+
mul: 0,
|
|
93
|
+
add: 1,
|
|
94
|
+
bool: 2
|
|
95
|
+
}, {});
|
|
96
|
+
|
|
97
|
+
tree.addPrefix("negate", Node.createValueNode("literal", "!", "!"));
|
|
98
|
+
tree.addPostfix("increment", Node.createValueNode("literal", "++", "++"));
|
|
99
|
+
tree.addAtom(Node.createValueNode("literal", "a", "a"));
|
|
100
|
+
tree.addBinary("mul", Node.createValueNode("literal", "*", "*"));
|
|
101
|
+
tree.addAtom(Node.createValueNode("literal", "b", "b"));
|
|
102
|
+
tree.addBinary("add", Node.createValueNode("literal", "+", "+"));
|
|
103
|
+
tree.addAtom(Node.createValueNode("literal", "c", "c"));
|
|
104
|
+
|
|
105
|
+
const result = tree.commit();
|
|
106
|
+
const expected = Node.createNode("expression", "add", [
|
|
107
|
+
Node.createNode("expression", "mul", [
|
|
108
|
+
Node.createNode("expression", "increment", [
|
|
109
|
+
Node.createNode("expression", "negate", [
|
|
110
|
+
Node.createValueNode("literal", "!", "!"),
|
|
111
|
+
Node.createValueNode("literal", "a", "a"),
|
|
112
|
+
]),
|
|
113
|
+
Node.createValueNode("literal", "++", "++"),
|
|
114
|
+
]),
|
|
115
|
+
Node.createValueNode("literal", "*", "*"),
|
|
116
|
+
Node.createValueNode("literal", "b", "b"),
|
|
117
|
+
]),
|
|
118
|
+
Node.createValueNode("literal", "+", "+"),
|
|
119
|
+
Node.createValueNode("literal", "c", "c"),
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
expect(result?.toString()).toBe("!a++*b+c");
|
|
123
|
+
expect(result?.toCycleFreeObject()).toEqual(expected.toCycleFreeObject());
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("Incomplete", () => {
|
|
127
|
+
const tree = new PrecedenceTree({
|
|
128
|
+
mul: 0,
|
|
129
|
+
add: 1,
|
|
130
|
+
bool: 2
|
|
131
|
+
}, {});
|
|
132
|
+
|
|
133
|
+
tree.addPrefix("negate", Node.createValueNode("literal", "!", "!"));
|
|
134
|
+
tree.addPostfix("increment", Node.createValueNode("literal", "++", "++"));
|
|
135
|
+
tree.addAtom(Node.createValueNode("literal", "a", "a"));
|
|
136
|
+
tree.addBinary("mul", Node.createValueNode("literal", "*", "*"));
|
|
137
|
+
tree.addAtom(Node.createValueNode("literal", "b", "b"));
|
|
138
|
+
tree.addBinary("add", Node.createValueNode("literal", "+", "+"));
|
|
139
|
+
tree.addAtom(Node.createValueNode("literal", "c", "c"));
|
|
140
|
+
tree.addBinary("mul", Node.createValueNode("literal", "*", "*"));
|
|
141
|
+
|
|
142
|
+
const result = tree.commit();
|
|
143
|
+
const expected = Node.createNode("expression", "add", [
|
|
144
|
+
Node.createNode("expression", "mul", [
|
|
145
|
+
Node.createNode("expression", "increment", [
|
|
146
|
+
Node.createNode("expression", "negate", [
|
|
147
|
+
Node.createValueNode("literal", "!", "!"),
|
|
148
|
+
Node.createValueNode("literal", "a", "a"),
|
|
149
|
+
]),
|
|
150
|
+
Node.createValueNode("literal", "++", "++"),
|
|
151
|
+
]),
|
|
152
|
+
Node.createValueNode("literal", "*", "*"),
|
|
153
|
+
Node.createValueNode("literal", "b", "b"),
|
|
154
|
+
]),
|
|
155
|
+
Node.createValueNode("literal", "+", "+"),
|
|
156
|
+
Node.createValueNode("literal", "c", "c"),
|
|
157
|
+
]);
|
|
158
|
+
|
|
159
|
+
expect(result?.toString()).toBe("!a++*b+c");
|
|
160
|
+
expect(result?.toCycleFreeObject()).toEqual(expected.toCycleFreeObject());
|
|
161
|
+
});
|
|
162
|
+
});
|