@bablr/boot 0.1.4 → 0.1.6
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/lib/index.js +1 -1
- package/lib/languages/cstml.js +149 -9
- package/lib/languages/instruction.js +1 -0
- package/lib/languages/string.js +2 -2
- package/lib/miniparser.js +24 -15
- package/lib/path.js +11 -1
- package/lib/utils.js +5 -4
- package/package.json +2 -2
- package/shorthand.macro.js +15 -12
package/lib/index.js
CHANGED
|
@@ -35,6 +35,6 @@ const spam = buildTag(spamex, 'Matcher');
|
|
|
35
35
|
const re = buildTag(regex, 'Pattern');
|
|
36
36
|
const str = buildTag(string, 'String');
|
|
37
37
|
const num = buildTag(number, 'Number');
|
|
38
|
-
const cst = buildTag(cstml, '
|
|
38
|
+
const cst = buildTag(cstml, 'Fragment');
|
|
39
39
|
|
|
40
40
|
module.exports = { re, spam, str, num, i, cst };
|
package/lib/languages/cstml.js
CHANGED
|
@@ -14,20 +14,92 @@ const name = 'CSTML';
|
|
|
14
14
|
const dependencies = { Regex, String: StringLanguage, Number };
|
|
15
15
|
|
|
16
16
|
const covers = buildCovers({
|
|
17
|
-
[sym.node]: [
|
|
18
|
-
|
|
17
|
+
[sym.node]: [
|
|
18
|
+
'Attribute',
|
|
19
|
+
'Property',
|
|
20
|
+
'TagType',
|
|
21
|
+
'Node',
|
|
22
|
+
'OpenFragmentNodeTag',
|
|
23
|
+
'OpenTerminalNodeTag',
|
|
24
|
+
'OpenNodeTag',
|
|
25
|
+
'CloseNodeTag',
|
|
26
|
+
'Terminal',
|
|
27
|
+
],
|
|
28
|
+
[sym.fragment]: ['Attributes', 'Fragment'],
|
|
19
29
|
Attribute: ['MappingAttribute', 'BooleanAttribute'],
|
|
20
30
|
AttributeValue: ['String:String', 'Number:Number'],
|
|
21
31
|
TagType: ['Identifier', 'GlobalIdentifier'],
|
|
32
|
+
Terminal: ['Literal', 'Trivia', 'Escape'],
|
|
33
|
+
EmbeddedTerminal: ['Literal', 'Escape'],
|
|
22
34
|
});
|
|
23
35
|
|
|
24
36
|
const grammar = class CSTMLMiniparserGrammar {
|
|
25
37
|
Fragment(p) {
|
|
26
38
|
p.eatMatchTrivia(_);
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
p.eatProduction('OpenFragmentNodeTag', { path: 'open' });
|
|
40
|
+
p.eatProduction('FragmentChildren');
|
|
41
|
+
p.eatProduction('CloseNodeTag', { path: 'close' });
|
|
42
|
+
p.eatMatchTrivia(_);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
FragmentChildren(p) {
|
|
46
|
+
p.eatMatchTrivia(_);
|
|
47
|
+
while (p.match(/#['"]|\w/y) || p.atExpression) {
|
|
48
|
+
if (p.match(/#['"]/y)) {
|
|
49
|
+
p.eatProduction('Trivia', { path: 'children[]' });
|
|
50
|
+
} else {
|
|
51
|
+
p.eatProduction('Property', { path: 'children[]' });
|
|
52
|
+
}
|
|
53
|
+
p.eatMatchTrivia(_);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// @Node
|
|
58
|
+
Node(p) {
|
|
59
|
+
const openType = p.match('<|') ? 'OpenTerminalNodeTag' : 'OpenNodeTag';
|
|
60
|
+
const childrenType = openType === 'OpenNodeTag' ? 'NodeChildren' : 'TerminalNodeChildren';
|
|
61
|
+
|
|
62
|
+
if (p.match('<>')) throw new Error('Fragment is not a node');
|
|
63
|
+
|
|
64
|
+
const open = p.eatProduction(openType, { path: 'open' });
|
|
65
|
+
if (!open.attributes.selfClosing) {
|
|
66
|
+
p.eatProduction(childrenType);
|
|
67
|
+
p.eatProduction('CloseNodeTag', { path: 'close' });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
NodeChildren(p) {
|
|
72
|
+
let properties = 0;
|
|
73
|
+
|
|
74
|
+
p.eatMatchTrivia(_);
|
|
75
|
+
while (p.match(/#['"]|\w/y) || p.atExpression) {
|
|
76
|
+
if (p.match(/#['"]/y)) {
|
|
77
|
+
p.eatProduction('Trivia', { path: 'children[]' });
|
|
78
|
+
} else {
|
|
79
|
+
p.eatProduction('Property', { path: 'children[]' });
|
|
80
|
+
properties++;
|
|
81
|
+
}
|
|
29
82
|
p.eatMatchTrivia(_);
|
|
30
83
|
}
|
|
84
|
+
|
|
85
|
+
if (!properties) throw new Error('Nodes must match text');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
TerminalNodeChildren(p) {
|
|
89
|
+
let properties = 0;
|
|
90
|
+
|
|
91
|
+
p.eatMatchTrivia(_);
|
|
92
|
+
while (p.match(/[!#]?['"]|\w/y) || p.atExpression) {
|
|
93
|
+
if (p.match(/[!#]?['"]/y)) {
|
|
94
|
+
p.eatProduction('Terminal', { path: 'children[]' });
|
|
95
|
+
} else {
|
|
96
|
+
p.eatProduction('Property', { path: 'children[]' });
|
|
97
|
+
properties++;
|
|
98
|
+
}
|
|
99
|
+
p.eatMatchTrivia(_);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!properties) throw new Error('Nodes must match text');
|
|
31
103
|
}
|
|
32
104
|
|
|
33
105
|
// @Node
|
|
@@ -40,10 +112,9 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
40
112
|
}
|
|
41
113
|
|
|
42
114
|
// @Node
|
|
43
|
-
|
|
44
|
-
p.
|
|
45
|
-
p.
|
|
46
|
-
p.eatProduction('CloseNodeTag', { path: 'close' });
|
|
115
|
+
OpenFragmentNodeTag(p) {
|
|
116
|
+
p.eat('<', PN, { path: 'open', startSpan: 'Tag', balanced: '>' });
|
|
117
|
+
p.eat('>', PN, { path: 'close', endSpan: 'Tag', balancer: true });
|
|
47
118
|
}
|
|
48
119
|
|
|
49
120
|
// @Node
|
|
@@ -62,10 +133,35 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
62
133
|
p.eat('>', PN, { path: 'close', endSpan: 'Tag', balancer: true });
|
|
63
134
|
}
|
|
64
135
|
|
|
136
|
+
// @Node
|
|
137
|
+
OpenTerminalNodeTag(p) {
|
|
138
|
+
p.eat('<|', PN, { path: 'open', startSpan: 'Tag', balanced: '>' });
|
|
139
|
+
p.eatMatchTrivia(_);
|
|
140
|
+
p.eatProduction('TagType', { path: 'type' });
|
|
141
|
+
|
|
142
|
+
let sp = p.eatMatchTrivia(_);
|
|
143
|
+
|
|
144
|
+
let value;
|
|
145
|
+
if (sp && p.match(/['"/]/y)) {
|
|
146
|
+
value = p.eatProduction('EmbeddedTerminal', { path: 'value' });
|
|
147
|
+
sp = p.eatMatchTrivia(_);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if ((sp && p.match(/\w+/y)) || p.atExpression) {
|
|
151
|
+
p.eatProduction('Attributes');
|
|
152
|
+
sp = p.eatMatchTrivia(_);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
p.eatMatchTrivia(_);
|
|
156
|
+
p.eat('|>', PN, { path: 'close', endSpan: 'Tag', balancer: true });
|
|
157
|
+
|
|
158
|
+
return { attrs: { selfClosing: !!value } };
|
|
159
|
+
}
|
|
160
|
+
|
|
65
161
|
// @Node
|
|
66
162
|
CloseNodeTag(p) {
|
|
67
163
|
p.eat('</', PN, { path: 'open', startSpan: 'Tag', balanced: '>' });
|
|
68
|
-
|
|
164
|
+
// TODO permit .type
|
|
69
165
|
p.eat('>', PN, { path: 'close', endSpan: 'Tag', balancer: true });
|
|
70
166
|
}
|
|
71
167
|
|
|
@@ -138,6 +234,50 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
138
234
|
Identifier(p) {
|
|
139
235
|
p.eatLiteral(/\w+/y);
|
|
140
236
|
}
|
|
237
|
+
|
|
238
|
+
// @Cover
|
|
239
|
+
Terminal(p) {
|
|
240
|
+
if (p.match(/!['"]/y)) {
|
|
241
|
+
p.eatProduction('Escape');
|
|
242
|
+
} else if (p.match(/#['"]/y)) {
|
|
243
|
+
p.eatProduction('Trivia');
|
|
244
|
+
} else if (p.match(/['"]/y)) {
|
|
245
|
+
p.eatProduction('Literal');
|
|
246
|
+
} else {
|
|
247
|
+
throw new Error();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// @Cover
|
|
252
|
+
EmbeddedTerminal(p) {
|
|
253
|
+
if (p.match(/!['"]/y)) {
|
|
254
|
+
p.eatProduction('Escape');
|
|
255
|
+
} else if (p.match(/['"]/y)) {
|
|
256
|
+
p.eatProduction('Literal');
|
|
257
|
+
} else {
|
|
258
|
+
throw new Error();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// @Node
|
|
263
|
+
Escape(p) {
|
|
264
|
+
p.eat('!', PN, { path: 'escapeOperator' });
|
|
265
|
+
p.eatProduction('String:String', { path: 'rawValue' });
|
|
266
|
+
p.eatMatchTrivia(_);
|
|
267
|
+
p.eat(':', PN, { path: 'rawOperator' });
|
|
268
|
+
p.eatProduction('String:String', { path: 'value' });
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// @Node
|
|
272
|
+
Trivia(p) {
|
|
273
|
+
p.eat('#', PN, { path: 'trivializeOperator' });
|
|
274
|
+
p.eatProduction('String:String', { path: 'value' });
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// @Node
|
|
278
|
+
Literal(p) {
|
|
279
|
+
p.eatProduction('String:String', { path: 'value' });
|
|
280
|
+
}
|
|
141
281
|
};
|
|
142
282
|
|
|
143
283
|
module.exports = { name, dependencies, covers, grammar };
|
package/lib/languages/string.js
CHANGED
|
@@ -79,8 +79,8 @@ const grammar = class StringMiniparserGrammar {
|
|
|
79
79
|
: p.eatMatchEscape(/\\(u(\{\d{1,6}\}|\d{4})|x[0-9a-fA-F]{2}|[\\nrt0"])/y);
|
|
80
80
|
lit =
|
|
81
81
|
p.span.type === 'Single'
|
|
82
|
-
? p.eatMatchLiteral(/[^\r\n\\']+/y)
|
|
83
|
-
: p.eatMatchLiteral(/[^\r\n\\"]+/y);
|
|
82
|
+
? p.eatMatchLiteral(/[^\r\n\0\\']+/y)
|
|
83
|
+
: p.eatMatchLiteral(/[^\r\n\0\\"]+/y);
|
|
84
84
|
i++;
|
|
85
85
|
} while (esc || lit);
|
|
86
86
|
if (i === 1 && !esc && !lit) {
|
package/lib/miniparser.js
CHANGED
|
@@ -5,7 +5,8 @@ const isString = require('iter-tools-es/methods/is-string');
|
|
|
5
5
|
const isObject = require('iter-tools-es/methods/is-object');
|
|
6
6
|
const sym = require('./symbols.js');
|
|
7
7
|
const { Match } = require('./match.js');
|
|
8
|
-
const {
|
|
8
|
+
const { parsePath } = require('./path.js');
|
|
9
|
+
const { set, isRegex, isArray, getPrototypeOf, buildNode } = require('./utils.js');
|
|
9
10
|
|
|
10
11
|
class TemplateParser {
|
|
11
12
|
constructor(rootLanguage, quasis, expressions) {
|
|
@@ -163,19 +164,20 @@ class TemplateParser {
|
|
|
163
164
|
for (const { 0: key, 1: property } of Object.entries(result.properties)) {
|
|
164
165
|
if (isArray(property)) {
|
|
165
166
|
for (const value of property) {
|
|
166
|
-
set(properties,
|
|
167
|
+
set(properties, { pathName: key, pathIsArray: true }, value);
|
|
167
168
|
}
|
|
168
169
|
} else {
|
|
169
|
-
set(properties, key, property);
|
|
170
|
+
set(properties, { pathName: key, pathIsArray: false }, property);
|
|
170
171
|
}
|
|
171
172
|
}
|
|
172
173
|
}
|
|
173
174
|
} else if (parentPath?.node && (isNode || covers.has(type))) {
|
|
174
175
|
const { properties, children } = parentPath.node;
|
|
176
|
+
const path = parsePath(this.m.attrs.path);
|
|
175
177
|
|
|
176
|
-
children.push({ ...ref(
|
|
178
|
+
children.push({ ...ref(path), id });
|
|
177
179
|
|
|
178
|
-
set(properties,
|
|
180
|
+
set(properties, path, result);
|
|
179
181
|
}
|
|
180
182
|
} else {
|
|
181
183
|
if (isEmbedded) {
|
|
@@ -194,9 +196,11 @@ class TemplateParser {
|
|
|
194
196
|
node.attributes = result.attrs;
|
|
195
197
|
}
|
|
196
198
|
if (parentPath?.node && !covers.has(type)) {
|
|
197
|
-
|
|
199
|
+
const path = parsePath(this.m.attrs.path);
|
|
198
200
|
|
|
199
|
-
|
|
201
|
+
parentPath.node.children.push(ref(path));
|
|
202
|
+
|
|
203
|
+
set(parentPath.node.properties, path, node);
|
|
200
204
|
}
|
|
201
205
|
}
|
|
202
206
|
}
|
|
@@ -258,8 +262,10 @@ class TemplateParser {
|
|
|
258
262
|
|
|
259
263
|
this.held = null;
|
|
260
264
|
|
|
261
|
-
|
|
262
|
-
|
|
265
|
+
const path = parsePath(attrs.path);
|
|
266
|
+
|
|
267
|
+
children.push(ref(path));
|
|
268
|
+
set(properties, path, held);
|
|
263
269
|
|
|
264
270
|
return held;
|
|
265
271
|
}
|
|
@@ -276,8 +282,7 @@ class TemplateParser {
|
|
|
276
282
|
throw new Error();
|
|
277
283
|
}
|
|
278
284
|
|
|
279
|
-
const
|
|
280
|
-
const { pathIsArray, pathName } = parsePath(path);
|
|
285
|
+
const { pathIsArray, pathName } = lastChild.value;
|
|
281
286
|
|
|
282
287
|
this.held = pathIsArray ? arrayLast(properties[pathName]) : properties[pathName];
|
|
283
288
|
|
|
@@ -304,9 +309,11 @@ class TemplateParser {
|
|
|
304
309
|
|
|
305
310
|
this.updateSpans(attrs);
|
|
306
311
|
|
|
307
|
-
|
|
312
|
+
const path = parsePath(attrs.path);
|
|
308
313
|
|
|
309
|
-
this.node.
|
|
314
|
+
set(this.node.properties, path, buildNode(this.buildId(type), [lit(result)]));
|
|
315
|
+
|
|
316
|
+
this.node.children.push(ref(path));
|
|
310
317
|
|
|
311
318
|
return result;
|
|
312
319
|
}
|
|
@@ -332,9 +339,11 @@ class TemplateParser {
|
|
|
332
339
|
|
|
333
340
|
this.idx += result.length;
|
|
334
341
|
|
|
335
|
-
|
|
342
|
+
const path = parsePath(attrs.path);
|
|
343
|
+
|
|
344
|
+
set(this.node.properties, path, buildNode(this.buildId(type), [lit(result)]));
|
|
336
345
|
|
|
337
|
-
this.node.children.push(ref(
|
|
346
|
+
this.node.children.push(ref(path));
|
|
338
347
|
}
|
|
339
348
|
return result;
|
|
340
349
|
}
|
package/lib/path.js
CHANGED
|
@@ -10,6 +10,16 @@ const buildNode = (id) => {
|
|
|
10
10
|
};
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
+
const stripPathBraces = (str) => (str.endsWith('[]') ? str.slice(0, -2) : str);
|
|
14
|
+
|
|
15
|
+
const parsePath = (str) => {
|
|
16
|
+
const pathName = stripPathBraces(str);
|
|
17
|
+
|
|
18
|
+
if (!/^\w+$/.test(pathName)) throw new Error();
|
|
19
|
+
|
|
20
|
+
return { pathIsArray: pathName !== str, pathName };
|
|
21
|
+
};
|
|
22
|
+
|
|
13
23
|
class Path {
|
|
14
24
|
constructor(id, attributes, parent = null) {
|
|
15
25
|
this.id = id;
|
|
@@ -44,4 +54,4 @@ class Path {
|
|
|
44
54
|
}
|
|
45
55
|
}
|
|
46
56
|
|
|
47
|
-
module.exports = { Path, buildNode };
|
|
57
|
+
module.exports = { Path, buildNode, parsePath };
|
package/lib/utils.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const every = require('iter-tools-es/methods/every');
|
|
2
2
|
const isArray = require('iter-tools-es/methods/is-array');
|
|
3
3
|
const isString = require('iter-tools-es/methods/is-string');
|
|
4
|
-
const { parsePath, stripPathBraces } = require('@bablr/boot-helpers/path');
|
|
5
4
|
|
|
6
5
|
const { hasOwn, getPrototypeOf, getOwnPropertySymbols } = Object;
|
|
7
6
|
const isSymbol = (value) => typeof value === 'symbol';
|
|
@@ -54,7 +53,11 @@ const buildCovers = (rawAliases) => {
|
|
|
54
53
|
};
|
|
55
54
|
|
|
56
55
|
const set = (obj, path, value) => {
|
|
57
|
-
const { pathIsArray, pathName } =
|
|
56
|
+
const { pathIsArray, pathName } = path;
|
|
57
|
+
|
|
58
|
+
if (!pathName) {
|
|
59
|
+
throw new Error();
|
|
60
|
+
}
|
|
58
61
|
|
|
59
62
|
if (pathIsArray) {
|
|
60
63
|
if (!obj[pathName]) {
|
|
@@ -105,8 +108,6 @@ const id = (...args) => {
|
|
|
105
108
|
};
|
|
106
109
|
|
|
107
110
|
module.exports = {
|
|
108
|
-
parsePath,
|
|
109
|
-
stripPathBraces,
|
|
110
111
|
buildCovers,
|
|
111
112
|
set,
|
|
112
113
|
resolveDependentLanguage,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bablr/boot",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Compile-time tools for bootstrapping BABLR VM",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=12.0.0"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@babel/helper-module-imports": "^7.22.15",
|
|
19
19
|
"@babel/template": "^7.22.15",
|
|
20
20
|
"@babel/types": "7.23.0",
|
|
21
|
-
"@bablr/boot-helpers": "0.1.
|
|
21
|
+
"@bablr/boot-helpers": "0.1.2",
|
|
22
22
|
"escape-string-regexp": "4.0.0",
|
|
23
23
|
"iter-tools-es": "^7.5.3"
|
|
24
24
|
},
|
package/shorthand.macro.js
CHANGED
|
@@ -23,20 +23,21 @@ const isBoolean = (v) => typeof v === 'boolean';
|
|
|
23
23
|
|
|
24
24
|
const isPlainObject = (v) => isObject(v) && !isArray(v);
|
|
25
25
|
|
|
26
|
-
const set = (obj, path, value
|
|
26
|
+
const set = (obj, path, value) => {
|
|
27
|
+
const { pathName, pathIsArray } = path;
|
|
27
28
|
if (pathIsArray) {
|
|
28
|
-
if (!obj[
|
|
29
|
-
obj[
|
|
29
|
+
if (!obj[pathName]) {
|
|
30
|
+
obj[pathName] = [];
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
if (!isArray(obj[
|
|
33
|
+
if (!isArray(obj[pathName])) throw new Error('bad array value');
|
|
33
34
|
|
|
34
|
-
obj[
|
|
35
|
+
obj[pathName].push(value);
|
|
35
36
|
} else {
|
|
36
|
-
if (hasOwn(obj,
|
|
37
|
+
if (hasOwn(obj, pathName)) {
|
|
37
38
|
throw new Error('duplicate child name');
|
|
38
39
|
}
|
|
39
|
-
obj[
|
|
40
|
+
obj[pathName] = value;
|
|
40
41
|
}
|
|
41
42
|
};
|
|
42
43
|
|
|
@@ -64,7 +65,9 @@ const getASTValue = (v, exprs, bindings) => {
|
|
|
64
65
|
|
|
65
66
|
const generateNodeChild = (child, bindings) => {
|
|
66
67
|
if (child.type === 'Reference') {
|
|
67
|
-
|
|
68
|
+
const { pathName, pathIsArray } = child.value;
|
|
69
|
+
const printedRef = pathIsArray ? `${pathName}[]` : pathName;
|
|
70
|
+
return expression(`%%t%%.ref\`${printedRef}\``)({ t: bindings.t });
|
|
68
71
|
} else if (child.type === 'Literal') {
|
|
69
72
|
return expression(`%%t%%.lit\`${child.value.replace(/\\/g, '\\\\')}\``)({ t: bindings.t });
|
|
70
73
|
} else if (child.type === 'Trivia') {
|
|
@@ -82,7 +85,7 @@ const generateNodeChild = (child, bindings) => {
|
|
|
82
85
|
|
|
83
86
|
const generateNode = (node, exprs, bindings) => {
|
|
84
87
|
const resolver = new PathResolver(node);
|
|
85
|
-
const { children, type, language, attributes
|
|
88
|
+
const { children, type, language, attributes } = node;
|
|
86
89
|
const properties_ = {};
|
|
87
90
|
const children_ = [];
|
|
88
91
|
|
|
@@ -95,8 +98,8 @@ const generateNode = (node, exprs, bindings) => {
|
|
|
95
98
|
|
|
96
99
|
if (child.type === 'Reference') {
|
|
97
100
|
const path = child.value;
|
|
101
|
+
const { pathIsArray } = path;
|
|
98
102
|
const resolved = resolver.get(path);
|
|
99
|
-
const pathIsArray = isArray(properties[path]);
|
|
100
103
|
|
|
101
104
|
let embedded = resolved;
|
|
102
105
|
if (resolved) {
|
|
@@ -118,7 +121,7 @@ const generateNode = (node, exprs, bindings) => {
|
|
|
118
121
|
}
|
|
119
122
|
}
|
|
120
123
|
|
|
121
|
-
set(properties_, path, embedded
|
|
124
|
+
set(properties_, path, embedded);
|
|
122
125
|
}
|
|
123
126
|
}
|
|
124
127
|
|
|
@@ -157,7 +160,7 @@ const topTypes = {
|
|
|
157
160
|
spam: 'Matcher',
|
|
158
161
|
str: 'String',
|
|
159
162
|
num: 'Number',
|
|
160
|
-
cst: '
|
|
163
|
+
cst: 'Fragment',
|
|
161
164
|
};
|
|
162
165
|
|
|
163
166
|
const getTopScope = (scope) => {
|