occam-dom 5.0.0 → 5.0.2
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/example.js +1495 -1305
- package/lib/example/constants.js +22 -0
- package/lib/example/utilities/query.js +23 -0
- package/lib/example/view/div/sizeable.js +2 -2
- package/lib/example/view/textarea/expressions.js +143 -0
- package/lib/example/view/textarea/outerNodes.js +147 -0
- package/lib/example/view/{input/expressionString.js → textarea/parseTree/inner.js} +43 -28
- package/lib/{expression/parser.js → example/view/textarea/parseTree/outer.js} +20 -28
- package/lib/example/view/textarea/parseTree.js +1 -19
- package/lib/example/view.js +26 -20
- package/lib/index.js +7 -19
- package/lib/node.js +302 -0
- package/lib/parseTree/childNodes.js +164 -0
- package/lib/parseTree/horizontalBranch.js +120 -0
- package/lib/parseTree/node.js +145 -0
- package/lib/parseTree/string.js +109 -0
- package/lib/parseTree/verticalBranch.js +184 -0
- package/lib/parseTree.js +191 -0
- package/lib/utilities/node.js +56 -309
- package/package.json +3 -2
- package/src/example/constants.js +4 -0
- package/src/example/utilities/query.js +21 -0
- package/src/example/view/div/sizeable.js +1 -1
- package/src/example/view/textarea/expressions.js +39 -0
- package/src/example/view/textarea/outerNodes.js +48 -0
- package/src/example/view/textarea/parseTree/inner.js +24 -0
- package/src/example/view/textarea/parseTree/outer.js +17 -0
- package/src/example/view/textarea/parseTree.js +0 -18
- package/src/example/view.js +44 -32
- package/src/index.js +2 -5
- package/src/node.js +221 -0
- package/src/parseTree/childNodes.js +108 -0
- package/src/parseTree/horizontalBranch.js +32 -0
- package/src/parseTree/node.js +77 -0
- package/src/parseTree/string.js +18 -0
- package/src/parseTree/verticalBranch.js +77 -0
- package/src/parseTree.js +141 -0
- package/src/utilities/node.js +66 -416
- package/lib/example/view/textarea/nodes.js +0 -155
- package/lib/expression/bnf.js +0 -14
- package/lib/expression/entries.js +0 -27
- package/lib/expression/lexer.js +0 -145
- package/lib/expression.js +0 -113
- package/lib/path.js +0 -69
- package/lib/query.js +0 -216
- package/lib/ruleNames.js +0 -54
- package/lib/spread.js +0 -113
- package/lib/subExpression.js +0 -101
- package/lib/utilities/array.js +0 -67
- package/lib/utilities/query.js +0 -39
- package/src/example/view/input/expressionString.js +0 -33
- package/src/example/view/textarea/nodes.js +0 -55
- package/src/expression/bnf.js +0 -63
- package/src/expression/entries.js +0 -18
- package/src/expression/lexer.js +0 -35
- package/src/expression/parser.js +0 -15
- package/src/expression.js +0 -82
- package/src/path.js +0 -32
- package/src/query.js +0 -207
- package/src/ruleNames.js +0 -12
- package/src/spread.js +0 -104
- package/src/subExpression.js +0 -52
- package/src/utilities/array.js +0 -30
- package/src/utilities/query.js +0 -22
|
@@ -4,8 +4,6 @@ import withStyle from "easy-with-style"; ///
|
|
|
4
4
|
|
|
5
5
|
import Textarea from "../textarea";
|
|
6
6
|
|
|
7
|
-
import { EMPTY_STRING } from "../../../constants";
|
|
8
|
-
|
|
9
7
|
class ParseTreeTextarea extends Textarea {
|
|
10
8
|
setParseTree(parseTree) {
|
|
11
9
|
parseTree.shiftLine(); //
|
|
@@ -16,22 +14,6 @@ class ParseTreeTextarea extends Textarea {
|
|
|
16
14
|
this.setValue(value);
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
clearParseTree(parseTree) {
|
|
20
|
-
const value = EMPTY_STRING;
|
|
21
|
-
|
|
22
|
-
this.setValue(value);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
parentContext() {
|
|
26
|
-
const setParseTree = this.setParseTree.bind(this), ///
|
|
27
|
-
clearParseTree = this.clearParseTree.bind(this); ///
|
|
28
|
-
|
|
29
|
-
return ({
|
|
30
|
-
setParseTree,
|
|
31
|
-
clearParseTree
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
17
|
static defaultProperties = {
|
|
36
18
|
className: "parse-tree",
|
|
37
19
|
spellCheck: "false",
|
package/src/example/view.js
CHANGED
|
@@ -3,29 +3,28 @@
|
|
|
3
3
|
import withStyle from "easy-with-style"; ///
|
|
4
4
|
|
|
5
5
|
import { Element } from "easy";
|
|
6
|
-
import {
|
|
6
|
+
import { nodeUtilities } from "../index" ///
|
|
7
7
|
import { CSSLexer, CSSParser } from "with-style";
|
|
8
8
|
import { RowsDiv, ColumnDiv, ColumnsDiv, VerticalSplitterDiv } from "easy-layout";
|
|
9
9
|
|
|
10
10
|
import SubHeading from "./view/subHeading";
|
|
11
11
|
import SizeableDiv from "./view/div/sizeable";
|
|
12
|
-
import NodesTextarea from "./view/textarea/nodes";
|
|
13
12
|
import ContentTextarea from "./view/textarea/content";
|
|
14
13
|
import MaximumDepthInput from "./view/input/maximumDepth";
|
|
15
|
-
import
|
|
16
|
-
import
|
|
14
|
+
import OuterNodesTextarea from "./view/textarea/outerNodes";
|
|
15
|
+
import ExpressionsTextarea from "./view/textarea/expressions";
|
|
16
|
+
import OuterParseTreeTextarea from "./view/textarea/parseTree/outer";
|
|
17
|
+
import InnerParseTreeTextarea from "./view/textarea/parseTree/inner";
|
|
18
|
+
|
|
19
|
+
import { queryByExpressions } from "./utilities/query";
|
|
20
|
+
|
|
21
|
+
const { topmostNodeFromOuterNodes: topmostInnerNodeFromOuterNodes } = nodeUtilities;
|
|
17
22
|
|
|
18
23
|
const cssLexer = CSSLexer.fromNothing(),
|
|
19
24
|
cssParser = CSSParser.fromNothing();
|
|
20
25
|
|
|
21
|
-
const { queryByExpressionString } = queryUtilities;
|
|
22
|
-
|
|
23
26
|
class View extends Element {
|
|
24
27
|
keyUpHandler = (event, element) => {
|
|
25
|
-
this.clearNodes();
|
|
26
|
-
|
|
27
|
-
this.clearParseTree();
|
|
28
|
-
|
|
29
28
|
const content = this.getContent(),
|
|
30
29
|
tokens = cssLexer.tokenise(content),
|
|
31
30
|
node = cssParser.parse(tokens);
|
|
@@ -34,17 +33,20 @@ class View extends Element {
|
|
|
34
33
|
return;
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
expressionString = this.getExpressionString(),
|
|
36
|
+
const outerNode = node, ///
|
|
37
|
+
expressions = this.getExpressions(),
|
|
40
38
|
maximumDepth = this.getMaximumDepth(),
|
|
41
|
-
|
|
39
|
+
outerNodes = queryByExpressions(outerNode, expressions, maximumDepth),
|
|
40
|
+
topmostInnerNode = topmostInnerNodeFromOuterNodes(outerNodes),
|
|
41
|
+
innerNode = topmostInnerNode, ///
|
|
42
|
+
outerParseTree = outerNode.asParseTree(tokens),
|
|
43
|
+
innerParseTree = innerNode.asParseTree();
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
this.setNodes(nodes, tokens); ///
|
|
45
|
+
this.setOuterNodes(outerNodes, tokens); ///
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
this.setOuterParseTree(outerParseTree);
|
|
48
|
+
|
|
49
|
+
this.setInnerParseTree(innerParseTree);
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
childElements() {
|
|
@@ -54,30 +56,34 @@ class View extends Element {
|
|
|
54
56
|
<SizeableDiv>
|
|
55
57
|
<RowsDiv>
|
|
56
58
|
<SubHeading>
|
|
57
|
-
|
|
59
|
+
Content
|
|
58
60
|
</SubHeading>
|
|
59
|
-
<
|
|
61
|
+
<ContentTextarea onKeyUp={this.keyUpHandler} />
|
|
62
|
+
<SubHeading>
|
|
63
|
+
Expressions
|
|
64
|
+
</SubHeading>
|
|
65
|
+
<ExpressionsTextarea onKeyUp={this.keyUpHandler} />
|
|
60
66
|
<SubHeading>
|
|
61
67
|
Maximum depth
|
|
62
68
|
</SubHeading>
|
|
63
69
|
<MaximumDepthInput onKeyUp={this.keyUpHandler} />
|
|
70
|
+
<SubHeading>
|
|
71
|
+
Outer nodes
|
|
72
|
+
</SubHeading>
|
|
73
|
+
<OuterNodesTextarea/>
|
|
64
74
|
</RowsDiv>
|
|
65
75
|
</SizeableDiv>
|
|
66
76
|
<VerticalSplitterDiv />
|
|
67
77
|
<ColumnDiv>
|
|
68
78
|
<RowsDiv>
|
|
69
79
|
<SubHeading>
|
|
70
|
-
|
|
71
|
-
</SubHeading>
|
|
72
|
-
<ContentTextarea onKeyUp={this.keyUpHandler} />
|
|
73
|
-
<SubHeading>
|
|
74
|
-
Parse tree
|
|
80
|
+
Outer parse tree
|
|
75
81
|
</SubHeading>
|
|
76
|
-
<
|
|
82
|
+
<OuterParseTreeTextarea/>
|
|
77
83
|
<SubHeading>
|
|
78
|
-
|
|
84
|
+
Inner parse tree
|
|
79
85
|
</SubHeading>
|
|
80
|
-
<
|
|
86
|
+
<InnerParseTreeTextarea/>
|
|
81
87
|
</RowsDiv>
|
|
82
88
|
</ColumnDiv>
|
|
83
89
|
</ColumnsDiv>
|
|
@@ -88,16 +94,16 @@ class View extends Element {
|
|
|
88
94
|
initialise() {
|
|
89
95
|
this.assignContext();
|
|
90
96
|
|
|
91
|
-
const { initialContent,
|
|
97
|
+
const { initialContent, initialExpressions, initialMaximumDepth } = this.constructor,
|
|
92
98
|
content = initialContent, ///
|
|
93
99
|
maximumDepth = initialMaximumDepth, ///
|
|
94
|
-
|
|
100
|
+
expressions = initialExpressions; ///
|
|
95
101
|
|
|
96
102
|
this.setContent(content);
|
|
97
103
|
|
|
98
104
|
this.setMaximumDepth(maximumDepth);
|
|
99
105
|
|
|
100
|
-
this.
|
|
106
|
+
this.setExpressions(expressions);
|
|
101
107
|
|
|
102
108
|
this.keyUpHandler(); ///
|
|
103
109
|
}
|
|
@@ -107,7 +113,13 @@ class View extends Element {
|
|
|
107
113
|
}
|
|
108
114
|
`;
|
|
109
115
|
|
|
110
|
-
static
|
|
116
|
+
static initialExpressions = [
|
|
117
|
+
"//term",
|
|
118
|
+
"//ruleSet",
|
|
119
|
+
"//selectors",
|
|
120
|
+
"//propertyName",
|
|
121
|
+
"//@identifier"
|
|
122
|
+
];
|
|
111
123
|
|
|
112
124
|
static initialMaximumDepth = 5;
|
|
113
125
|
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
export { default as
|
|
4
|
-
export { default as
|
|
5
|
-
export { default as queryUtilities } from "./utilities/query";
|
|
6
|
-
export { default as ExpressionLexer } from "./expression/lexer";
|
|
7
|
-
export { default as ExpressionParser } from "./expression/parser";
|
|
3
|
+
export { default as Node } from "./node";
|
|
4
|
+
export { default as nodeUtilities } from "./utilities/node";
|
package/src/node.js
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import NodeParseTree from "./parseTree/node";
|
|
4
|
+
|
|
5
|
+
import { EMPTY_STRING } from "./constants";
|
|
6
|
+
|
|
7
|
+
export default class Node {
|
|
8
|
+
constructor(outerNode, parentNode, childNodes) {
|
|
9
|
+
this.outerNode = outerNode;
|
|
10
|
+
this.parentNode = parentNode;
|
|
11
|
+
this.childNodes = childNodes;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
getOuterNode() {
|
|
15
|
+
return this.outerNode;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getParentNode() {
|
|
19
|
+
return this.parentNode;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getChildNodes() {
|
|
23
|
+
return this.childNodes;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
setOuterNode(outerNode) {
|
|
27
|
+
this.outerNode = outerNode;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
setParentNode(parentNode) {
|
|
31
|
+
this.parentNode = parentNode;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setChildNodes(childNodes) {
|
|
35
|
+
this.childNodes = childNodes;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
mapChildNode(callback) { return this.childNodes.map(callback); }
|
|
39
|
+
|
|
40
|
+
someChildNode(callback) { return this.childNodes.some(callback); }
|
|
41
|
+
|
|
42
|
+
findChildNode(callback) { return this.childNodes.find(callback); }
|
|
43
|
+
|
|
44
|
+
everyChildNode(callback) { return this.childNodes.every(callback); }
|
|
45
|
+
|
|
46
|
+
filterChildNode(callback) { return this.childNodes.filter(callback); }
|
|
47
|
+
|
|
48
|
+
reduceChildNode(callback, initialValue) { return this.childNodes.reduce(callback, initialValue); }
|
|
49
|
+
|
|
50
|
+
forEachChildNode(callback) { this.childNodes.forEach(callback); }
|
|
51
|
+
|
|
52
|
+
setChildNodesParentNode(childNodes) {
|
|
53
|
+
if (childNodes === undefined) {
|
|
54
|
+
childNodes = [
|
|
55
|
+
...this.childNodes
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const parentNode = this;
|
|
60
|
+
|
|
61
|
+
childNodes.forEach((childNode) => {
|
|
62
|
+
childNode.setParentNode(parentNode);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
resetChildNodesParentNode(childNodes) {
|
|
67
|
+
if (childNodes === undefined) {
|
|
68
|
+
childNodes = [
|
|
69
|
+
...this.childNodes
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const parentNode = null;
|
|
74
|
+
|
|
75
|
+
childNodes.forEach((childNode) => {
|
|
76
|
+
childNode.setParentNode(parentNode);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
addChildNode(addedChildNode, startIndex) {
|
|
81
|
+
const addedChildNodes = [
|
|
82
|
+
addedChildNode
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
this.addChildNodes(addedChildNodes, startIndex);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
addChildNodes(addedChildNodes, startIndex) {
|
|
89
|
+
const deleteCount = 0;
|
|
90
|
+
|
|
91
|
+
this.spliceChildNodes(startIndex, deleteCount, addedChildNodes);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
removeChildNode(removedChildNode) {
|
|
95
|
+
let removedChildNodes;
|
|
96
|
+
|
|
97
|
+
removedChildNodes = [
|
|
98
|
+
removedChildNode
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
removedChildNodes = this.removeChildNodes(removedChildNodes);
|
|
102
|
+
|
|
103
|
+
return removedChildNodes;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
removeChildNodes(removedChildNodes) {
|
|
107
|
+
if (removedChildNodes === undefined) {
|
|
108
|
+
removedChildNodes = [
|
|
109
|
+
...this.childNodes
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const removedChildNodesLength = removedChildNodes.length;
|
|
114
|
+
|
|
115
|
+
if (removedChildNodesLength === 0) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const firstReplacedChildNode = first(removedChildNodes),
|
|
120
|
+
firstIndex = this.childNodes.indexOf(firstReplacedChildNode),
|
|
121
|
+
startIndex = firstIndex, ///
|
|
122
|
+
deleteCount = removedChildNodesLength, ///
|
|
123
|
+
addedChildNodes = [];
|
|
124
|
+
|
|
125
|
+
removedChildNodes = this.spliceChildNodes(startIndex, deleteCount, addedChildNodes);
|
|
126
|
+
|
|
127
|
+
return removedChildNodes;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
replaceChildNode(replacedChildNode, replacementChildNodes) {
|
|
131
|
+
const replacedChildNodes = [
|
|
132
|
+
replacedChildNode
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
this.replaceChildNodes(replacedChildNodes, replacementChildNodes);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
replaceChildNodes(replacedChildNodes, replacementChildNodes) {
|
|
139
|
+
const replacedChildNodesLength = replacedChildNodes.length,
|
|
140
|
+
firstReplacedChildNode = first(replacedChildNodes),
|
|
141
|
+
firstIndex = this.childNodes.indexOf(firstReplacedChildNode),
|
|
142
|
+
startIndex = firstIndex, ///
|
|
143
|
+
deleteCount = replacedChildNodesLength; ///
|
|
144
|
+
|
|
145
|
+
this.spliceChildNodes(startIndex, deleteCount, replacementChildNodes);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
spliceChildNodes(startIndex, deleteCount, addedChildNodes = []) {
|
|
149
|
+
const removedChildNodes = this.childNodes.splice(startIndex, deleteCount, ...addedChildNodes);
|
|
150
|
+
|
|
151
|
+
this.resetChildNodesParentNode(removedChildNodes);
|
|
152
|
+
|
|
153
|
+
this.setChildNodesParentNode(addedChildNodes);
|
|
154
|
+
|
|
155
|
+
return removedChildNodes;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
sliceChildNodes(startIndex, endIndex = Infinity) {
|
|
159
|
+
const childNodes = this.childNodes.slice(startIndex, endIndex);
|
|
160
|
+
|
|
161
|
+
return childNodes;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
asString() {
|
|
165
|
+
let string = EMPTY_STRING;
|
|
166
|
+
|
|
167
|
+
if (this.outerNode !== null) {
|
|
168
|
+
const nodeTerminalNode = this.outerNode.isTerminalNode();
|
|
169
|
+
|
|
170
|
+
if (nodeTerminalNode) {
|
|
171
|
+
const terminalNode = this.outerNode,
|
|
172
|
+
type = terminalNode.getType(),
|
|
173
|
+
content = terminalNode.getContent();
|
|
174
|
+
|
|
175
|
+
string = `"${content}" [${type}]`;
|
|
176
|
+
} else {
|
|
177
|
+
const nonTerminalNode = this.outerNode,
|
|
178
|
+
ruleName = nonTerminalNode.getRuleName();
|
|
179
|
+
|
|
180
|
+
string = ruleName; ///
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return string;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
asParseTree() {
|
|
188
|
+
const node = this, ///
|
|
189
|
+
nodeParseTree = NodeParseTree.fromNode(node),
|
|
190
|
+
parseTree = nodeParseTree; ///
|
|
191
|
+
|
|
192
|
+
return parseTree;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
static fromNothing(Class) {
|
|
196
|
+
if (Class === undefined) {
|
|
197
|
+
Class = Node; ///
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const outerNode = null,
|
|
201
|
+
parentNode = null,
|
|
202
|
+
childNodes = [],
|
|
203
|
+
node = new Class(outerNode, parentNode, childNodes);
|
|
204
|
+
|
|
205
|
+
return node;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
static fromOuterNode(Class, outerNode) {
|
|
209
|
+
if (outerNode === undefined) {
|
|
210
|
+
outerNode = Class; ///
|
|
211
|
+
|
|
212
|
+
Class = Node; ///
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const parentNode = null,
|
|
216
|
+
childNodes = [],
|
|
217
|
+
node = new Class(outerNode, parentNode, childNodes);
|
|
218
|
+
|
|
219
|
+
return node;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { arrayUtilities } from "necessary";
|
|
4
|
+
|
|
5
|
+
import VerticalBranchParseTree from "./verticalBranch";
|
|
6
|
+
import HorizontalBranchParseTree from "./horizontalBranch";
|
|
7
|
+
|
|
8
|
+
const { first } = arrayUtilities;
|
|
9
|
+
|
|
10
|
+
export default class ChildNodesParseTree extends VerticalBranchParseTree {
|
|
11
|
+
static fromChildNodes(childNodes) {
|
|
12
|
+
let childNodesParseTree = null;
|
|
13
|
+
|
|
14
|
+
const childNodesLength = childNodes.length;
|
|
15
|
+
|
|
16
|
+
if (childNodesLength > 0) {
|
|
17
|
+
const childNodeParseTrees = childNodes.reduce((childNodeParseTrees, childNode) => {
|
|
18
|
+
const childNodeParseTree = childNode.asParseTree();
|
|
19
|
+
|
|
20
|
+
childNodeParseTrees.push(childNodeParseTree);
|
|
21
|
+
|
|
22
|
+
return childNodeParseTrees;
|
|
23
|
+
}, []),
|
|
24
|
+
childNodeParseTreesLength = childNodeParseTrees.length;
|
|
25
|
+
|
|
26
|
+
if (childNodeParseTreesLength === 1) {
|
|
27
|
+
const firstChildNodeParseTree = first(childNodeParseTrees);
|
|
28
|
+
|
|
29
|
+
childNodesParseTree = firstChildNodeParseTree; ///
|
|
30
|
+
} else {
|
|
31
|
+
let firstVerticalBranchPosition,
|
|
32
|
+
lastVerticalBranchPosition = 0,
|
|
33
|
+
childNodeParseTreesWidth = 0,
|
|
34
|
+
childNodeParseTreesDepth = 0;
|
|
35
|
+
|
|
36
|
+
childNodeParseTrees.forEach((childNodeParseTree, index) => {
|
|
37
|
+
const childNodeParseTreeWidth = childNodeParseTree.getWidth(),
|
|
38
|
+
childNodeParseTreeDepth = childNodeParseTree.getDepth();
|
|
39
|
+
|
|
40
|
+
if (index === 0) {
|
|
41
|
+
const firstChildNodeParseTree = childNodeParseTree,
|
|
42
|
+
firstChildNodeParseTreeVerticalBranchPosition = firstChildNodeParseTree.getVerticalBranchPosition();
|
|
43
|
+
|
|
44
|
+
firstVerticalBranchPosition = firstChildNodeParseTreeVerticalBranchPosition;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (index === childNodeParseTreesLength - 1) {
|
|
48
|
+
const lastChildNodeParseTree = childNodeParseTree,
|
|
49
|
+
lastChildNodeParseTreeVerticalBranchPosition = lastChildNodeParseTree.getVerticalBranchPosition();
|
|
50
|
+
|
|
51
|
+
lastVerticalBranchPosition += lastChildNodeParseTreeVerticalBranchPosition;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (index < childNodeParseTreesLength - 1) {
|
|
55
|
+
lastVerticalBranchPosition += childNodeParseTreeWidth;
|
|
56
|
+
lastVerticalBranchPosition += 1;
|
|
57
|
+
|
|
58
|
+
childNodeParseTreesWidth += 1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
childNodeParseTreesWidth += childNodeParseTreeWidth;
|
|
62
|
+
childNodeParseTreesDepth = Math.max(childNodeParseTreesDepth, childNodeParseTreeDepth);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const width = lastVerticalBranchPosition - firstVerticalBranchPosition + 1,
|
|
66
|
+
verticalBranchParseTree = VerticalBranchParseTree.fromWidth(width),
|
|
67
|
+
horizontalBranchParseTree = HorizontalBranchParseTree.fromWidth(width),
|
|
68
|
+
leftMarginWidth = firstVerticalBranchPosition,
|
|
69
|
+
rightMarginWidth = childNodeParseTreesWidth - width - leftMarginWidth;
|
|
70
|
+
|
|
71
|
+
verticalBranchParseTree.addLeftMargin(leftMarginWidth);
|
|
72
|
+
verticalBranchParseTree.addRightMargin(rightMarginWidth);
|
|
73
|
+
horizontalBranchParseTree.addLeftMargin(leftMarginWidth);
|
|
74
|
+
horizontalBranchParseTree.addRightMargin(rightMarginWidth);
|
|
75
|
+
|
|
76
|
+
const verticalBranchPosition = verticalBranchParseTree.getVerticalBranchPosition(),
|
|
77
|
+
depth = childNodeParseTreesDepth; ///
|
|
78
|
+
|
|
79
|
+
childNodesParseTree = VerticalBranchParseTree.fromDepthAndVerticalBranchPosition(ChildNodesParseTree, depth, verticalBranchPosition);
|
|
80
|
+
|
|
81
|
+
childNodeParseTrees.forEach((childNodeParseTree, index) => {
|
|
82
|
+
const childNodeParseTreeDepth = childNodeParseTree.getDepth(),
|
|
83
|
+
clonedChildNodeParseTree = childNodeParseTree.clone();
|
|
84
|
+
|
|
85
|
+
if (index < childNodeParseTreesLength - 1) {
|
|
86
|
+
const rightMarginWidth = 1;
|
|
87
|
+
|
|
88
|
+
clonedChildNodeParseTree.addRightMargin(rightMarginWidth);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (childNodeParseTreeDepth < childNodeParseTreesDepth) {
|
|
92
|
+
const bottomMarginDepth = childNodeParseTreesDepth - childNodeParseTreeDepth;
|
|
93
|
+
|
|
94
|
+
clonedChildNodeParseTree.addBottomMargin(bottomMarginDepth);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
childNodesParseTree.appendToRight(clonedChildNodeParseTree);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
childNodesParseTree.appendToTop(horizontalBranchParseTree);
|
|
101
|
+
|
|
102
|
+
childNodesParseTree.appendToTop(verticalBranchParseTree);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return childNodesParseTree;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { characters } from "necessary";
|
|
4
|
+
|
|
5
|
+
import ParseTree from "../parseTree";
|
|
6
|
+
|
|
7
|
+
import { EMPTY_STRING } from "../constants";
|
|
8
|
+
|
|
9
|
+
const { DASH_CHARACTER } = characters;
|
|
10
|
+
|
|
11
|
+
export default class HorizontalBranchParseTree extends ParseTree {
|
|
12
|
+
static fromWidth(width) {
|
|
13
|
+
const string = stringFromCharactersWidth(width, DASH_CHARACTER),
|
|
14
|
+
line = string, ///
|
|
15
|
+
lines = [
|
|
16
|
+
line
|
|
17
|
+
],
|
|
18
|
+
horizontalBranchParseTree = new HorizontalBranchParseTree(lines);
|
|
19
|
+
|
|
20
|
+
return horizontalBranchParseTree;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function stringFromCharactersWidth(charactersWidth, character) {
|
|
25
|
+
let string = EMPTY_STRING;
|
|
26
|
+
|
|
27
|
+
for (let index = 0; index < charactersWidth; index++) {
|
|
28
|
+
string += character;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return string;
|
|
32
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import StringParseTree from "./string";
|
|
4
|
+
import ChildNodesParseTree from "./childNodes";
|
|
5
|
+
import VerticalBranchParseTree from "./verticalBranch";
|
|
6
|
+
|
|
7
|
+
export default class NodeParseTree extends VerticalBranchParseTree {
|
|
8
|
+
static fromNode(node) {
|
|
9
|
+
let nodeParseTree;
|
|
10
|
+
|
|
11
|
+
const childNodes = node.getChildNodes(),
|
|
12
|
+
ruleNameParseTree = StringParseTree.fromNode(node),
|
|
13
|
+
childNodesParseTree = ChildNodesParseTree.fromChildNodes(childNodes);
|
|
14
|
+
|
|
15
|
+
if (childNodesParseTree === null) {
|
|
16
|
+
const ruleNameParseTreeDepth = ruleNameParseTree.getDepth(),
|
|
17
|
+
ruleNameParseTreeVerticalBranchPosition = ruleNameParseTree.getVerticalBranchPosition(),
|
|
18
|
+
verticalBranchPosition = ruleNameParseTreeVerticalBranchPosition, ///
|
|
19
|
+
depth = ruleNameParseTreeDepth; ///
|
|
20
|
+
|
|
21
|
+
nodeParseTree = VerticalBranchParseTree.fromDepthAndVerticalBranchPosition(NodeParseTree, depth, verticalBranchPosition);
|
|
22
|
+
|
|
23
|
+
nodeParseTree.appendToRight(ruleNameParseTree);
|
|
24
|
+
} else {
|
|
25
|
+
let ruleNameParseTreeVerticalBranchPosition = ruleNameParseTree.getVerticalBranchPosition();
|
|
26
|
+
|
|
27
|
+
const childNodesParseTreeVerticalBranchPosition = childNodesParseTree.getVerticalBranchPosition(),
|
|
28
|
+
verticalBranchPositionsDifference = ruleNameParseTreeVerticalBranchPosition - childNodesParseTreeVerticalBranchPosition;
|
|
29
|
+
|
|
30
|
+
let leftMarginWidth;
|
|
31
|
+
|
|
32
|
+
if (false) {
|
|
33
|
+
///
|
|
34
|
+
} else if (verticalBranchPositionsDifference < 0) {
|
|
35
|
+
leftMarginWidth = -verticalBranchPositionsDifference;
|
|
36
|
+
|
|
37
|
+
ruleNameParseTree.addLeftMargin(leftMarginWidth);
|
|
38
|
+
} else if (verticalBranchPositionsDifference > 0) {
|
|
39
|
+
leftMarginWidth = +verticalBranchPositionsDifference;
|
|
40
|
+
|
|
41
|
+
childNodesParseTree.addLeftMargin(leftMarginWidth);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const ruleNameParseTreeWidth = ruleNameParseTree.getWidth(),
|
|
45
|
+
childNodesParseTreeWidth = childNodesParseTree.getWidth(),
|
|
46
|
+
widthsDifference = ruleNameParseTreeWidth - childNodesParseTreeWidth;
|
|
47
|
+
|
|
48
|
+
let rightMarginWidth;
|
|
49
|
+
|
|
50
|
+
if (false) {
|
|
51
|
+
///
|
|
52
|
+
} else if (widthsDifference < 0) {
|
|
53
|
+
rightMarginWidth = -widthsDifference;
|
|
54
|
+
|
|
55
|
+
ruleNameParseTree.addRightMargin(rightMarginWidth);
|
|
56
|
+
} else if (widthsDifference > 0) {
|
|
57
|
+
rightMarginWidth = +widthsDifference;
|
|
58
|
+
|
|
59
|
+
childNodesParseTree.addRightMargin(rightMarginWidth);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
ruleNameParseTreeVerticalBranchPosition = ruleNameParseTree.getVerticalBranchPosition();
|
|
63
|
+
|
|
64
|
+
const ruleNameParseTreeDepth = ruleNameParseTree.getDepth(),
|
|
65
|
+
verticalBranchPosition = ruleNameParseTreeVerticalBranchPosition, ///
|
|
66
|
+
depth = ruleNameParseTreeDepth; ///
|
|
67
|
+
|
|
68
|
+
nodeParseTree = VerticalBranchParseTree.fromDepthAndVerticalBranchPosition(NodeParseTree, depth, verticalBranchPosition);
|
|
69
|
+
|
|
70
|
+
nodeParseTree.appendToRight(ruleNameParseTree);
|
|
71
|
+
|
|
72
|
+
nodeParseTree.appendToBottom(childNodesParseTree);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return nodeParseTree;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import VerticalBranchParseTree from "./verticalBranch";
|
|
4
|
+
|
|
5
|
+
export default class StringParseTree extends VerticalBranchParseTree {
|
|
6
|
+
static fromNode(node) {
|
|
7
|
+
const string = node.asString(),
|
|
8
|
+
stringLength = string.length,
|
|
9
|
+
verticalBranchParseTreeWidth = stringLength, ///
|
|
10
|
+
verticalBranchParseTree = VerticalBranchParseTree.fromWidth(verticalBranchParseTreeWidth),
|
|
11
|
+
verticalBranchPosition = verticalBranchParseTree.getVerticalBranchPosition(),
|
|
12
|
+
ruleNameParseTree = VerticalBranchParseTree.fromStringAndVerticalBranchPosition(StringParseTree, string, verticalBranchPosition);
|
|
13
|
+
|
|
14
|
+
ruleNameParseTree.appendToTop(verticalBranchParseTree);
|
|
15
|
+
|
|
16
|
+
return ruleNameParseTree;
|
|
17
|
+
}
|
|
18
|
+
}
|