@bablr/boot 0.4.0 → 0.6.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/lib/builders.js +122 -55
- package/lib/index.js +131 -39
- package/lib/index.mjs +15 -1
- package/lib/languages/cstml.js +54 -40
- package/lib/languages/instruction.js +1 -1
- package/lib/languages/regex.js +3 -3
- package/lib/languages/spamex.js +41 -8
- package/lib/match.js +1 -1
- package/lib/miniparser.js +18 -6
- package/lib/print.js +196 -128
- package/package.json +3 -2
- package/shorthand.macro.js +108 -69
- package/lib/symbols.js +0 -4
package/lib/builders.js
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
const sym = require('@bablr/boot-helpers/symbols');
|
|
1
2
|
const { freeze, getPrototypeOf } = Object;
|
|
2
3
|
const { isArray } = Array;
|
|
4
|
+
const {
|
|
5
|
+
DoctypeTag,
|
|
6
|
+
OpenNodeTag,
|
|
7
|
+
CloseNodeTag,
|
|
8
|
+
OpenFragmentTag,
|
|
9
|
+
CloseFragmentTag,
|
|
10
|
+
ReferenceTag,
|
|
11
|
+
GapTag,
|
|
12
|
+
LiteralTag,
|
|
13
|
+
} = require('@bablr/boot-helpers/symbols');
|
|
3
14
|
|
|
4
15
|
const spreads = new WeakMap();
|
|
5
16
|
|
|
@@ -31,16 +42,16 @@ const interpolateArray = (values, buildSeparator) => {
|
|
|
31
42
|
return children;
|
|
32
43
|
};
|
|
33
44
|
|
|
34
|
-
const
|
|
45
|
+
const buildTag = (term) => {
|
|
35
46
|
switch (term?.type) {
|
|
36
|
-
case
|
|
47
|
+
case LiteralTag:
|
|
37
48
|
return term;
|
|
38
49
|
|
|
39
50
|
// case 'Escape':
|
|
40
51
|
// return buildEscapeNode;
|
|
41
52
|
|
|
42
53
|
default:
|
|
43
|
-
throw new Error('Invalid
|
|
54
|
+
throw new Error('Invalid tag of type ' + term.type);
|
|
44
55
|
}
|
|
45
56
|
};
|
|
46
57
|
|
|
@@ -48,34 +59,54 @@ const interpolateString = (value) => {
|
|
|
48
59
|
const children = [];
|
|
49
60
|
if (isArray(value)) {
|
|
50
61
|
for (const element of value) {
|
|
51
|
-
children.push(
|
|
62
|
+
children.push(buildTag(element));
|
|
52
63
|
}
|
|
53
64
|
} else {
|
|
54
65
|
// we can't safely interpolate strings here, though I wish we could
|
|
55
|
-
children.push(
|
|
66
|
+
children.push(buildTag(value));
|
|
56
67
|
}
|
|
57
68
|
|
|
58
69
|
return buildNode('String', 'Content', children);
|
|
59
70
|
};
|
|
60
71
|
|
|
61
|
-
const
|
|
62
|
-
return freeze({
|
|
72
|
+
const buildDoctypeTag = (attributes) => {
|
|
73
|
+
return freeze({
|
|
74
|
+
type: DoctypeTag,
|
|
75
|
+
value: freeze({ doctype: 'cstml', version: 0, attributes }),
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const buildReferenceTag = (name, isArray) => {
|
|
80
|
+
return freeze({ type: ReferenceTag, value: freeze({ name, isArray }) });
|
|
63
81
|
};
|
|
64
82
|
|
|
65
|
-
const
|
|
66
|
-
return freeze({ type:
|
|
83
|
+
const buildGapTag = () => {
|
|
84
|
+
return freeze({ type: GapTag, value: undefined });
|
|
67
85
|
};
|
|
68
86
|
|
|
69
|
-
const buildNodeOpenTag = (flags, type, attributes = {}) => {
|
|
70
|
-
return freeze({ type:
|
|
87
|
+
const buildNodeOpenTag = (flags, language, type, attributes = {}) => {
|
|
88
|
+
return freeze({ type: OpenNodeTag, value: freeze({ flags, language, type, attributes }) });
|
|
71
89
|
};
|
|
72
90
|
|
|
73
91
|
const buildNodeCloseTag = (type) => {
|
|
74
|
-
return freeze({ type:
|
|
92
|
+
return freeze({ type: CloseNodeTag, value: freeze({ type }) });
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const buildFragmentOpenTag = (flags = {}) => {
|
|
96
|
+
return freeze({
|
|
97
|
+
type: OpenFragmentTag,
|
|
98
|
+
value: freeze({
|
|
99
|
+
flags: freeze(flags),
|
|
100
|
+
}),
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const buildFragmentCloseTag = (type = null, language = null) => {
|
|
105
|
+
return freeze({ type: CloseFragmentTag, value: freeze({ language, type }) });
|
|
75
106
|
};
|
|
76
107
|
|
|
77
|
-
const
|
|
78
|
-
return freeze({ type:
|
|
108
|
+
const buildLiteralTag = (value) => {
|
|
109
|
+
return freeze({ type: LiteralTag, value });
|
|
79
110
|
};
|
|
80
111
|
|
|
81
112
|
const buildProperty = (key, value) => {
|
|
@@ -87,43 +118,43 @@ const buildProperty = (key, value) => {
|
|
|
87
118
|
};
|
|
88
119
|
|
|
89
120
|
const buildString = (value) => {
|
|
90
|
-
const
|
|
121
|
+
const Tags = [];
|
|
91
122
|
let literal = '';
|
|
92
123
|
for (const chr of value) {
|
|
93
124
|
if (chr === "'") {
|
|
94
125
|
if (literal)
|
|
95
|
-
|
|
126
|
+
Tags.push(
|
|
96
127
|
freeze({
|
|
97
|
-
type:
|
|
128
|
+
type: LiteralTag,
|
|
98
129
|
value: literal,
|
|
99
130
|
}),
|
|
100
131
|
);
|
|
101
|
-
|
|
132
|
+
Tags.push(
|
|
102
133
|
e_node(
|
|
103
134
|
'String',
|
|
104
135
|
'Escape',
|
|
105
136
|
[ref`escape`, ref`escapee`],
|
|
106
137
|
{
|
|
107
138
|
escape: s_node('String', 'Punctuator', '\\'),
|
|
108
|
-
escapee: s_node('String',
|
|
139
|
+
escapee: s_node('String', LiteralTag, "'"),
|
|
109
140
|
},
|
|
110
141
|
{ cooked: chr },
|
|
111
142
|
),
|
|
112
143
|
);
|
|
113
144
|
} else if (chr === '\\') {
|
|
114
145
|
if (literal)
|
|
115
|
-
|
|
116
|
-
type:
|
|
146
|
+
Tags.push({
|
|
147
|
+
type: LiteralTag,
|
|
117
148
|
value: literal,
|
|
118
149
|
});
|
|
119
|
-
|
|
150
|
+
Tags.push(
|
|
120
151
|
e_node(
|
|
121
152
|
'String',
|
|
122
153
|
'Escape',
|
|
123
154
|
[ref`escape`, ref`escapee`],
|
|
124
155
|
{
|
|
125
156
|
escape: s_node('String', 'Punctuator', '\\'),
|
|
126
|
-
escapee: s_node('String',
|
|
157
|
+
escapee: s_node('String', LiteralTag, '\\'),
|
|
127
158
|
},
|
|
128
159
|
{ cooked: chr },
|
|
129
160
|
),
|
|
@@ -133,9 +164,9 @@ const buildString = (value) => {
|
|
|
133
164
|
}
|
|
134
165
|
}
|
|
135
166
|
if (literal)
|
|
136
|
-
|
|
167
|
+
Tags.push(
|
|
137
168
|
freeze({
|
|
138
|
-
type:
|
|
169
|
+
type: LiteralTag,
|
|
139
170
|
value: literal,
|
|
140
171
|
}),
|
|
141
172
|
);
|
|
@@ -145,7 +176,7 @@ const buildString = (value) => {
|
|
|
145
176
|
[ref`open`, ref`content`, ref`close`],
|
|
146
177
|
{
|
|
147
178
|
open: s_node('String', 'Punctuator', "'"),
|
|
148
|
-
content: interpolateString(
|
|
179
|
+
content: interpolateString(Tags),
|
|
149
180
|
close: s_node('String', 'Punctuator', "'"),
|
|
150
181
|
},
|
|
151
182
|
{},
|
|
@@ -174,7 +205,7 @@ const buildBoolean = (value) => {
|
|
|
174
205
|
);
|
|
175
206
|
};
|
|
176
207
|
|
|
177
|
-
const
|
|
208
|
+
const buildNullTag = () => {
|
|
178
209
|
return node(
|
|
179
210
|
'Instruction',
|
|
180
211
|
'Null',
|
|
@@ -186,7 +217,7 @@ const buildNull = () => {
|
|
|
186
217
|
);
|
|
187
218
|
};
|
|
188
219
|
|
|
189
|
-
const
|
|
220
|
+
const buildArrayTag = (elements) => {
|
|
190
221
|
return node(
|
|
191
222
|
'Instruction',
|
|
192
223
|
'Array',
|
|
@@ -237,7 +268,7 @@ const buildSpace = () => {
|
|
|
237
268
|
};
|
|
238
269
|
|
|
239
270
|
const buildIdentifier = (name) => {
|
|
240
|
-
return node('Instruction', 'Identifier', [
|
|
271
|
+
return node('Instruction', 'Identifier', [buildLiteralTag(name)]);
|
|
241
272
|
};
|
|
242
273
|
|
|
243
274
|
const buildAttribute = (key, value) => {
|
|
@@ -249,7 +280,7 @@ const buildAttribute = (key, value) => {
|
|
|
249
280
|
};
|
|
250
281
|
|
|
251
282
|
const buildExpression = (expr) => {
|
|
252
|
-
if (expr == null) return
|
|
283
|
+
if (expr == null) return buildNullTag();
|
|
253
284
|
|
|
254
285
|
switch (typeof expr) {
|
|
255
286
|
case 'boolean':
|
|
@@ -259,7 +290,7 @@ const buildExpression = (expr) => {
|
|
|
259
290
|
case 'object': {
|
|
260
291
|
switch (getPrototypeOf(expr)) {
|
|
261
292
|
case Array.prototype:
|
|
262
|
-
return
|
|
293
|
+
return buildArrayTag(expr);
|
|
263
294
|
case Object.prototype:
|
|
264
295
|
if (expr.type && expr.language && expr.children && expr.properties) {
|
|
265
296
|
return expr;
|
|
@@ -276,39 +307,48 @@ const buildExpression = (expr) => {
|
|
|
276
307
|
|
|
277
308
|
const nodeFlags = freeze({ syntactic: false, escape: false, trivia: false });
|
|
278
309
|
|
|
279
|
-
const buildNode = (language, type, children = [], properties = {}, attributes = {}) =>
|
|
280
|
-
|
|
310
|
+
const buildNode = (language, type, children = [], properties = {}, attributes = {}) => {
|
|
311
|
+
const openTag = buildNodeOpenTag(nodeFlags, language, type, attributes);
|
|
312
|
+
const closeTag = buildNodeCloseTag(type);
|
|
313
|
+
return freeze({
|
|
281
314
|
flags: nodeFlags,
|
|
282
315
|
language,
|
|
283
316
|
type,
|
|
284
|
-
children: freeze(children),
|
|
317
|
+
children: freeze([openTag, ...children, closeTag]),
|
|
285
318
|
properties: freeze(properties),
|
|
286
319
|
attributes: freeze(attributes),
|
|
287
320
|
});
|
|
321
|
+
};
|
|
288
322
|
|
|
289
323
|
const syntacticFlags = freeze({ syntactic: true, escape: false, trivia: false });
|
|
290
324
|
|
|
291
|
-
const buildSyntacticNode = (language, type, value, attributes = {}) =>
|
|
292
|
-
|
|
325
|
+
const buildSyntacticNode = (language, type, value, attributes = {}) => {
|
|
326
|
+
const openTag = buildNodeOpenTag(syntacticFlags, language, type, attributes);
|
|
327
|
+
const closeTag = buildNodeCloseTag(type);
|
|
328
|
+
return freeze({
|
|
293
329
|
flags: syntacticFlags,
|
|
294
330
|
language,
|
|
295
331
|
type,
|
|
296
|
-
children: [
|
|
332
|
+
children: [openTag, buildLiteralTag(value), closeTag],
|
|
297
333
|
properties: freeze({}),
|
|
298
334
|
attributes: freeze(attributes),
|
|
299
335
|
});
|
|
336
|
+
};
|
|
300
337
|
|
|
301
338
|
const escapeFlags = freeze({ syntactic: false, escape: true, trivia: false });
|
|
302
339
|
|
|
303
|
-
const buildEscapeNode = (language, type, children = [], properties = {}, attributes = {}) =>
|
|
304
|
-
|
|
340
|
+
const buildEscapeNode = (language, type, children = [], properties = {}, attributes = {}) => {
|
|
341
|
+
const openTag = buildNodeOpenTag(escapeFlags, language, type, attributes);
|
|
342
|
+
const closeTag = buildNodeCloseTag(type);
|
|
343
|
+
return freeze({
|
|
305
344
|
flags: escapeFlags,
|
|
306
345
|
language,
|
|
307
346
|
type,
|
|
308
|
-
children: freeze(children),
|
|
347
|
+
children: freeze([openTag, ...children, closeTag]),
|
|
309
348
|
properties: freeze(properties),
|
|
310
349
|
attributes: freeze(attributes),
|
|
311
350
|
});
|
|
351
|
+
};
|
|
312
352
|
|
|
313
353
|
const syntacticEscapeFlags = freeze({ syntactic: true, escape: true, trivia: false });
|
|
314
354
|
|
|
@@ -318,27 +358,44 @@ const buildSyntacticEscapeNode = (
|
|
|
318
358
|
children = [],
|
|
319
359
|
properties = {},
|
|
320
360
|
attributes = {},
|
|
321
|
-
) =>
|
|
322
|
-
|
|
361
|
+
) => {
|
|
362
|
+
const openTag = buildNodeOpenTag(syntacticEscapeFlags, language, type, attributes);
|
|
363
|
+
const closeTag = buildNodeCloseTag(type);
|
|
364
|
+
return freeze({
|
|
323
365
|
flags: syntacticEscapeFlags,
|
|
324
366
|
language,
|
|
325
367
|
type,
|
|
326
|
-
children: freeze(children),
|
|
368
|
+
children: freeze([openTag, ...children, closeTag]),
|
|
327
369
|
properties: freeze(properties),
|
|
328
370
|
attributes: freeze(attributes),
|
|
329
371
|
});
|
|
372
|
+
};
|
|
330
373
|
|
|
331
374
|
const triviaFlags = freeze({ syntactic: false, escape: false, trivia: true });
|
|
332
375
|
|
|
333
|
-
const buildTriviaNode = (language, type, children = [], properties = {}, attributes = {}) =>
|
|
334
|
-
|
|
376
|
+
const buildTriviaNode = (language, type, children = [], properties = {}, attributes = {}) => {
|
|
377
|
+
const openTag = buildNodeOpenTag(triviaFlags, language, type, attributes);
|
|
378
|
+
const closeTag = buildNodeCloseTag(type);
|
|
379
|
+
return freeze({
|
|
335
380
|
flags: triviaFlags,
|
|
336
381
|
language,
|
|
337
382
|
type,
|
|
338
|
-
children: freeze(children),
|
|
383
|
+
children: freeze([openTag, ...children, closeTag]),
|
|
339
384
|
properties: freeze(properties),
|
|
340
385
|
attributes: freeze(attributes),
|
|
341
386
|
});
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
const buildGapNode = (attributes = []) => {
|
|
390
|
+
return freeze({
|
|
391
|
+
flags: nodeFlags,
|
|
392
|
+
language: null,
|
|
393
|
+
type: sym.gap,
|
|
394
|
+
children: freeze([buildGapTag()]),
|
|
395
|
+
properties: freeze({}),
|
|
396
|
+
attributes: freeze(attributes),
|
|
397
|
+
});
|
|
398
|
+
};
|
|
342
399
|
|
|
343
400
|
const stripArray = (val) => {
|
|
344
401
|
if (isArray(val)) {
|
|
@@ -355,19 +412,21 @@ const ref = (path) => {
|
|
|
355
412
|
if (isArray(path)) {
|
|
356
413
|
const pathIsArray = path[0].endsWith('[]');
|
|
357
414
|
const name = pathIsArray ? path[0].slice(0, -2) : path[0];
|
|
358
|
-
return
|
|
415
|
+
return buildReferenceTag(name, pathIsArray);
|
|
359
416
|
} else {
|
|
360
417
|
const { name, pathIsArray } = path;
|
|
361
|
-
return
|
|
418
|
+
return buildReferenceTag(name, pathIsArray);
|
|
362
419
|
}
|
|
363
420
|
};
|
|
364
421
|
|
|
365
|
-
const lit = (str) =>
|
|
422
|
+
const lit = (str) => buildLiteralTag(stripArray(str));
|
|
366
423
|
|
|
367
|
-
const gap =
|
|
424
|
+
const gap = buildGapTag;
|
|
425
|
+
const arr = buildArrayTag;
|
|
368
426
|
const nodeOpen = buildNodeOpenTag;
|
|
369
427
|
const nodeClose = buildNodeCloseTag;
|
|
370
428
|
const node = buildNode;
|
|
429
|
+
const g_node = buildGapNode;
|
|
371
430
|
const s_node = buildSyntacticNode;
|
|
372
431
|
const e_node = buildEscapeNode;
|
|
373
432
|
const s_e_node = buildSyntacticEscapeNode;
|
|
@@ -377,30 +436,38 @@ module.exports = {
|
|
|
377
436
|
buildProperty,
|
|
378
437
|
buildString,
|
|
379
438
|
buildBoolean,
|
|
380
|
-
|
|
381
|
-
|
|
439
|
+
buildNullTag,
|
|
440
|
+
buildArrayTag,
|
|
382
441
|
buildTuple,
|
|
383
442
|
buildObject,
|
|
384
443
|
buildExpression,
|
|
385
444
|
buildSpace,
|
|
386
445
|
buildIdentifier,
|
|
387
446
|
buildAttribute,
|
|
388
|
-
|
|
389
|
-
|
|
447
|
+
buildDoctypeTag,
|
|
448
|
+
buildReferenceTag,
|
|
449
|
+
buildGapTag,
|
|
390
450
|
buildNodeOpenTag,
|
|
391
451
|
buildNodeCloseTag,
|
|
392
|
-
|
|
452
|
+
buildFragmentOpenTag,
|
|
453
|
+
buildFragmentCloseTag,
|
|
454
|
+
buildLiteralTag,
|
|
393
455
|
buildNode,
|
|
394
456
|
buildSyntacticNode,
|
|
395
457
|
buildEscapeNode,
|
|
396
458
|
buildSyntacticEscapeNode,
|
|
397
459
|
buildTriviaNode,
|
|
460
|
+
buildGapNode,
|
|
461
|
+
nodeFlags,
|
|
462
|
+
|
|
398
463
|
ref,
|
|
399
464
|
lit,
|
|
400
465
|
gap,
|
|
466
|
+
arr,
|
|
401
467
|
nodeOpen,
|
|
402
468
|
nodeClose,
|
|
403
469
|
node,
|
|
470
|
+
g_node,
|
|
404
471
|
s_node,
|
|
405
472
|
e_node,
|
|
406
473
|
s_e_node,
|
package/lib/index.js
CHANGED
|
@@ -1,14 +1,53 @@
|
|
|
1
1
|
const { PathResolver } = require('@bablr/boot-helpers/path');
|
|
2
2
|
const cstml = require('./languages/cstml.js');
|
|
3
|
+
const spamex = require('./languages/spamex.js');
|
|
3
4
|
const regex = require('./languages/regex.js');
|
|
4
5
|
const instruction = require('./languages/instruction.js');
|
|
5
|
-
const {
|
|
6
|
+
const {
|
|
7
|
+
buildLiteralTag,
|
|
8
|
+
buildDoctypeTag,
|
|
9
|
+
buildNodeOpenTag,
|
|
10
|
+
buildNodeCloseTag,
|
|
11
|
+
buildFragmentOpenTag,
|
|
12
|
+
buildFragmentCloseTag,
|
|
13
|
+
buildTriviaNode,
|
|
14
|
+
buildGapNode,
|
|
15
|
+
buildSyntacticEscapeNode,
|
|
16
|
+
nodeFlags,
|
|
17
|
+
buildReferenceTag,
|
|
18
|
+
} = require('./builders.js');
|
|
6
19
|
const { TemplateParser } = require('./miniparser.js');
|
|
20
|
+
const { Resolver } = require('./print.js');
|
|
21
|
+
const {
|
|
22
|
+
OpenNodeTag,
|
|
23
|
+
CloseNodeTag,
|
|
24
|
+
ReferenceTag,
|
|
25
|
+
ArrayTag,
|
|
26
|
+
EmbeddedNode,
|
|
27
|
+
Trivia,
|
|
28
|
+
Escape,
|
|
29
|
+
} = require('@bablr/boot-helpers/symbols');
|
|
30
|
+
const btree = require('@bablr/boot-helpers/btree');
|
|
7
31
|
|
|
8
32
|
const { isArray } = Array;
|
|
9
33
|
const { hasOwn } = Object;
|
|
10
34
|
|
|
11
|
-
const
|
|
35
|
+
const get = (node, path) => {
|
|
36
|
+
const { type, properties } = node;
|
|
37
|
+
const { 1: name, 2: index } = /^([^\.]+)(?:\.(\d+))?/.exec(path) || [];
|
|
38
|
+
|
|
39
|
+
if (!hasOwn(properties, name)) {
|
|
40
|
+
throw new Error(`Cannot find {name: ${name}} on node of {type: ${type}}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (index != null) {
|
|
44
|
+
return properties[name]?.[parseInt(index, 10)];
|
|
45
|
+
} else {
|
|
46
|
+
return properties[name];
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const add = (obj, path, value) => {
|
|
12
51
|
const { name, isArray: pathIsArray } = path;
|
|
13
52
|
if (pathIsArray) {
|
|
14
53
|
if (!obj[name]) {
|
|
@@ -17,7 +56,7 @@ const set = (obj, path, value) => {
|
|
|
17
56
|
|
|
18
57
|
if (!isArray(obj[name])) throw new Error('bad array value');
|
|
19
58
|
|
|
20
|
-
obj[name].push(value);
|
|
59
|
+
obj[name] = btree.push(obj[name], value);
|
|
21
60
|
} else {
|
|
22
61
|
if (hasOwn(obj, name)) {
|
|
23
62
|
throw new Error('duplicate child name');
|
|
@@ -28,7 +67,7 @@ const set = (obj, path, value) => {
|
|
|
28
67
|
|
|
29
68
|
const buildTag = (language, defaultType) => {
|
|
30
69
|
const defaultTag = (quasis, ...exprs) => {
|
|
31
|
-
return
|
|
70
|
+
return getAgASTTree(
|
|
32
71
|
language,
|
|
33
72
|
new TemplateParser(language, quasis.raw, exprs).eval({
|
|
34
73
|
language: language.name,
|
|
@@ -44,7 +83,7 @@ const buildTag = (language, defaultType) => {
|
|
|
44
83
|
|
|
45
84
|
get(_, type) {
|
|
46
85
|
return (quasis, ...exprs) => {
|
|
47
|
-
return
|
|
86
|
+
return getAgASTTree(
|
|
48
87
|
language,
|
|
49
88
|
new TemplateParser(language, quasis.raw, exprs).eval({
|
|
50
89
|
language: language.name,
|
|
@@ -63,6 +102,23 @@ const parse = (language, type, sourceText) => {
|
|
|
63
102
|
});
|
|
64
103
|
};
|
|
65
104
|
|
|
105
|
+
const getAgASTTree = (language, miniNode) => {
|
|
106
|
+
const attributes = { 'bablr-language': language.canonicalURL };
|
|
107
|
+
return {
|
|
108
|
+
flags: nodeFlags,
|
|
109
|
+
language: language.canonicalURL,
|
|
110
|
+
type: null,
|
|
111
|
+
children: [
|
|
112
|
+
buildDoctypeTag(attributes),
|
|
113
|
+
buildFragmentOpenTag(nodeFlags, null, null, null),
|
|
114
|
+
buildReferenceTag('.'),
|
|
115
|
+
buildFragmentCloseTag(),
|
|
116
|
+
],
|
|
117
|
+
properties: { ['.']: getAgASTValue(language, miniNode) },
|
|
118
|
+
attributes,
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
|
|
66
122
|
const getAgASTValue = (language, miniNode) => {
|
|
67
123
|
if (!miniNode) return miniNode;
|
|
68
124
|
|
|
@@ -71,9 +127,14 @@ const getAgASTValue = (language, miniNode) => {
|
|
|
71
127
|
}
|
|
72
128
|
|
|
73
129
|
const { language: languageName, type, attributes } = miniNode;
|
|
74
|
-
const flags = {
|
|
130
|
+
const flags = {
|
|
131
|
+
escape: !!miniNode.flags?.escape,
|
|
132
|
+
trivia: !!miniNode.flags?.trivia,
|
|
133
|
+
token: false,
|
|
134
|
+
hasGap: false,
|
|
135
|
+
};
|
|
75
136
|
const properties = {};
|
|
76
|
-
|
|
137
|
+
let children = [];
|
|
77
138
|
const resolver = new PathResolver(miniNode);
|
|
78
139
|
const resolvedLanguage =
|
|
79
140
|
languageName !== language.name ? language.dependencies[languageName] : language;
|
|
@@ -90,60 +151,91 @@ const getAgASTValue = (language, miniNode) => {
|
|
|
90
151
|
type === 'Punctuator' ||
|
|
91
152
|
type === 'Keyword' ||
|
|
92
153
|
type === 'Identifier' ||
|
|
93
|
-
type === 'StringContent'
|
|
154
|
+
type === 'StringContent' ||
|
|
155
|
+
type === 'Escape' ||
|
|
156
|
+
miniNode.flags?.syntactic
|
|
94
157
|
) {
|
|
95
158
|
flags.token = true;
|
|
96
159
|
}
|
|
97
160
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
161
|
+
children = btree.push(
|
|
162
|
+
children,
|
|
163
|
+
buildNodeOpenTag(flags, resolvedLanguage.canonicalURL, type, attributes),
|
|
164
|
+
);
|
|
101
165
|
|
|
102
166
|
for (const child of miniNode.children) {
|
|
103
|
-
if (child.type ===
|
|
167
|
+
if (child.type === OpenNodeTag || child.type === CloseNodeTag) {
|
|
168
|
+
continue;
|
|
169
|
+
} else if (child.type === ReferenceTag) {
|
|
104
170
|
const path = child.value;
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
171
|
+
const { name, isArray } = path;
|
|
172
|
+
let node = resolver.get(child.value);
|
|
173
|
+
|
|
174
|
+
if (node === undefined) throw new Error();
|
|
175
|
+
|
|
176
|
+
const agASTNode = node === null ? buildGapNode() : getAgASTValue(resolvedLanguage, node);
|
|
177
|
+
|
|
178
|
+
if (isArray && !hasOwn(properties, name)) {
|
|
179
|
+
const newRef = { type: ReferenceTag, value: { name, isArray } };
|
|
180
|
+
const arrayTag = { type: ArrayTag, value: undefined };
|
|
181
|
+
|
|
182
|
+
children = btree.push(children, newRef);
|
|
183
|
+
children = btree.push(children, arrayTag);
|
|
184
|
+
|
|
185
|
+
add(properties, { name }, []);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
add(properties, path, agASTNode);
|
|
189
|
+
children = btree.push(children, { type: ReferenceTag, value: { name, isArray } });
|
|
190
|
+
} else if (child.type === Trivia) {
|
|
191
|
+
children = btree.push(children, {
|
|
192
|
+
type: EmbeddedNode,
|
|
193
|
+
value: getAgASTValue(
|
|
194
|
+
resolvedLanguage,
|
|
195
|
+
buildTriviaNode(languageName, 'Space', [buildLiteralTag(child.value)]),
|
|
196
|
+
),
|
|
119
197
|
});
|
|
120
|
-
} else if (child.type ===
|
|
198
|
+
} else if (child.type === Escape) {
|
|
121
199
|
const { cooked, raw } = child.value;
|
|
122
200
|
const attributes = { cooked };
|
|
123
201
|
|
|
124
|
-
children.push({
|
|
125
|
-
type:
|
|
126
|
-
value:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
children: [buildLiteral(raw)],
|
|
131
|
-
properties: {},
|
|
132
|
-
attributes,
|
|
133
|
-
},
|
|
202
|
+
children = btree.push(children, {
|
|
203
|
+
type: EmbeddedNode,
|
|
204
|
+
value: getAgASTValue(
|
|
205
|
+
resolvedLanguage,
|
|
206
|
+
buildSyntacticEscapeNode(languageName, 'Escape', [buildLiteralTag(raw)], {}, attributes),
|
|
207
|
+
),
|
|
134
208
|
});
|
|
135
209
|
} else {
|
|
136
|
-
|
|
210
|
+
if (child.type === ArrayTag) throw new Error('badbad');
|
|
211
|
+
children = btree.push(children, child);
|
|
137
212
|
}
|
|
138
213
|
}
|
|
139
214
|
|
|
215
|
+
children = btree.push(children, buildNodeCloseTag());
|
|
216
|
+
|
|
140
217
|
return { flags, language: resolvedLanguage.canonicalURL, type, children, properties, attributes };
|
|
141
218
|
};
|
|
142
219
|
|
|
143
220
|
const str = buildTag(cstml, 'String');
|
|
144
221
|
const num = buildTag(cstml, 'Integer');
|
|
145
222
|
const cst = buildTag(cstml, 'Node');
|
|
223
|
+
const spam = buildTag(spamex, 'Pattern');
|
|
146
224
|
const re = buildTag(regex, 'Pattern');
|
|
147
225
|
const i = buildTag(instruction, 'Call');
|
|
148
226
|
|
|
149
|
-
module.exports = {
|
|
227
|
+
module.exports = {
|
|
228
|
+
str,
|
|
229
|
+
num,
|
|
230
|
+
cst,
|
|
231
|
+
spam,
|
|
232
|
+
re,
|
|
233
|
+
i,
|
|
234
|
+
buildTag,
|
|
235
|
+
get,
|
|
236
|
+
add,
|
|
237
|
+
getAgASTValue,
|
|
238
|
+
TemplateParser,
|
|
239
|
+
Resolver,
|
|
240
|
+
parse,
|
|
241
|
+
};
|
package/lib/index.mjs
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
1
|
import index from './index.js';
|
|
2
2
|
|
|
3
|
-
export const {
|
|
3
|
+
export const {
|
|
4
|
+
str,
|
|
5
|
+
num,
|
|
6
|
+
cst,
|
|
7
|
+
cst: cstml,
|
|
8
|
+
spam,
|
|
9
|
+
spam: spamex,
|
|
10
|
+
re,
|
|
11
|
+
i,
|
|
12
|
+
buildTag,
|
|
13
|
+
set,
|
|
14
|
+
getAgASTValue,
|
|
15
|
+
TemplateParser,
|
|
16
|
+
parse,
|
|
17
|
+
} = index;
|