occam-dom 4.0.16 → 5.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/bin/main.js +15 -0
- package/example.js +37842 -0
- package/index.html +47 -0
- package/lib/constants.js +13 -0
- package/lib/example/utilities/token.js +28 -0
- package/lib/example/view/div/sizeable.js +39 -0
- package/lib/example/view/input/expressionString.js +142 -0
- package/lib/example/view/input/maximumDepth.js +143 -0
- package/lib/example/view/input.js +39 -0
- package/lib/example/view/subHeading.js +39 -0
- package/lib/example/view/textarea/content.js +142 -0
- package/lib/example/view/textarea/nodes.js +155 -0
- package/lib/example/view/textarea/parseTree.js +166 -0
- package/lib/example/view/textarea.js +39 -0
- package/lib/example/view.js +239 -0
- package/lib/example.js +19 -0
- package/lib/expression/bnf.js +14 -0
- package/lib/expression/entries.js +27 -0
- package/lib/expression/lexer.js +145 -0
- package/lib/expression/parser.js +134 -0
- package/lib/expression.js +113 -0
- package/lib/index.js +39 -0
- package/lib/path.js +69 -0
- package/lib/query.js +216 -0
- package/lib/ruleNames.js +54 -0
- package/lib/spread.js +113 -0
- package/lib/subExpression.js +101 -0
- package/lib/utilities/array.js +67 -0
- package/lib/utilities/node.js +334 -0
- package/lib/utilities/query.js +39 -0
- package/package.json +1 -1
- package/src/constants.js +3 -0
- package/src/example/utilities/token.js +19 -0
- package/src/example/view/div/sizeable.js +12 -0
- package/src/example/view/input/expressionString.js +33 -0
- package/src/example/view/input/maximumDepth.js +35 -0
- package/src/example/view/input.js +14 -0
- package/src/example/view/subHeading.js +16 -0
- package/src/example/view/textarea/content.js +33 -0
- package/src/example/view/textarea/nodes.js +55 -0
- package/src/example/view/textarea/parseTree.js +46 -0
- package/src/example/view/textarea.js +18 -0
- package/src/example/view.js +125 -0
- package/src/example.js +21 -0
- package/src/expression/bnf.js +63 -0
- package/src/expression/entries.js +18 -0
- package/src/expression/lexer.js +35 -0
- package/src/expression/parser.js +15 -0
- package/src/expression.js +82 -0
- package/src/index.js +7 -0
- package/src/path.js +32 -0
- package/src/query.js +207 -0
- package/src/ruleNames.js +12 -0
- package/src/spread.js +104 -0
- package/src/subExpression.js +52 -0
- package/src/utilities/array.js +30 -0
- package/src/utilities/node.js +454 -0
- package/src/utilities/query.js +22 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import withStyle from "easy-with-style"; ///
|
|
4
|
+
|
|
5
|
+
import Textarea from "../textarea";
|
|
6
|
+
|
|
7
|
+
import { EMPTY_STRING } from "../../../constants";
|
|
8
|
+
|
|
9
|
+
class ParseTreeTextarea extends Textarea {
|
|
10
|
+
setParseTree(parseTree) {
|
|
11
|
+
parseTree.shiftLine(); //
|
|
12
|
+
|
|
13
|
+
const parseTreeString = parseTree.asString(),
|
|
14
|
+
value = parseTreeString; ///
|
|
15
|
+
|
|
16
|
+
this.setValue(value);
|
|
17
|
+
}
|
|
18
|
+
|
|
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
|
+
static defaultProperties = {
|
|
36
|
+
className: "parse-tree",
|
|
37
|
+
spellCheck: "false",
|
|
38
|
+
readOnly: true
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default withStyle(ParseTreeTextarea)`
|
|
43
|
+
|
|
44
|
+
height: 32rem;
|
|
45
|
+
|
|
46
|
+
`;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import withStyle from "easy-with-style"; ///
|
|
4
|
+
|
|
5
|
+
import { Textarea } from "easy";
|
|
6
|
+
|
|
7
|
+
export default withStyle(Textarea)`
|
|
8
|
+
|
|
9
|
+
border: 1px solid darkgrey;
|
|
10
|
+
height: 12rem;
|
|
11
|
+
resize: vertical;
|
|
12
|
+
padding: 0.25rem;
|
|
13
|
+
font-size: 1.2rem;
|
|
14
|
+
line-height: 1.5rem;
|
|
15
|
+
white-space: pre;
|
|
16
|
+
font-family: monospace;
|
|
17
|
+
|
|
18
|
+
`;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import withStyle from "easy-with-style"; ///
|
|
4
|
+
|
|
5
|
+
import { Element } from "easy";
|
|
6
|
+
import { queryUtilities } from "../index"; ///
|
|
7
|
+
import { CSSLexer, CSSParser } from "with-style";
|
|
8
|
+
import { RowsDiv, ColumnDiv, ColumnsDiv, VerticalSplitterDiv } from "easy-layout";
|
|
9
|
+
|
|
10
|
+
import SubHeading from "./view/subHeading";
|
|
11
|
+
import SizeableDiv from "./view/div/sizeable";
|
|
12
|
+
import NodesTextarea from "./view/textarea/nodes";
|
|
13
|
+
import ContentTextarea from "./view/textarea/content";
|
|
14
|
+
import MaximumDepthInput from "./view/input/maximumDepth";
|
|
15
|
+
import ExpressionStringInput from "./view/input/expressionString";
|
|
16
|
+
import ParseTreeTextarea from "./view/textarea/parseTree";
|
|
17
|
+
|
|
18
|
+
const cssLexer = CSSLexer.fromNothing(),
|
|
19
|
+
cssParser = CSSParser.fromNothing();
|
|
20
|
+
|
|
21
|
+
const { queryByExpressionString } = queryUtilities;
|
|
22
|
+
|
|
23
|
+
class View extends Element {
|
|
24
|
+
keyUpHandler = (event, element) => {
|
|
25
|
+
this.clearNodes();
|
|
26
|
+
|
|
27
|
+
this.clearParseTree();
|
|
28
|
+
|
|
29
|
+
const content = this.getContent(),
|
|
30
|
+
tokens = cssLexer.tokenise(content),
|
|
31
|
+
node = cssParser.parse(tokens);
|
|
32
|
+
|
|
33
|
+
if (node === null) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const abridged = true,
|
|
38
|
+
parseTree = node.asParseTree(tokens, abridged),
|
|
39
|
+
expressionString = this.getExpressionString(),
|
|
40
|
+
maximumDepth = this.getMaximumDepth(),
|
|
41
|
+
nodes = queryByExpressionString(node, expressionString, maximumDepth);
|
|
42
|
+
|
|
43
|
+
if (nodes !== null) {
|
|
44
|
+
this.setNodes(nodes, tokens); ///
|
|
45
|
+
|
|
46
|
+
this.setParseTree(parseTree);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
childElements() {
|
|
51
|
+
return ([
|
|
52
|
+
|
|
53
|
+
<ColumnsDiv>
|
|
54
|
+
<SizeableDiv>
|
|
55
|
+
<RowsDiv>
|
|
56
|
+
<SubHeading>
|
|
57
|
+
Expression
|
|
58
|
+
</SubHeading>
|
|
59
|
+
<ExpressionStringInput onKeyUp={this.keyUpHandler} />
|
|
60
|
+
<SubHeading>
|
|
61
|
+
Maximum depth
|
|
62
|
+
</SubHeading>
|
|
63
|
+
<MaximumDepthInput onKeyUp={this.keyUpHandler} />
|
|
64
|
+
</RowsDiv>
|
|
65
|
+
</SizeableDiv>
|
|
66
|
+
<VerticalSplitterDiv />
|
|
67
|
+
<ColumnDiv>
|
|
68
|
+
<RowsDiv>
|
|
69
|
+
<SubHeading>
|
|
70
|
+
Content
|
|
71
|
+
</SubHeading>
|
|
72
|
+
<ContentTextarea onKeyUp={this.keyUpHandler} />
|
|
73
|
+
<SubHeading>
|
|
74
|
+
Parse tree
|
|
75
|
+
</SubHeading>
|
|
76
|
+
<ParseTreeTextarea />
|
|
77
|
+
<SubHeading>
|
|
78
|
+
Nodes
|
|
79
|
+
</SubHeading>
|
|
80
|
+
<NodesTextarea />
|
|
81
|
+
</RowsDiv>
|
|
82
|
+
</ColumnDiv>
|
|
83
|
+
</ColumnsDiv>
|
|
84
|
+
|
|
85
|
+
]);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
initialise() {
|
|
89
|
+
this.assignContext();
|
|
90
|
+
|
|
91
|
+
const { initialContent, initialExpressionString, initialMaximumDepth } = this.constructor,
|
|
92
|
+
content = initialContent, ///
|
|
93
|
+
maximumDepth = initialMaximumDepth, ///
|
|
94
|
+
expressionString = initialExpressionString; ///
|
|
95
|
+
|
|
96
|
+
this.setContent(content);
|
|
97
|
+
|
|
98
|
+
this.setMaximumDepth(maximumDepth);
|
|
99
|
+
|
|
100
|
+
this.setExpressionString(expressionString);
|
|
101
|
+
|
|
102
|
+
this.keyUpHandler(); ///
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static initialContent = `.view {
|
|
106
|
+
background: red;
|
|
107
|
+
}
|
|
108
|
+
`;
|
|
109
|
+
|
|
110
|
+
static initialExpressionString = "/*//@special[2...4]";
|
|
111
|
+
|
|
112
|
+
static initialMaximumDepth = 5;
|
|
113
|
+
|
|
114
|
+
static tagName = "div";
|
|
115
|
+
|
|
116
|
+
static defaultProperties = {
|
|
117
|
+
className: "view"
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export default withStyle(View)`
|
|
122
|
+
|
|
123
|
+
padding: 1rem;
|
|
124
|
+
|
|
125
|
+
`;
|
package/src/example.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import "juxtapose";
|
|
4
|
+
|
|
5
|
+
import withStyle from "easy-with-style"; ///
|
|
6
|
+
|
|
7
|
+
import { Body } from "easy";
|
|
8
|
+
|
|
9
|
+
import View from "./example/view";
|
|
10
|
+
|
|
11
|
+
const { renderStyles } = withStyle;
|
|
12
|
+
|
|
13
|
+
const body = new Body();
|
|
14
|
+
|
|
15
|
+
renderStyles();
|
|
16
|
+
|
|
17
|
+
body.mount(
|
|
18
|
+
|
|
19
|
+
<View/>
|
|
20
|
+
|
|
21
|
+
);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const bnf = `
|
|
4
|
+
|
|
5
|
+
expression ::= path spread? subExpression?
|
|
6
|
+
|
|
7
|
+
| error+
|
|
8
|
+
|
|
9
|
+
;
|
|
10
|
+
|
|
11
|
+
path ::= "/" infiniteDescent? selectors ;
|
|
12
|
+
|
|
13
|
+
subExpression ::= path spread? subExpression?;
|
|
14
|
+
|
|
15
|
+
infiniteDescent ::= "/" ;
|
|
16
|
+
|
|
17
|
+
selectors ::= selector ( "|" selector )* ;
|
|
18
|
+
|
|
19
|
+
spread ::= unique
|
|
20
|
+
|
|
21
|
+
| "["
|
|
22
|
+
|
|
23
|
+
(
|
|
24
|
+
|
|
25
|
+
( startIndex "..." endIndex )
|
|
26
|
+
|
|
27
|
+
|
|
|
28
|
+
|
|
29
|
+
( startIndex "..." )
|
|
30
|
+
|
|
31
|
+
|
|
|
32
|
+
|
|
33
|
+
( "..." endIndex )
|
|
34
|
+
|
|
35
|
+
|
|
|
36
|
+
|
|
37
|
+
index
|
|
38
|
+
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
"]" ;
|
|
42
|
+
|
|
43
|
+
selector ::= ruleName | tokenType ;
|
|
44
|
+
|
|
45
|
+
ruleName ::= [name] | "*" ;
|
|
46
|
+
|
|
47
|
+
tokenType ::= "@"<NO_WHITESPACE>( [name] | "*" ) ;
|
|
48
|
+
|
|
49
|
+
startIndex ::= [number] ;
|
|
50
|
+
|
|
51
|
+
endIndex ::= [number] ;
|
|
52
|
+
|
|
53
|
+
index ::= [number] ;
|
|
54
|
+
|
|
55
|
+
unique ::= "!" ;
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
error. ::= . ;
|
|
60
|
+
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
export default bnf;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { CommonLexer, WhitespaceToken, EndOfLineSignificantToken } from "occam-lexers";
|
|
4
|
+
|
|
5
|
+
import entries from "./entries";
|
|
6
|
+
|
|
7
|
+
export default class ExpressionLexer extends CommonLexer {
|
|
8
|
+
static entries = entries;
|
|
9
|
+
|
|
10
|
+
static EndOfLineToken = EndOfLineSignificantToken; ///
|
|
11
|
+
|
|
12
|
+
static WhitespaceToken = WhitespaceToken;
|
|
13
|
+
|
|
14
|
+
static EndOfLineCommentToken = null;
|
|
15
|
+
|
|
16
|
+
static SingleLineCommentToken = null;
|
|
17
|
+
|
|
18
|
+
static RegularExpressionToken = null;
|
|
19
|
+
|
|
20
|
+
static EndOfMultiLineCommentToken = null;
|
|
21
|
+
|
|
22
|
+
static StartOfMultiLineCommentToken = null;
|
|
23
|
+
|
|
24
|
+
static MiddleOfMultiLineCommentToken = null;
|
|
25
|
+
|
|
26
|
+
static SinglyQuotedStringLiteralToken = null;
|
|
27
|
+
|
|
28
|
+
static DoublyQuotedStringLiteralToken = null;
|
|
29
|
+
|
|
30
|
+
static fromNothing() { return CommonLexer.fromNothing(ExpressionLexer); }
|
|
31
|
+
|
|
32
|
+
static fromRules(rules) { return CommonLexer.fromRules(ExpressionLexer, rules); }
|
|
33
|
+
|
|
34
|
+
static fromEntries(entries) { return CommonLexer.fromEntries(ExpressionLexer, entries); }
|
|
35
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { CommonParser } from "occam-parsers";
|
|
4
|
+
|
|
5
|
+
import bnf from "./bnf";
|
|
6
|
+
|
|
7
|
+
export default class ExpressionParser extends CommonParser {
|
|
8
|
+
static bnf = bnf;
|
|
9
|
+
|
|
10
|
+
static fromNothing() { return CommonParser.fromNothing(ExpressionParser); }
|
|
11
|
+
|
|
12
|
+
static fromBNF(bnf) { return CommonParser.fromBNF(ExpressionParser, bnf); }
|
|
13
|
+
|
|
14
|
+
static fromRules(rules) { return CommonParser.fromRules(ExpressionParser, rules); }
|
|
15
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import Path from "./path";
|
|
4
|
+
import Spread from "./spread";
|
|
5
|
+
import SubExpression from "./subExpression";
|
|
6
|
+
import ExpressionLexer from "./expression/lexer";
|
|
7
|
+
import ExpressionParser from "./expression/parser";
|
|
8
|
+
|
|
9
|
+
import { pathNodeFromExpressionNode,
|
|
10
|
+
spreadNodeFromExpressionNode,
|
|
11
|
+
errorNodesFromExpressionNode,
|
|
12
|
+
subExpressionNodeFromExpressionNode } from "./utilities/node";
|
|
13
|
+
|
|
14
|
+
const expressionLexer = ExpressionLexer.fromNothing(),
|
|
15
|
+
expressionParser = ExpressionParser.fromNothing();
|
|
16
|
+
|
|
17
|
+
export default class Expression {
|
|
18
|
+
constructor(path, spread, subExpression) {
|
|
19
|
+
this.path = path;
|
|
20
|
+
this.spread = spread;
|
|
21
|
+
this.subExpression = subExpression;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getPath() {
|
|
25
|
+
return this.path;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getSpread() {
|
|
29
|
+
return this.spread;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getSubExpression() {
|
|
33
|
+
return this.subExpression;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getRuleNames() { return this.path.getRuleNames(); }
|
|
37
|
+
|
|
38
|
+
getTokenTypes() { return this.path.getTokenTypes(); }
|
|
39
|
+
|
|
40
|
+
isInfiniteDescent() { return this.path.isInfiniteDescent(); }
|
|
41
|
+
|
|
42
|
+
static fromExpressionNode(expressionNode) {
|
|
43
|
+
const pathNode = pathNodeFromExpressionNode(expressionNode),
|
|
44
|
+
spreadNode = spreadNodeFromExpressionNode(expressionNode),
|
|
45
|
+
subExpressionNode = subExpressionNodeFromExpressionNode(expressionNode),
|
|
46
|
+
path = Path.fromPathNode(pathNode),
|
|
47
|
+
spread = Spread.fromSpreadNode(spreadNode),
|
|
48
|
+
subExpression = SubExpression.fromSubExpressionNode(subExpressionNode),
|
|
49
|
+
expression = new Expression(path, spread, subExpression);
|
|
50
|
+
|
|
51
|
+
return expression;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static fromExpressionString(expressionString) {
|
|
55
|
+
let expression = null;
|
|
56
|
+
|
|
57
|
+
const lexer = expressionLexer, ///
|
|
58
|
+
parser = expressionParser, ///
|
|
59
|
+
content = expressionString, ///
|
|
60
|
+
tokens = lexer.tokenise(content),
|
|
61
|
+
node = parser.parse(tokens);
|
|
62
|
+
|
|
63
|
+
if (node !== null) {
|
|
64
|
+
const expressionNode = node, ///
|
|
65
|
+
errorNodes = errorNodesFromExpressionNode(expressionNode),
|
|
66
|
+
errorNodesLength = errorNodes.length;
|
|
67
|
+
|
|
68
|
+
if (errorNodesLength === 0) {
|
|
69
|
+
const pathNode = pathNodeFromExpressionNode(expressionNode),
|
|
70
|
+
spreadNode = spreadNodeFromExpressionNode(expressionNode),
|
|
71
|
+
subExpressionNode = subExpressionNodeFromExpressionNode(expressionNode),
|
|
72
|
+
path = Path.fromPathNode(pathNode),
|
|
73
|
+
spread = Spread.fromSpreadNode(spreadNode),
|
|
74
|
+
subExpression = SubExpression.fromSubExpressionNode(subExpressionNode);
|
|
75
|
+
|
|
76
|
+
expression = new Expression(path, spread, subExpression);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return expression;
|
|
81
|
+
}
|
|
82
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export { default as Query } from "./query";
|
|
4
|
+
export { default as Expression } from "./expression";
|
|
5
|
+
export { default as queryUtilities } from "./utilities/query";
|
|
6
|
+
export { default as ExpressionLexer } from "./expression/lexer";
|
|
7
|
+
export { default as ExpressionParser } from "./expression/parser";
|
package/src/path.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { ruleNamesFromPathNode, tokenTypesFromPathNode, infiniteDescentFromPathNode } from "./utilities/node";
|
|
4
|
+
|
|
5
|
+
export default class Path {
|
|
6
|
+
constructor(ruleNames, tokenTypes, infiniteDescent) {
|
|
7
|
+
this.ruleNames = ruleNames;
|
|
8
|
+
this.tokenTypes = tokenTypes;
|
|
9
|
+
this.infiniteDescent = infiniteDescent;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
getRuleNames() {
|
|
13
|
+
return this.ruleNames;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getTokenTypes() {
|
|
17
|
+
return this.tokenTypes;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
isInfiniteDescent() {
|
|
21
|
+
return this.infiniteDescent;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static fromPathNode(pathNode) {
|
|
25
|
+
const ruleNames = ruleNamesFromPathNode(pathNode),
|
|
26
|
+
tokenTypes = tokenTypesFromPathNode(pathNode),
|
|
27
|
+
infiniteDescent = infiniteDescentFromPathNode(pathNode),
|
|
28
|
+
path = new Path(ruleNames, tokenTypes, infiniteDescent);
|
|
29
|
+
|
|
30
|
+
return path;
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/query.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { characters } from "necessary";
|
|
4
|
+
|
|
5
|
+
import Expression from "./expression";
|
|
6
|
+
|
|
7
|
+
import { push, clear, includes } from "./utilities/array";
|
|
8
|
+
|
|
9
|
+
const { WILDCARD_CHARACTER } = characters;
|
|
10
|
+
|
|
11
|
+
export default class Query {
|
|
12
|
+
constructor(spread, subQuery, ruleNames, tokenTypes, maximumDepth, infiniteDescent, intermediateNodes) {
|
|
13
|
+
this.spread = spread;
|
|
14
|
+
this.subQuery = subQuery;
|
|
15
|
+
this.ruleNames = ruleNames;
|
|
16
|
+
this.tokenTypes = tokenTypes;
|
|
17
|
+
this.maximumDepth = maximumDepth;
|
|
18
|
+
this.infiniteDescent = infiniteDescent;
|
|
19
|
+
this.intermediateNodes = intermediateNodes;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getSpread() {
|
|
23
|
+
return this.sprea;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getSubQuery() {
|
|
27
|
+
return this.subQuery;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getRuleNames() {
|
|
31
|
+
return this.ruleNames;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getTokenTypes() {
|
|
35
|
+
return this.tokenTypes;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getMaximumDepth() {
|
|
39
|
+
return this.maximumDepth;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
isInfiniteDescent() {
|
|
43
|
+
return this.infiniteDescent;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
getIntermediateNodes() {
|
|
47
|
+
return this.intermediateNodes;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
execute(node, depth = 0, maximumDepth = this.maximumDepth) {
|
|
51
|
+
const nodes = [];
|
|
52
|
+
|
|
53
|
+
this.clear();
|
|
54
|
+
|
|
55
|
+
this.find(node, depth, maximumDepth);
|
|
56
|
+
|
|
57
|
+
this.apply(nodes, depth, maximumDepth);
|
|
58
|
+
|
|
59
|
+
return nodes;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
clear() {
|
|
63
|
+
clear(this.intermediateNodes);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
find(node, depth, maximumDepth) {
|
|
67
|
+
if (depth > maximumDepth) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const nodeTerminalNode = node.isTerminalNode(),
|
|
72
|
+
nodeNonTerminalNode = !nodeTerminalNode;
|
|
73
|
+
|
|
74
|
+
let found;
|
|
75
|
+
|
|
76
|
+
if (nodeTerminalNode) {
|
|
77
|
+
const terminalNode = node, ///
|
|
78
|
+
types = this.tokenTypes, ///
|
|
79
|
+
type = terminalNode.getType();
|
|
80
|
+
|
|
81
|
+
found = includes(types, type, WILDCARD_CHARACTER);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (nodeNonTerminalNode) {
|
|
85
|
+
const nonTerminalNode = node, ///
|
|
86
|
+
ruleName = nonTerminalNode.getRuleName();
|
|
87
|
+
|
|
88
|
+
found = includes(this.ruleNames, ruleName, WILDCARD_CHARACTER);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (found) {
|
|
92
|
+
const intermediateNode = node; ///
|
|
93
|
+
|
|
94
|
+
this.intermediateNodes.push(intermediateNode);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (this.infiniteDescent) {
|
|
98
|
+
if (nodeNonTerminalNode) {
|
|
99
|
+
depth++;
|
|
100
|
+
|
|
101
|
+
const nonTerminalNode = node; ///
|
|
102
|
+
|
|
103
|
+
nonTerminalNode.forEachChildNode((childNode) => {
|
|
104
|
+
this.find(childNode, depth, maximumDepth);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
apply(nodes, depth, maximumDepth) {
|
|
111
|
+
this.spread.adjustNodes(this.intermediateNodes);
|
|
112
|
+
|
|
113
|
+
if (this.subQuery === null) {
|
|
114
|
+
push(nodes, this.intermediateNodes);
|
|
115
|
+
} else {
|
|
116
|
+
this.intermediateNodes.forEach((intermediateNode) => {
|
|
117
|
+
const intermediateNodeNonTerminalNode = intermediateNode.isNonTerminalNode();
|
|
118
|
+
|
|
119
|
+
if (intermediateNodeNonTerminalNode) {
|
|
120
|
+
depth++;
|
|
121
|
+
|
|
122
|
+
const nonTerminalNode = intermediateNode; ///
|
|
123
|
+
|
|
124
|
+
this.subQuery.clear();
|
|
125
|
+
|
|
126
|
+
nonTerminalNode.forEachChildNode((childNode) => {
|
|
127
|
+
this.subQuery.find(childNode, depth, maximumDepth);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
this.subQuery.apply(nodes, depth, maximumDepth);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static fromExpression(expression, maximumDepth = Infinity) {
|
|
137
|
+
const spread = expression.getSpread(),
|
|
138
|
+
subQuery = subQueryFromExpression(expression),
|
|
139
|
+
ruleNames = expression.getRuleNames(),
|
|
140
|
+
tokenTypes = expression.getTokenTypes(),
|
|
141
|
+
infiniteDescent = expression.isInfiniteDescent(),
|
|
142
|
+
intermediateNodes = [],
|
|
143
|
+
query = new Query(spread, subQuery, ruleNames, tokenTypes, maximumDepth, infiniteDescent, intermediateNodes);
|
|
144
|
+
|
|
145
|
+
return query;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static fromSubExpression(subExpression) {
|
|
149
|
+
const spread = subExpression.getSpread(),
|
|
150
|
+
subQuery = subQueryFromSubExpression(subExpression),
|
|
151
|
+
ruleNames = subExpression.getRuleNames(),
|
|
152
|
+
tokenTypes = subExpression.getTokenTypes(),
|
|
153
|
+
maximumDepth = Infinity,
|
|
154
|
+
infiniteDescent = subExpression.isInfiniteDescent(),
|
|
155
|
+
intermediateNodes = [],
|
|
156
|
+
query = new Query(spread, subQuery, ruleNames, tokenTypes, maximumDepth, infiniteDescent, intermediateNodes);
|
|
157
|
+
|
|
158
|
+
return query;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static fromExpressionString(expressionString, maximumDepth = Infinity) {
|
|
162
|
+
let query = null;
|
|
163
|
+
|
|
164
|
+
const expression = Expression.fromExpressionString(expressionString);
|
|
165
|
+
|
|
166
|
+
if (expression !== null) {
|
|
167
|
+
const spread = expression.getSpread(),
|
|
168
|
+
subQuery = subQueryFromExpression(expression),
|
|
169
|
+
ruleNames = expression.getRuleNames(),
|
|
170
|
+
tokenTypes = expression.getTokenTypes(),
|
|
171
|
+
infiniteDescent = expression.isInfiniteDescent(),
|
|
172
|
+
intermediateNodes = [];
|
|
173
|
+
|
|
174
|
+
query = new Query(spread, subQuery, ruleNames, tokenTypes, maximumDepth, infiniteDescent, intermediateNodes);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return query;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function subQueryFromExpression(expression) {
|
|
182
|
+
let subQuery = null;
|
|
183
|
+
|
|
184
|
+
const subExpression = expression.getSubExpression();
|
|
185
|
+
|
|
186
|
+
if (subExpression !== null) {
|
|
187
|
+
const query = Query.fromSubExpression(subExpression);
|
|
188
|
+
|
|
189
|
+
subQuery = query; ///
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return subQuery;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function subQueryFromSubExpression(subExpression) {
|
|
196
|
+
let subQuery = null;
|
|
197
|
+
|
|
198
|
+
subExpression = subExpression.getSubExpression(); ///
|
|
199
|
+
|
|
200
|
+
if (subExpression !== null) {
|
|
201
|
+
const query = Query.fromSubExpression(subExpression);
|
|
202
|
+
|
|
203
|
+
subQuery = query; ///
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return subQuery;
|
|
207
|
+
}
|
package/src/ruleNames.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export const ERROR_RULE_NAME = "error";
|
|
4
|
+
export const INDEX_RULE_NAME = "index";
|
|
5
|
+
export const UNIQUE_RULE_NAME = "unique";
|
|
6
|
+
export const SPREAD_RULE_NAME = "spread";
|
|
7
|
+
export const END_INDEX_RULE_NAME = "endIndex";
|
|
8
|
+
export const RULE_NAME_RULE_NAME = "ruleName";
|
|
9
|
+
export const TOKEN_TYPE_RULE_NAME = "tokenType";
|
|
10
|
+
export const START_INDEX_RULE_NAME = "startIndex";
|
|
11
|
+
export const SUB_EXPRESSION_RULE_NAME = "subExpression";
|
|
12
|
+
export const INFINITE_DESCENT_RULE_NAME = "infiniteDescent";
|