occam-dom 4.0.15 → 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.
Files changed (58) hide show
  1. package/bin/main.js +15 -0
  2. package/example.js +37842 -0
  3. package/index.html +47 -0
  4. package/lib/constants.js +13 -0
  5. package/lib/example/utilities/token.js +28 -0
  6. package/lib/example/view/div/sizeable.js +39 -0
  7. package/lib/example/view/input/expressionString.js +142 -0
  8. package/lib/example/view/input/maximumDepth.js +143 -0
  9. package/lib/example/view/input.js +39 -0
  10. package/lib/example/view/subHeading.js +39 -0
  11. package/lib/example/view/textarea/content.js +142 -0
  12. package/lib/example/view/textarea/nodes.js +155 -0
  13. package/lib/example/view/textarea/parseTree.js +166 -0
  14. package/lib/example/view/textarea.js +39 -0
  15. package/lib/example/view.js +239 -0
  16. package/lib/example.js +19 -0
  17. package/lib/expression/bnf.js +14 -0
  18. package/lib/expression/entries.js +27 -0
  19. package/lib/expression/lexer.js +145 -0
  20. package/lib/expression/parser.js +134 -0
  21. package/lib/expression.js +113 -0
  22. package/lib/index.js +39 -0
  23. package/lib/path.js +69 -0
  24. package/lib/query.js +216 -0
  25. package/lib/ruleNames.js +54 -0
  26. package/lib/spread.js +113 -0
  27. package/lib/subExpression.js +101 -0
  28. package/lib/utilities/array.js +67 -0
  29. package/lib/utilities/node.js +334 -0
  30. package/lib/utilities/query.js +39 -0
  31. package/package.json +3 -3
  32. package/src/constants.js +3 -0
  33. package/src/example/utilities/token.js +19 -0
  34. package/src/example/view/div/sizeable.js +12 -0
  35. package/src/example/view/input/expressionString.js +33 -0
  36. package/src/example/view/input/maximumDepth.js +35 -0
  37. package/src/example/view/input.js +14 -0
  38. package/src/example/view/subHeading.js +16 -0
  39. package/src/example/view/textarea/content.js +33 -0
  40. package/src/example/view/textarea/nodes.js +55 -0
  41. package/src/example/view/textarea/parseTree.js +46 -0
  42. package/src/example/view/textarea.js +18 -0
  43. package/src/example/view.js +125 -0
  44. package/src/example.js +21 -0
  45. package/src/expression/bnf.js +63 -0
  46. package/src/expression/entries.js +18 -0
  47. package/src/expression/lexer.js +35 -0
  48. package/src/expression/parser.js +15 -0
  49. package/src/expression.js +82 -0
  50. package/src/index.js +7 -0
  51. package/src/path.js +32 -0
  52. package/src/query.js +207 -0
  53. package/src/ruleNames.js +12 -0
  54. package/src/spread.js +104 -0
  55. package/src/subExpression.js +52 -0
  56. package/src/utilities/array.js +30 -0
  57. package/src/utilities/node.js +454 -0
  58. package/src/utilities/query.js +22 -0
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+
3
+ import Textarea from "../textarea";
4
+
5
+ import { EMPTY_STRING } from "../../../constants";
6
+ import { tokenIndexFromTerminalNodeAndTokens, tokenIndexesFromNonTerminalNodeAndTokens } from "../../utilities/token"
7
+
8
+ export default class NodesTextarea extends Textarea {
9
+ setNodes(nodes, tokens) { ///
10
+ const value = nodes.reduce((value, node) => {
11
+ const nodeTerminalNode = node.isTerminalNode();
12
+
13
+ if (nodeTerminalNode) {
14
+ const terminalNode = node, ///
15
+ significantToken = terminalNode.getSignificantToken(),
16
+ significantTokenType = significantToken.getType(),
17
+ tokenIndex = tokenIndexFromTerminalNodeAndTokens(terminalNode, tokens);
18
+
19
+ value = `${value}[${significantTokenType}]${tokenIndex}\n`;
20
+ } else {
21
+ const nonTerminalNode = node, ///
22
+ ruleName = nonTerminalNode.getRuleName(),
23
+ tokenIndexes = tokenIndexesFromNonTerminalNodeAndTokens(nonTerminalNode, tokens);
24
+
25
+ value = `${value}${ruleName}${tokenIndexes}\n`;
26
+ }
27
+
28
+ return value;
29
+ }, EMPTY_STRING);
30
+
31
+ this.setValue(value);
32
+ }
33
+
34
+ clearNodes() {
35
+ const value = EMPTY_STRING;
36
+
37
+ this.setValue(value);
38
+ }
39
+
40
+ parentContext() {
41
+ const setNodes = this.setNodes.bind(this),
42
+ clearNodes = this.clearNodes.bind(this);
43
+
44
+ return ({
45
+ setNodes,
46
+ clearNodes
47
+ });
48
+ }
49
+
50
+ static defaultProperties = {
51
+ className: "nodes",
52
+ spellCheck: "false",
53
+ readOnly: true
54
+ };
55
+ }
@@ -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,18 @@
1
+ "use strict";
2
+
3
+ const entries = [
4
+ {
5
+ "special": "^(?:@|!|\\*|\\||\\/|\\[|\\]|\\.\\.\\.)"
6
+ },
7
+ {
8
+ "name": "^[a-zA-Z\-]+"
9
+ },
10
+ {
11
+ "number": "^[0-9]+"
12
+ },
13
+ {
14
+ "unassigned": "^."
15
+ }
16
+ ];
17
+
18
+ export default entries;
@@ -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
+ }