@bablr/agast-vm-helpers 0.5.1 → 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/deembed.js +30 -18
- package/lib/embed.js +4 -2
- package/lib/index.js +209 -135
- package/lib/iterable.js +29 -0
- package/lib/languages.js +1 -1
- package/package.json +3 -2
- package/lib/builders.js +0 -696
package/lib/deembed.js
CHANGED
|
@@ -1,25 +1,37 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
EmbeddedNode,
|
|
3
|
+
EmbeddedObject,
|
|
4
|
+
EmbeddedTag,
|
|
5
|
+
EmbeddedMatcher,
|
|
6
|
+
EmbeddedRegex,
|
|
7
|
+
} from '@bablr/agast-helpers/symbols';
|
|
2
8
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
export const getEmbeddedObject = (expr) => {
|
|
10
|
+
if (!expr) return expr;
|
|
11
|
+
if (expr.type !== EmbeddedObject) throw new Error();
|
|
12
|
+
return expr.value;
|
|
13
|
+
};
|
|
6
14
|
|
|
7
|
-
export const
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return expr.map((value) => deembedExpression(value));
|
|
12
|
-
} else if (typeof expr === 'object') {
|
|
13
|
-
return Object.fromEntries(
|
|
14
|
-
Object.entries(expr.value).map(({ 0: key, 1: value }) => [key, deembedExpression(value)]),
|
|
15
|
-
);
|
|
16
|
-
} else {
|
|
17
|
-
throw new Error();
|
|
18
|
-
}
|
|
15
|
+
export const getEmbeddedNode = (expr) => {
|
|
16
|
+
if (!expr) return expr;
|
|
17
|
+
if (expr.type !== EmbeddedNode) throw new Error();
|
|
18
|
+
return expr.value;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
export const
|
|
21
|
+
export const getEmbeddedMatcher = (expr) => {
|
|
22
22
|
if (!expr) return expr;
|
|
23
|
-
if (expr.type !==
|
|
23
|
+
if (expr.type !== EmbeddedMatcher) throw new Error();
|
|
24
24
|
return expr.value;
|
|
25
25
|
};
|
|
26
|
+
|
|
27
|
+
export const getEmbeddedRegex = (expr) => {
|
|
28
|
+
if (!expr) return expr;
|
|
29
|
+
if (expr.type !== EmbeddedRegex) throw new Error();
|
|
30
|
+
return expr.value;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const getEmbeddedTag = (expr) => {
|
|
34
|
+
if (expr.type !== EmbeddedTag) throw new Error();
|
|
35
|
+
const tag = expr.value;
|
|
36
|
+
return tag;
|
|
37
|
+
};
|
package/lib/embed.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buildEmbeddedObject } from './internal-builders.js';
|
|
2
2
|
|
|
3
3
|
const { isArray } = Array;
|
|
4
4
|
const isString = (val) => typeof val === 'string';
|
|
@@ -10,7 +10,7 @@ export const embedExpression = (expr) => {
|
|
|
10
10
|
} else if (isArray(expr)) {
|
|
11
11
|
return expr.map((value) => embedExpression(value));
|
|
12
12
|
} else if (typeof expr === 'object') {
|
|
13
|
-
return
|
|
13
|
+
return buildEmbeddedObject(
|
|
14
14
|
Object.fromEntries(
|
|
15
15
|
Object.entries(expr).map(({ 0: key, 1: value }) => [key, embedExpression(value)]),
|
|
16
16
|
),
|
|
@@ -19,3 +19,5 @@ export const embedExpression = (expr) => {
|
|
|
19
19
|
throw new Error();
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
|
+
|
|
23
|
+
export { buildEmbeddedObject, buildEmbeddedObject as o };
|
package/lib/index.js
CHANGED
|
@@ -1,22 +1,37 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
sourceTextFor,
|
|
3
|
+
getCooked,
|
|
4
|
+
isNull,
|
|
5
|
+
nodeFlags,
|
|
6
|
+
printType,
|
|
7
|
+
buildGapTag,
|
|
8
|
+
buildEmbeddedMatcher,
|
|
9
|
+
isNullNode,
|
|
10
|
+
buildNullTag,
|
|
11
|
+
buildStubNode,
|
|
12
|
+
isFragmentNode,
|
|
13
|
+
buildReferenceTag,
|
|
14
|
+
} from '@bablr/agast-helpers/tree';
|
|
2
15
|
import * as btree from '@bablr/agast-helpers/btree';
|
|
3
|
-
import
|
|
4
|
-
|
|
16
|
+
import {
|
|
17
|
+
buildCloseNodeTag,
|
|
18
|
+
buildLiteralTag,
|
|
19
|
+
buildDoctypeTag,
|
|
20
|
+
referenceFlags,
|
|
21
|
+
buildEmbeddedRegex,
|
|
22
|
+
} from '@bablr/agast-helpers/builders';
|
|
5
23
|
import {
|
|
6
24
|
DoctypeTag,
|
|
7
25
|
OpenNodeTag,
|
|
8
|
-
OpenFragmentTag,
|
|
9
|
-
CloseFragmentTag,
|
|
10
26
|
CloseNodeTag,
|
|
11
|
-
ReferenceTag,
|
|
12
27
|
ShiftTag,
|
|
13
28
|
GapTag,
|
|
14
29
|
NullTag,
|
|
15
|
-
|
|
30
|
+
ArrayInitializerTag,
|
|
16
31
|
LiteralTag,
|
|
17
32
|
} from '@bablr/agast-helpers/symbols';
|
|
18
33
|
|
|
19
|
-
|
|
34
|
+
const { freeze } = Object;
|
|
20
35
|
|
|
21
36
|
export const effectsFor = (verb) => {
|
|
22
37
|
switch (verb) {
|
|
@@ -43,15 +58,21 @@ export const shouldBranch = (effects) => {
|
|
|
43
58
|
return effects ? effects.success === 'none' || effects.failure === 'none' : false;
|
|
44
59
|
};
|
|
45
60
|
|
|
46
|
-
const
|
|
47
|
-
let {
|
|
61
|
+
export const reifyNodeFlags = (flags) => {
|
|
62
|
+
let { tokenToken, hasGapToken } = flags.properties;
|
|
48
63
|
|
|
49
64
|
return {
|
|
50
|
-
token: !!reifyExpression(tokenToken),
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
token: !!(tokenToken && reifyExpression(tokenToken.node)),
|
|
66
|
+
hasGap: !!(hasGapToken && reifyExpression(hasGapToken.node)),
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const reifyReferenceFlags = (flags) => {
|
|
71
|
+
let { expressionToken, hasGapToken } = flags.properties;
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
expression: !!(expressionToken && reifyExpression(expressionToken.node)),
|
|
75
|
+
hasGap: !!(hasGapToken && reifyExpression(hasGapToken.node)),
|
|
55
76
|
};
|
|
56
77
|
};
|
|
57
78
|
|
|
@@ -64,18 +85,18 @@ export const reifyLanguage = (language) => {
|
|
|
64
85
|
export const reifyProperties = (properties = []) => {
|
|
65
86
|
const built = {};
|
|
66
87
|
for (const property of btree.traverse(properties)) {
|
|
67
|
-
switch (property.type) {
|
|
68
|
-
case 'Property': {
|
|
69
|
-
let { reference, value } = property.properties;
|
|
88
|
+
switch (property.node.type) {
|
|
89
|
+
case Symbol.for('Property'): {
|
|
90
|
+
let { reference, value: node } = property.node.properties;
|
|
70
91
|
|
|
71
|
-
reference = reifyExpression(reference);
|
|
72
|
-
|
|
92
|
+
reference = reifyExpression(reference.node);
|
|
93
|
+
node = reifyExpression(node.node);
|
|
73
94
|
|
|
74
95
|
if (reference.value.isArray) {
|
|
75
96
|
built[reference.value.name] ||= [];
|
|
76
|
-
built[reference.value.name].push(
|
|
97
|
+
built[reference.value.name].push({ reference, node });
|
|
77
98
|
} else {
|
|
78
|
-
built[reference.value.name] =
|
|
99
|
+
built[reference.value.name] = { reference, node };
|
|
79
100
|
}
|
|
80
101
|
break;
|
|
81
102
|
}
|
|
@@ -91,19 +112,20 @@ export const buildFragmentChildren = (node) => {
|
|
|
91
112
|
|
|
92
113
|
let built = [];
|
|
93
114
|
|
|
94
|
-
open = reifyExpression(open);
|
|
95
|
-
close = reifyExpression(close);
|
|
115
|
+
open = reifyExpression(open.node);
|
|
116
|
+
close = reifyExpression(close.node);
|
|
96
117
|
|
|
97
118
|
built = btree.push(built, open);
|
|
98
119
|
|
|
99
120
|
for (const child of btree.traverse(children)) {
|
|
100
|
-
if (child.type !== 'Property') throw new Error('umimplemented');
|
|
121
|
+
if (child.node.type !== Symbol.for('Property')) throw new Error('umimplemented');
|
|
101
122
|
|
|
102
|
-
let { reference } = child.properties;
|
|
123
|
+
let { reference } = child.node.properties;
|
|
103
124
|
|
|
104
|
-
reference = reifyExpression(reference);
|
|
125
|
+
reference = reifyExpression(reference.node);
|
|
105
126
|
|
|
106
127
|
built = btree.push(built, reference);
|
|
128
|
+
built = btree.push(built, buildGapTag());
|
|
107
129
|
}
|
|
108
130
|
|
|
109
131
|
built = btree.push(built, close);
|
|
@@ -114,29 +136,30 @@ export const buildFragmentChildren = (node) => {
|
|
|
114
136
|
export const buildChildren = (node) => {
|
|
115
137
|
let { open, children = [], close } = node.properties;
|
|
116
138
|
|
|
117
|
-
const selfClosing =
|
|
118
|
-
const { intrinsicValue } = open.properties;
|
|
139
|
+
const selfClosing = !isNull(open.node.properties.selfClosingTagToken?.node);
|
|
140
|
+
const { intrinsicValue } = open.node.properties;
|
|
119
141
|
let built = [];
|
|
120
142
|
|
|
121
|
-
open = reifyExpression(open);
|
|
122
|
-
close = reifyExpression(close);
|
|
143
|
+
open = reifyExpression(open.node);
|
|
144
|
+
close = reifyExpression(close?.node);
|
|
123
145
|
|
|
124
146
|
if (selfClosing) {
|
|
125
147
|
built = btree.push(built, open);
|
|
126
|
-
if (intrinsicValue) {
|
|
127
|
-
built = btree.push(built, buildLiteralTag(intrinsicValue));
|
|
148
|
+
if (!isNull(intrinsicValue?.node)) {
|
|
149
|
+
built = btree.push(built, buildLiteralTag(intrinsicValue.node));
|
|
128
150
|
}
|
|
129
|
-
built = btree.push(built,
|
|
151
|
+
built = btree.push(built, buildCloseNodeTag());
|
|
130
152
|
} else {
|
|
131
153
|
built = btree.push(built, open);
|
|
132
154
|
for (const child of btree.traverse(children)) {
|
|
133
|
-
if (child.type !== 'Property') throw new Error('umimplemented');
|
|
155
|
+
if (child.node.type !== Symbol.for('Property')) throw new Error('umimplemented');
|
|
134
156
|
|
|
135
|
-
let { reference } = child.properties;
|
|
157
|
+
let { reference } = child.node.properties;
|
|
136
158
|
|
|
137
|
-
reference = reifyExpression(reference);
|
|
159
|
+
reference = reifyExpression(reference.node);
|
|
138
160
|
|
|
139
161
|
built = btree.push(built, reference);
|
|
162
|
+
built = btree.push(built, buildGapTag());
|
|
140
163
|
}
|
|
141
164
|
|
|
142
165
|
built = btree.push(built, close);
|
|
@@ -148,10 +171,11 @@ export const buildChildren = (node) => {
|
|
|
148
171
|
export const reifyExpression = (node) => {
|
|
149
172
|
if (node instanceof Promise) throw new Error();
|
|
150
173
|
|
|
151
|
-
if (
|
|
174
|
+
if (node == null) return node;
|
|
175
|
+
if (isNullNode(node)) return null;
|
|
152
176
|
|
|
153
|
-
if (
|
|
154
|
-
node = node.properties['.'];
|
|
177
|
+
if (isFragmentNode(node)) {
|
|
178
|
+
node = node.properties['.'].node;
|
|
155
179
|
}
|
|
156
180
|
|
|
157
181
|
if (node.language === 'https://bablr.org/languages/core/en/cstml') {
|
|
@@ -159,19 +183,19 @@ export const reifyExpression = (node) => {
|
|
|
159
183
|
case 'Document': {
|
|
160
184
|
let { doctype, tree } = node.properties;
|
|
161
185
|
|
|
162
|
-
doctype = reifyExpression(doctype);
|
|
163
|
-
tree = reifyExpression(tree);
|
|
186
|
+
doctype = reifyExpression(doctype.node);
|
|
187
|
+
tree = reifyExpression(tree.node);
|
|
164
188
|
|
|
165
189
|
let { attributes } = doctype.value;
|
|
166
190
|
let { properties } = tree;
|
|
167
191
|
|
|
168
192
|
return {
|
|
169
193
|
flags: nodeFlags,
|
|
170
|
-
language: attributes
|
|
194
|
+
language: attributes.bablrLanguage,
|
|
171
195
|
type: null,
|
|
172
196
|
children: btree.addAt(
|
|
173
197
|
0,
|
|
174
|
-
buildFragmentChildren(node.properties.tree),
|
|
198
|
+
buildFragmentChildren(node.properties.tree.node),
|
|
175
199
|
buildDoctypeTag(attributes),
|
|
176
200
|
),
|
|
177
201
|
properties,
|
|
@@ -182,7 +206,7 @@ export const reifyExpression = (node) => {
|
|
|
182
206
|
case 'Node': {
|
|
183
207
|
let { open, children } = node.properties;
|
|
184
208
|
|
|
185
|
-
open = reifyExpression(open);
|
|
209
|
+
open = reifyExpression(open.node);
|
|
186
210
|
|
|
187
211
|
let { flags, language, type, attributes } = open.value;
|
|
188
212
|
|
|
@@ -201,7 +225,7 @@ export const reifyExpression = (node) => {
|
|
|
201
225
|
case 'Fragment': {
|
|
202
226
|
let { open, children } = node.properties;
|
|
203
227
|
|
|
204
|
-
open = reifyExpression(open);
|
|
228
|
+
open = reifyExpression(open.node);
|
|
205
229
|
|
|
206
230
|
let { flags } = open.value;
|
|
207
231
|
|
|
@@ -218,26 +242,24 @@ export const reifyExpression = (node) => {
|
|
|
218
242
|
}
|
|
219
243
|
|
|
220
244
|
case 'DoctypeTag': {
|
|
221
|
-
let {
|
|
245
|
+
let { doctypeToken, version, attributes } = node.properties;
|
|
222
246
|
return {
|
|
223
247
|
type: DoctypeTag,
|
|
224
248
|
value: {
|
|
225
|
-
|
|
226
|
-
version: parseInt(sourceTextFor(version), 10),
|
|
227
|
-
attributes:
|
|
249
|
+
doctypeToken: getCooked(doctypeToken?.node),
|
|
250
|
+
version: parseInt(sourceTextFor(version.node), 10),
|
|
251
|
+
attributes: reifyExpression(attributes.node),
|
|
228
252
|
},
|
|
229
253
|
};
|
|
230
254
|
}
|
|
231
255
|
|
|
232
256
|
case 'ReferenceTag': {
|
|
233
|
-
let { name, arrayOperatorToken,
|
|
257
|
+
let { name, arrayOperatorToken, flags } = node.properties;
|
|
234
258
|
|
|
235
|
-
name = reifyExpression(name);
|
|
259
|
+
name = reifyExpression(name.node);
|
|
260
|
+
flags = freeze({ expression: !!flags?.expressionToken, hasGap: !!flags?.hasGapToken });
|
|
236
261
|
|
|
237
|
-
return
|
|
238
|
-
type: ReferenceTag,
|
|
239
|
-
value: { name, isArray: !isNull(arrayOperatorToken), hasGap: !isNull(hasGapToken) },
|
|
240
|
-
};
|
|
262
|
+
return buildReferenceTag(name, !isNull(arrayOperatorToken?.node), flags);
|
|
241
263
|
}
|
|
242
264
|
|
|
243
265
|
case 'LiteralTag': {
|
|
@@ -245,20 +267,22 @@ export const reifyExpression = (node) => {
|
|
|
245
267
|
|
|
246
268
|
return { type: LiteralTag, value: getCooked(value.properties.content) };
|
|
247
269
|
}
|
|
270
|
+
|
|
248
271
|
case 'Identifier': {
|
|
249
272
|
return getCooked(node);
|
|
250
273
|
}
|
|
274
|
+
|
|
251
275
|
case 'IdentifierPath': {
|
|
252
|
-
return node.properties.segments.map((segment) => reifyExpression(segment));
|
|
276
|
+
return node.properties.segments.map((segment) => reifyExpression(segment.node));
|
|
253
277
|
}
|
|
254
278
|
|
|
255
279
|
case 'OpenNodeTag': {
|
|
256
280
|
let { flags, language, type, attributes } = node.properties;
|
|
257
281
|
|
|
258
|
-
flags =
|
|
259
|
-
language = reifyLanguage(language);
|
|
260
|
-
type = reifyExpression(type);
|
|
261
|
-
attributes =
|
|
282
|
+
flags = reifyNodeFlags(flags.node);
|
|
283
|
+
language = reifyLanguage(language?.node);
|
|
284
|
+
type = reifyExpression(type?.node);
|
|
285
|
+
attributes = reifyExpression(attributes?.node);
|
|
262
286
|
|
|
263
287
|
return {
|
|
264
288
|
type: OpenNodeTag,
|
|
@@ -267,50 +291,27 @@ export const reifyExpression = (node) => {
|
|
|
267
291
|
}
|
|
268
292
|
|
|
269
293
|
case 'CloseNodeTag': {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
language = reifyLanguage(language);
|
|
273
|
-
type = reifyExpression(type);
|
|
274
|
-
|
|
275
|
-
return { type: CloseNodeTag, value: { language, type } };
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
case 'OpenFragmentTag': {
|
|
279
|
-
let { flags } = node.properties;
|
|
280
|
-
|
|
281
|
-
flags = reifyFlags(flags);
|
|
282
|
-
|
|
283
|
-
return {
|
|
284
|
-
type: OpenFragmentTag,
|
|
285
|
-
value: { flags },
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
case 'CloseFragmentTag': {
|
|
290
|
-
return { type: CloseFragmentTag, value: undefined };
|
|
294
|
+
return { type: CloseNodeTag, value: undefined };
|
|
291
295
|
}
|
|
292
296
|
|
|
293
297
|
case 'Integer': {
|
|
294
298
|
let { digits } = node.properties;
|
|
295
|
-
return parseInt(digits.map((digit) => getCooked(digit)).join(''), 10);
|
|
299
|
+
return parseInt(digits.map((digit) => getCooked(digit.node)).join(''), 10);
|
|
296
300
|
}
|
|
297
301
|
|
|
298
302
|
case 'Infinity': {
|
|
299
|
-
return node.properties.sign === '-' ? -Infinity : Infinity;
|
|
303
|
+
return getCooked(node.properties.sign.node) === '-' ? -Infinity : Infinity;
|
|
300
304
|
}
|
|
301
305
|
|
|
302
306
|
case 'Punctuator': {
|
|
303
307
|
return getCooked(node);
|
|
304
308
|
}
|
|
305
309
|
|
|
306
|
-
case 'String':
|
|
307
|
-
return node.properties.content ? getCooked(node.properties.content) : '';
|
|
308
|
-
|
|
309
310
|
case 'GapTag':
|
|
310
311
|
return { type: GapTag, value: undefined };
|
|
311
312
|
|
|
312
|
-
case '
|
|
313
|
-
return { type:
|
|
313
|
+
case 'ArrayInitializerTag':
|
|
314
|
+
return { type: ArrayInitializerTag, value: undefined };
|
|
314
315
|
|
|
315
316
|
case 'NullTag':
|
|
316
317
|
return { type: NullTag, value: undefined };
|
|
@@ -326,6 +327,7 @@ export const reifyExpression = (node) => {
|
|
|
326
327
|
if (
|
|
327
328
|
![
|
|
328
329
|
'https://bablr.org/languages/core/en/bablr-vm-instruction',
|
|
330
|
+
'https://bablr.org/languages/core/en/cstml-json',
|
|
329
331
|
'https://bablr.org/languages/core/en/cstml',
|
|
330
332
|
'https://bablr.org/languages/core/en/spamex',
|
|
331
333
|
].includes(node.language)
|
|
@@ -333,44 +335,112 @@ export const reifyExpression = (node) => {
|
|
|
333
335
|
return node;
|
|
334
336
|
}
|
|
335
337
|
|
|
336
|
-
switch (node.type) {
|
|
337
|
-
case '
|
|
338
|
-
|
|
338
|
+
switch (printType(node.type)) {
|
|
339
|
+
case 'String':
|
|
340
|
+
return node.properties.content.node ? getCooked(node.properties.content.node) : '';
|
|
341
|
+
|
|
342
|
+
case 'SpamexString': {
|
|
343
|
+
return buildEmbeddedMatcher(node.properties.content.node);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
case 'RegexString': {
|
|
347
|
+
return buildEmbeddedRegex(node.properties.content.node);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
case 'OpenNodeMatcher': {
|
|
351
|
+
let { flags, language, type, attributes, intrinsicValue } = node.properties;
|
|
339
352
|
|
|
340
|
-
flags =
|
|
341
|
-
language = reifyLanguage(language);
|
|
342
|
-
type =
|
|
343
|
-
|
|
344
|
-
|
|
353
|
+
flags = (flags && reifyNodeFlags(flags.node)) || {};
|
|
354
|
+
language = language && reifyLanguage(language.node);
|
|
355
|
+
type =
|
|
356
|
+
type.node.type === Symbol.for('String')
|
|
357
|
+
? getCooked(type.node.properties.content.node)
|
|
358
|
+
: getCooked(type.node);
|
|
359
|
+
attributes = attributes ? reifyExpression(attributes.node) : {};
|
|
360
|
+
intrinsicValue = intrinsicValue && reifyExpression(intrinsicValue.node);
|
|
345
361
|
|
|
346
362
|
return { flags, language, type, intrinsicValue, attributes };
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
case 'FragmentMatcher': {
|
|
366
|
+
let { flags } = node.properties;
|
|
367
|
+
|
|
368
|
+
flags = (flags && reifyNodeFlags(flags.node)) || {};
|
|
369
|
+
|
|
370
|
+
return {
|
|
371
|
+
flags,
|
|
372
|
+
language: null,
|
|
373
|
+
type: Symbol.for('@bablr/fragment'),
|
|
374
|
+
intrinsicValue: null,
|
|
375
|
+
attributes: null,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
case 'BasicNodeMatcher': {
|
|
380
|
+
let { open } = node.properties;
|
|
381
|
+
|
|
382
|
+
return reifyExpression(open.node);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
case 'PropertyMatcher': {
|
|
386
|
+
let { refMatcher, nodeMatcher } = node.properties;
|
|
387
|
+
|
|
388
|
+
refMatcher = refMatcher ? reifyExpression(refMatcher.node) : null;
|
|
389
|
+
nodeMatcher = reifyExpression(nodeMatcher.node);
|
|
390
|
+
|
|
391
|
+
return { refMatcher, nodeMatcher };
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
case 'ReferenceMatcher': {
|
|
395
|
+
let { name, openIndexToken, flags } = node.properties;
|
|
396
|
+
|
|
397
|
+
name =
|
|
398
|
+
name &&
|
|
399
|
+
(name.node.type === Symbol.for('Identifier')
|
|
400
|
+
? reifyExpression(name.node)
|
|
401
|
+
: getCooked(name.node));
|
|
402
|
+
let isArray = !isNull(openIndexToken?.node);
|
|
403
|
+
flags = (flags && reifyReferenceFlags(flags?.node)) || referenceFlags;
|
|
404
|
+
|
|
405
|
+
return { name, isArray, flags };
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
case 'GapNodeMatcher':
|
|
409
|
+
return buildStubNode(buildGapTag());
|
|
410
|
+
|
|
411
|
+
case 'NullNodeMatcher':
|
|
412
|
+
return buildStubNode(buildNullTag());
|
|
413
|
+
|
|
414
|
+
case 'ArrayNodeMatcher':
|
|
415
|
+
return [];
|
|
347
416
|
|
|
348
417
|
case 'Call': {
|
|
349
418
|
const { verb, arguments: args } = node.properties;
|
|
350
|
-
|
|
419
|
+
|
|
420
|
+
const args_ = [...btree.traverse(args)].map((el) => reifyExpression(el.node));
|
|
421
|
+
|
|
422
|
+
return { verb: reifyExpression(verb.node), arguments: args_ };
|
|
351
423
|
}
|
|
352
424
|
|
|
353
425
|
case 'Object': {
|
|
354
426
|
const { properties } = node.properties;
|
|
355
427
|
|
|
356
428
|
return Object.fromEntries(
|
|
357
|
-
[...btree.traverse(properties)].map((
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
429
|
+
[...btree.traverse(properties)].map((property) => {
|
|
430
|
+
const {
|
|
431
|
+
node: {
|
|
432
|
+
properties: { key, value },
|
|
433
|
+
},
|
|
434
|
+
} = property;
|
|
435
|
+
return [getCooked(key.node), reifyExpression(value.node)];
|
|
436
|
+
}),
|
|
361
437
|
);
|
|
362
438
|
}
|
|
363
439
|
|
|
364
|
-
case 'Tuple': {
|
|
365
|
-
const { values = [] } = node.properties;
|
|
366
|
-
|
|
367
|
-
return [...btree.traverse(values)].map((el) => reifyExpression(el));
|
|
368
|
-
}
|
|
369
|
-
|
|
370
440
|
case 'Array': {
|
|
371
441
|
const { elements = [] } = node.properties;
|
|
372
442
|
|
|
373
|
-
return [...btree.traverse(elements)].map((el) => reifyExpression(el));
|
|
443
|
+
return [...btree.traverse(elements)].map((el) => reifyExpression(el.node));
|
|
374
444
|
}
|
|
375
445
|
|
|
376
446
|
case 'LiteralTag':
|
|
@@ -379,7 +449,7 @@ export const reifyExpression = (node) => {
|
|
|
379
449
|
|
|
380
450
|
case 'Boolean': {
|
|
381
451
|
// prettier-ignore
|
|
382
|
-
switch (getCooked(node.properties.sigilToken)) {
|
|
452
|
+
switch (getCooked(node.properties.sigilToken.node)) {
|
|
383
453
|
case 'true': return true;
|
|
384
454
|
case 'false': return false;
|
|
385
455
|
default: throw new Error();
|
|
@@ -395,52 +465,56 @@ export const reifyExpression = (node) => {
|
|
|
395
465
|
};
|
|
396
466
|
|
|
397
467
|
export const reifyExpressionShallow = (node) => {
|
|
398
|
-
if (!node || node
|
|
468
|
+
if (!node || isNullNode(node)) return null;
|
|
399
469
|
|
|
400
470
|
if (
|
|
401
471
|
![
|
|
402
472
|
'https://bablr.org/languages/core/en/bablr-vm-instruction',
|
|
403
473
|
'https://bablr.org/languages/core/en/cstml',
|
|
474
|
+
'https://bablr.org/languages/core/en/cstml-json',
|
|
475
|
+
'https://bablr.org/languages/core/en/spamex',
|
|
404
476
|
].includes(node.language)
|
|
405
477
|
) {
|
|
406
478
|
return node;
|
|
407
479
|
}
|
|
408
480
|
|
|
409
|
-
switch (node.type) {
|
|
481
|
+
switch (printType(node.type)) {
|
|
482
|
+
case 'String':
|
|
483
|
+
case 'SpamexString':
|
|
484
|
+
case 'RegexString': {
|
|
485
|
+
return reifyExpression(node);
|
|
486
|
+
}
|
|
487
|
+
|
|
410
488
|
case 'Object': {
|
|
411
489
|
const { properties } = node.properties;
|
|
412
490
|
|
|
413
491
|
return Object.fromEntries(
|
|
414
|
-
[...btree.traverse(properties)].map(
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
492
|
+
[...btree.traverse(properties)].map(
|
|
493
|
+
({
|
|
494
|
+
node: {
|
|
495
|
+
properties: { key, value },
|
|
496
|
+
},
|
|
497
|
+
}) => [getCooked(key.node), value.node],
|
|
498
|
+
),
|
|
418
499
|
);
|
|
419
500
|
}
|
|
420
501
|
|
|
421
502
|
case 'Array':
|
|
422
|
-
return [...btree.traverse(node.properties.elements)];
|
|
503
|
+
return [...btree.traverse(node.properties.elements)].map((prop) => prop.node);
|
|
423
504
|
|
|
424
|
-
case '
|
|
425
|
-
|
|
505
|
+
case 'Boolean': {
|
|
506
|
+
// prettier-ignore
|
|
507
|
+
switch (getCooked(node.properties.sigilToken.node)) {
|
|
508
|
+
case 'true': return true;
|
|
509
|
+
case 'false': return false;
|
|
510
|
+
default: throw new Error();
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
case 'Null':
|
|
515
|
+
return null;
|
|
426
516
|
|
|
427
517
|
default:
|
|
428
518
|
return reifyExpression(node);
|
|
429
519
|
}
|
|
430
520
|
};
|
|
431
|
-
|
|
432
|
-
export const reifyAttributes = (attributes) => {
|
|
433
|
-
if (attributes == null) return {};
|
|
434
|
-
|
|
435
|
-
return Object.fromEntries(
|
|
436
|
-
[...btree.traverse(attributes)].map((attr) => {
|
|
437
|
-
if (attr.type === 'MappingAttribute') {
|
|
438
|
-
return [reifyExpression(attr.properties.key), reifyExpression(attr.properties.value)];
|
|
439
|
-
} else if (attr.type === 'BooleanAttribute') {
|
|
440
|
-
return [reifyExpression(attr.properties.key), isNull(attr.properties.negateToken)];
|
|
441
|
-
} else {
|
|
442
|
-
throw new Error();
|
|
443
|
-
}
|
|
444
|
-
}),
|
|
445
|
-
);
|
|
446
|
-
};
|
package/lib/iterable.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function* concat(...iterables) {
|
|
2
|
+
for (const iterable of iterables) yield* iterable;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export const reduce = (reducer, values, initial) => {
|
|
6
|
+
let acc = initial;
|
|
7
|
+
|
|
8
|
+
for (const value of values) {
|
|
9
|
+
acc = reducer(acc, value);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return acc;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function* takeWhile(fn, iterable) {
|
|
16
|
+
for (const value of iterable) {
|
|
17
|
+
if (fn(value)) {
|
|
18
|
+
yield value;
|
|
19
|
+
} else {
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function* map(fn, iterable) {
|
|
26
|
+
for (const value of iterable) {
|
|
27
|
+
yield fn(value);
|
|
28
|
+
}
|
|
29
|
+
}
|
package/lib/languages.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const Spamex = 'https://bablr.org/languages/core/en/spamex';
|
|
2
2
|
export const CSTML = 'https://bablr.org/languages/core/en/cstml';
|
|
3
|
+
export const JSON = 'https://bablr.org/languages/core/en/cstml-json';
|
|
3
4
|
export const Regex = 'https://bablr.org/languages/core/en/bablr-regex-pattern';
|
|
4
5
|
export const Instruction = 'https://bablr.org/languages/core/en/bablr-vm-instruction';
|
|
5
|
-
export const Comment = 'https://bablr.org/languages/core/en/c-comments';
|
|
6
6
|
export const Space = 'https://bablr.org/languages/core/en/space-tab-newline';
|