@bablr/agast-vm-helpers 0.7.1 → 0.9.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 +10 -12
- package/lib/deembed.js +6 -13
- package/lib/embed.js +1 -1
- package/lib/index.js +239 -326
- package/lib/print.js +6 -13
- package/lib/stream.js +5 -18
- package/lib/symbols.js +6 -5
- package/package.json +3 -3
package/lib/builders.js
CHANGED
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EmbeddedNode,
|
|
3
|
-
EmbeddedMatcher,
|
|
4
|
-
EmbeddedRegex,
|
|
5
|
-
EmbeddedTag,
|
|
6
|
-
EmbeddedObject,
|
|
7
|
-
EmbeddedInstruction,
|
|
8
|
-
} from './symbols.js';
|
|
1
|
+
import { Node, Matcher, Regex, Tag, EmbeddedObject, Instruction } from './symbols.js';
|
|
9
2
|
|
|
10
3
|
const isObject = (val) => val !== null && typeof val === 'object';
|
|
11
4
|
|
|
@@ -20,24 +13,29 @@ export const buildEmbeddedObject = (obj) => {
|
|
|
20
13
|
return freeze({ type: EmbeddedObject, value: freeze(obj) });
|
|
21
14
|
};
|
|
22
15
|
|
|
16
|
+
export const buildEmbeddedNode = (node) => {
|
|
17
|
+
if (!isObject(node)) throw new Error();
|
|
18
|
+
return freeze({ type: Node, value: freeze(node) });
|
|
19
|
+
};
|
|
20
|
+
|
|
23
21
|
export const buildEmbeddedMatcher = (matcher) => {
|
|
24
22
|
if (!isObject(matcher)) throw new Error();
|
|
25
|
-
return freeze({ type:
|
|
23
|
+
return freeze({ type: Matcher, value: matcher });
|
|
26
24
|
};
|
|
27
25
|
|
|
28
26
|
export const buildEmbeddedInstruction = (instr) => {
|
|
29
27
|
if (!isObject(instr)) throw new Error();
|
|
30
|
-
return freeze({ type:
|
|
28
|
+
return freeze({ type: Instruction, value: instr });
|
|
31
29
|
};
|
|
32
30
|
|
|
33
31
|
export const buildEmbeddedRegex = (re) => {
|
|
34
32
|
if (!isObject(re)) throw new Error();
|
|
35
|
-
return freeze({ type:
|
|
33
|
+
return freeze({ type: Regex, value: re });
|
|
36
34
|
};
|
|
37
35
|
|
|
38
36
|
export const buildEmbeddedTag = (tag) => {
|
|
39
37
|
if (!isObject(tag)) throw new Error();
|
|
40
|
-
return freeze({ type:
|
|
38
|
+
return freeze({ type: Tag, value: tag });
|
|
41
39
|
};
|
|
42
40
|
|
|
43
41
|
export const buildEffect = (value) => {
|
package/lib/deembed.js
CHANGED
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EmbeddedNode,
|
|
3
|
-
EmbeddedObject,
|
|
4
|
-
EmbeddedTag,
|
|
5
|
-
EmbeddedMatcher,
|
|
6
|
-
EmbeddedRegex,
|
|
7
|
-
EmbeddedInstruction,
|
|
8
|
-
} from './symbols.js';
|
|
1
|
+
import { Node, EmbeddedObject, Tag, Matcher, Regex, Instruction } from './symbols.js';
|
|
9
2
|
|
|
10
3
|
export const getEmbeddedObject = (expr) => {
|
|
11
4
|
if (!expr) return expr;
|
|
@@ -15,30 +8,30 @@ export const getEmbeddedObject = (expr) => {
|
|
|
15
8
|
|
|
16
9
|
export const getEmbeddedNode = (expr) => {
|
|
17
10
|
if (!expr) return expr;
|
|
18
|
-
if (expr.type !==
|
|
11
|
+
if (expr.type !== Node) throw new Error();
|
|
19
12
|
return expr.value;
|
|
20
13
|
};
|
|
21
14
|
|
|
22
15
|
export const getEmbeddedMatcher = (expr) => {
|
|
23
16
|
if (!expr) return expr;
|
|
24
|
-
if (expr.type !==
|
|
17
|
+
if (expr.type !== Matcher) throw new Error();
|
|
25
18
|
return expr.value;
|
|
26
19
|
};
|
|
27
20
|
|
|
28
21
|
export const getEmbeddedInstruction = (expr) => {
|
|
29
22
|
if (!expr) return expr;
|
|
30
|
-
if (expr.type !==
|
|
23
|
+
if (expr.type !== Instruction) throw new Error();
|
|
31
24
|
return expr.value;
|
|
32
25
|
};
|
|
33
26
|
|
|
34
27
|
export const getEmbeddedRegex = (expr) => {
|
|
35
28
|
if (!expr) return expr;
|
|
36
|
-
if (expr.type !==
|
|
29
|
+
if (expr.type !== Regex) throw new Error();
|
|
37
30
|
return expr.value;
|
|
38
31
|
};
|
|
39
32
|
|
|
40
33
|
export const getEmbeddedTag = (expr) => {
|
|
41
|
-
if (expr.type !==
|
|
34
|
+
if (expr.type !== Tag) throw new Error();
|
|
42
35
|
const tag = expr.value;
|
|
43
36
|
return tag;
|
|
44
37
|
};
|
package/lib/embed.js
CHANGED
package/lib/index.js
CHANGED
|
@@ -2,45 +2,58 @@ import {
|
|
|
2
2
|
sourceTextFor,
|
|
3
3
|
getCooked,
|
|
4
4
|
isNull,
|
|
5
|
-
nodeFlags,
|
|
6
|
-
printType,
|
|
7
|
-
buildGapTag,
|
|
8
5
|
isNullNode,
|
|
9
|
-
buildNullTag,
|
|
10
6
|
buildStubNode,
|
|
11
7
|
isFragmentNode,
|
|
12
8
|
buildReferenceTag,
|
|
9
|
+
getRoot,
|
|
10
|
+
buildChild,
|
|
11
|
+
get,
|
|
12
|
+
list,
|
|
13
|
+
buildBounds,
|
|
13
14
|
} from '@bablr/agast-helpers/tree';
|
|
14
|
-
import * as
|
|
15
|
-
import * as sumtree from '@bablr/agast-helpers/sumtree';
|
|
15
|
+
import * as Tags from '@bablr/agast-helpers/tags';
|
|
16
16
|
import {
|
|
17
|
+
buildGapTag,
|
|
18
|
+
buildNullTag,
|
|
19
|
+
buildOpenNodeTag,
|
|
20
|
+
buildBindingTag,
|
|
21
|
+
buildInitializerTag,
|
|
22
|
+
buildShiftTag,
|
|
17
23
|
buildCloseNodeTag,
|
|
18
24
|
buildLiteralTag,
|
|
19
25
|
buildDoctypeTag,
|
|
20
26
|
referenceFlags,
|
|
27
|
+
buildProperty,
|
|
28
|
+
fragmentFlags,
|
|
29
|
+
buildBinding,
|
|
30
|
+
buildAttributeDefinition,
|
|
31
|
+
buildPropertyWrapper,
|
|
21
32
|
} from '@bablr/agast-helpers/builders';
|
|
33
|
+
import { buildEmbeddedMatcher, buildEmbeddedRegex } from './builders.js';
|
|
22
34
|
import {
|
|
23
|
-
|
|
24
|
-
OpenNodeTag,
|
|
35
|
+
AttributeDefinition,
|
|
25
36
|
CloseNodeTag,
|
|
26
|
-
ShiftTag,
|
|
27
37
|
GapTag,
|
|
28
|
-
NullTag,
|
|
29
38
|
InitializerTag,
|
|
30
39
|
LiteralTag,
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
NullTag,
|
|
41
|
+
OpenNodeTag,
|
|
42
|
+
Property,
|
|
43
|
+
PropertyWrapper,
|
|
44
|
+
} from './symbols.js';
|
|
45
|
+
import { isStubNode } from '@bablr/agast-helpers/path';
|
|
33
46
|
|
|
34
47
|
const { freeze } = Object;
|
|
35
48
|
|
|
36
49
|
export const effectsFor = (verb) => {
|
|
37
50
|
switch (verb) {
|
|
38
51
|
case 'eat':
|
|
39
|
-
case '
|
|
52
|
+
case 'shift':
|
|
40
53
|
return { success: 'eat', failure: 'fail' };
|
|
41
54
|
|
|
42
55
|
case 'eatMatch':
|
|
43
|
-
case '
|
|
56
|
+
case 'shiftMatch':
|
|
44
57
|
return { success: 'eat', failure: 'none' };
|
|
45
58
|
|
|
46
59
|
case 'match':
|
|
@@ -59,112 +72,94 @@ export const shouldBranch = (effects) => {
|
|
|
59
72
|
};
|
|
60
73
|
|
|
61
74
|
export const reifyNodeFlags = (flags) => {
|
|
62
|
-
let
|
|
75
|
+
let tokenToken = get('tokenToken', flags);
|
|
76
|
+
let hasGapToken = get('hasGapToken', flags);
|
|
77
|
+
let fragmentToken = get('fragmentToken', flags);
|
|
78
|
+
let multiFragmentToken = get('multiFragmentToken', flags);
|
|
63
79
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
};
|
|
80
|
+
let token = !!(tokenToken && reifyExpression(tokenToken));
|
|
81
|
+
let hasGap = !!(hasGapToken && reifyExpression(hasGapToken));
|
|
82
|
+
let fragment = !!(fragmentToken && reifyExpression(fragmentToken));
|
|
83
|
+
let cover = !!(fragment && !(multiFragmentToken && reifyExpression(multiFragmentToken)));
|
|
84
|
+
|
|
85
|
+
return { token, hasGap, fragment, cover };
|
|
70
86
|
};
|
|
71
87
|
|
|
72
88
|
export const reifyReferenceFlags = (flags) => {
|
|
73
|
-
let
|
|
89
|
+
let expressionToken = get('expressionToken', flags);
|
|
90
|
+
let hasGapToken = get('hasGapToken', flags);
|
|
74
91
|
|
|
75
92
|
return {
|
|
76
|
-
expression: !!(expressionToken && reifyExpression(expressionToken
|
|
77
|
-
hasGap: !!(hasGapToken && reifyExpression(hasGapToken
|
|
93
|
+
expression: !!(expressionToken && reifyExpression(expressionToken)),
|
|
94
|
+
hasGap: !!(hasGapToken && reifyExpression(hasGapToken)),
|
|
78
95
|
};
|
|
79
96
|
};
|
|
80
97
|
|
|
81
|
-
export const
|
|
82
|
-
|
|
98
|
+
export const buildTags = (node) => {
|
|
99
|
+
let open = get('open', node);
|
|
83
100
|
|
|
84
|
-
|
|
85
|
-
|
|
101
|
+
let children = buildChildren(list('children', node));
|
|
102
|
+
let openTag = reifyExpression(open);
|
|
103
|
+
let closeTag = buildCloseNodeTag();
|
|
86
104
|
|
|
87
|
-
|
|
88
|
-
const built = {};
|
|
89
|
-
for (const property of btree.traverse(properties)) {
|
|
90
|
-
switch (property.node.type) {
|
|
91
|
-
case Symbol.for('Property'): {
|
|
92
|
-
let { reference, value: node } = property.node.properties;
|
|
93
|
-
|
|
94
|
-
reference = reifyExpression(reference.node);
|
|
95
|
-
node = reifyExpression(node.node);
|
|
96
|
-
|
|
97
|
-
if (reference.value.isArray) {
|
|
98
|
-
built[reference.value.name] ||= [];
|
|
99
|
-
built[reference.value.name].push({ reference, node });
|
|
100
|
-
} else {
|
|
101
|
-
built[reference.value.name] = { reference, node };
|
|
102
|
-
}
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
default:
|
|
106
|
-
throw new Error();
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return built;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
export const buildFragmentChildren = (node) => {
|
|
113
|
-
let { open, children = [], close } = node.properties;
|
|
114
|
-
|
|
115
|
-
let built = [];
|
|
105
|
+
let literalValue = reifyExpression(get('literalValue', open));
|
|
116
106
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
built = sumtree.push(built, open);
|
|
121
|
-
|
|
122
|
-
for (const child of sumtree.traverse(children)) {
|
|
123
|
-
if (child.node.type !== Symbol.for('Property')) throw new Error('umimplemented');
|
|
124
|
-
|
|
125
|
-
let { reference } = child.node.properties;
|
|
126
|
-
|
|
127
|
-
reference = reifyExpression(reference.node);
|
|
128
|
-
|
|
129
|
-
built = sumtree.push(built, reference);
|
|
130
|
-
built = sumtree.push(built, buildGapTag());
|
|
107
|
+
if (literalValue) {
|
|
108
|
+
children = Tags.fromValues([buildLiteralTag(literalValue)]);
|
|
131
109
|
}
|
|
132
110
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return built;
|
|
111
|
+
return Tags.fromValues([openTag, children, closeTag]);
|
|
136
112
|
};
|
|
137
113
|
|
|
138
|
-
export const buildChildren = (
|
|
139
|
-
let
|
|
114
|
+
export const buildChildren = (children) => {
|
|
115
|
+
let built = Tags.fromValues([]);
|
|
140
116
|
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
117
|
+
for (const child of children) {
|
|
118
|
+
if ([AttributeDefinition, LiteralTag].includes(child.type)) {
|
|
119
|
+
built = Tags.push(built, reifyExpression(child));
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
144
122
|
|
|
145
|
-
|
|
146
|
-
close = reifyExpression(close?.node);
|
|
123
|
+
if (child.type !== Symbol.for('Property')) throw new Error('umimplemented');
|
|
147
124
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
built = sumtree.push(built, buildLiteralTag(intrinsicValue.node));
|
|
152
|
-
}
|
|
153
|
-
built = sumtree.push(built, buildCloseNodeTag());
|
|
154
|
-
} else {
|
|
155
|
-
built = sumtree.push(built, open);
|
|
156
|
-
for (const child of sumtree.traverse(children)) {
|
|
157
|
-
if (child.node.type !== Symbol.for('Property')) throw new Error('umimplemented');
|
|
125
|
+
let reference = get('reference', child);
|
|
126
|
+
let binding = get('binding', child);
|
|
127
|
+
let value = get('value', child);
|
|
158
128
|
|
|
159
|
-
|
|
129
|
+
let referenceTag = reference ? reifyExpression(reference) : buildReferenceTag('.');
|
|
130
|
+
let bindingTag = binding
|
|
131
|
+
? reifyExpression(binding)
|
|
132
|
+
: buildBindingTag(isStubNode(value) ? null : []);
|
|
160
133
|
|
|
161
|
-
|
|
134
|
+
value = reifyExpression(value);
|
|
162
135
|
|
|
163
|
-
|
|
164
|
-
|
|
136
|
+
if (referenceTag.value.type === '_') {
|
|
137
|
+
for (let child of Tags.traverse(value.tags)) {
|
|
138
|
+
if (![OpenNodeTag, CloseNodeTag].includes(child.type)) built = Tags.push(built, child);
|
|
139
|
+
}
|
|
140
|
+
continue;
|
|
165
141
|
}
|
|
166
142
|
|
|
167
|
-
|
|
143
|
+
if (value.type === NullTag || value.type === GapTag) {
|
|
144
|
+
value = buildStubNode(value);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
built = Tags.push(built, referenceTag);
|
|
148
|
+
if (value.type === InitializerTag) {
|
|
149
|
+
built = Tags.push(built, value);
|
|
150
|
+
} else {
|
|
151
|
+
let property = buildProperty(referenceTag.value, bindingTag.value, value);
|
|
152
|
+
built = Tags.push(
|
|
153
|
+
built,
|
|
154
|
+
buildChild(
|
|
155
|
+
PropertyWrapper,
|
|
156
|
+
buildPropertyWrapper(
|
|
157
|
+
[referenceTag, bindingTag, buildChild(Property, property)],
|
|
158
|
+
property,
|
|
159
|
+
),
|
|
160
|
+
),
|
|
161
|
+
);
|
|
162
|
+
}
|
|
168
163
|
}
|
|
169
164
|
|
|
170
165
|
return built;
|
|
@@ -177,230 +172,213 @@ export const reifyExpression = (node) => {
|
|
|
177
172
|
if (isNullNode(node)) return null;
|
|
178
173
|
|
|
179
174
|
if (isFragmentNode(node)) {
|
|
180
|
-
node = node
|
|
175
|
+
node = getRoot(node);
|
|
181
176
|
}
|
|
182
177
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
doctype = reifyExpression(doctype.node);
|
|
189
|
-
tree = reifyExpression(tree.node);
|
|
190
|
-
|
|
191
|
-
let { attributes } = doctype.value;
|
|
192
|
-
let { properties } = tree;
|
|
193
|
-
|
|
194
|
-
return {
|
|
195
|
-
flags: nodeFlags,
|
|
196
|
-
language: attributes.bablrLanguage,
|
|
197
|
-
type: null,
|
|
198
|
-
children: sumtree.addAt(
|
|
199
|
-
0,
|
|
200
|
-
buildFragmentChildren(node.properties.tree.node),
|
|
201
|
-
buildDoctypeTag(attributes),
|
|
202
|
-
),
|
|
203
|
-
properties,
|
|
204
|
-
attributes,
|
|
205
|
-
};
|
|
206
|
-
}
|
|
178
|
+
switch (node.type?.description || node.type) {
|
|
179
|
+
case 'Document': {
|
|
180
|
+
let doctype = get('doctype', node);
|
|
181
|
+
let tree = get('tree', node);
|
|
207
182
|
|
|
208
|
-
|
|
209
|
-
|
|
183
|
+
doctype = reifyExpression(doctype);
|
|
184
|
+
tree = reifyExpression(tree);
|
|
210
185
|
|
|
211
|
-
|
|
186
|
+
let { attributes } = doctype.value;
|
|
212
187
|
|
|
213
|
-
|
|
188
|
+
return Object.freeze({
|
|
189
|
+
flags: fragmentFlags,
|
|
190
|
+
type: null,
|
|
191
|
+
bounds: tree.bounds,
|
|
192
|
+
tags: tree.tags,
|
|
193
|
+
attributes,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
214
196
|
|
|
215
|
-
|
|
197
|
+
case 'Node': {
|
|
198
|
+
let open = get('open', node);
|
|
216
199
|
|
|
217
|
-
|
|
218
|
-
flags,
|
|
219
|
-
language,
|
|
220
|
-
type,
|
|
221
|
-
children: buildChildren(node),
|
|
222
|
-
properties,
|
|
223
|
-
attributes,
|
|
224
|
-
};
|
|
225
|
-
}
|
|
200
|
+
let openTag = reifyExpression(open);
|
|
226
201
|
|
|
227
|
-
|
|
228
|
-
let { open, children } = node.properties;
|
|
202
|
+
let { flags, type, attributes } = openTag.value;
|
|
229
203
|
|
|
230
|
-
|
|
204
|
+
return Object.freeze({
|
|
205
|
+
flags,
|
|
206
|
+
type,
|
|
207
|
+
bounds: buildBounds(),
|
|
208
|
+
tags: buildTags(node),
|
|
209
|
+
attributes,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
231
212
|
|
|
232
|
-
|
|
213
|
+
case 'DoctypeTag': {
|
|
214
|
+
let version = get('version', node);
|
|
215
|
+
let attributes = get('attributes', node);
|
|
233
216
|
|
|
234
|
-
|
|
217
|
+
return buildDoctypeTag(
|
|
218
|
+
attributes && reifyExpression(attributes),
|
|
219
|
+
parseInt(sourceTextFor(version), 10),
|
|
220
|
+
);
|
|
221
|
+
}
|
|
235
222
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
properties,
|
|
242
|
-
attributes: {},
|
|
243
|
-
};
|
|
244
|
-
}
|
|
223
|
+
case 'ReferenceTag': {
|
|
224
|
+
let type = get('type', node);
|
|
225
|
+
let name = get('name', node);
|
|
226
|
+
let arrayOperatorToken = get('arrayOperatorToken', node);
|
|
227
|
+
let flags = get('flags', node);
|
|
245
228
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
version: parseInt(sourceTextFor(version.node), 10),
|
|
253
|
-
attributes: reifyExpression(attributes.node),
|
|
254
|
-
},
|
|
255
|
-
};
|
|
256
|
-
}
|
|
229
|
+
name = name && reifyExpression(name);
|
|
230
|
+
type = type && reifyExpression(type);
|
|
231
|
+
flags = freeze({
|
|
232
|
+
expression: !!(flags && get('expressionToken', flags)),
|
|
233
|
+
hasGap: !!(flags && get('hasGapToken', flags)),
|
|
234
|
+
});
|
|
257
235
|
|
|
258
|
-
|
|
259
|
-
|
|
236
|
+
return buildReferenceTag(type, name, !isNull(arrayOperatorToken), flags);
|
|
237
|
+
}
|
|
260
238
|
|
|
261
|
-
|
|
262
|
-
|
|
239
|
+
case 'LiteralTag': {
|
|
240
|
+
return buildLiteralTag(getCooked(get(['value', 'content'], node)));
|
|
241
|
+
}
|
|
263
242
|
|
|
264
|
-
|
|
265
|
-
|
|
243
|
+
case 'Identifier': {
|
|
244
|
+
return getCooked(get('content', node));
|
|
245
|
+
}
|
|
266
246
|
|
|
267
|
-
|
|
268
|
-
|
|
247
|
+
case 'IdentifierPath': {
|
|
248
|
+
return [...list('segments', node)].map((segment) => reifyExpression(segment));
|
|
249
|
+
}
|
|
269
250
|
|
|
270
|
-
|
|
271
|
-
|
|
251
|
+
case 'AttributeDefinition': {
|
|
252
|
+
let path = get('path', node);
|
|
253
|
+
let value = get('value', node);
|
|
272
254
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
255
|
+
path = path && reifyExpression(path);
|
|
256
|
+
value = value && reifyExpression(value);
|
|
276
257
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
258
|
+
return buildAttributeDefinition(path, value);
|
|
259
|
+
}
|
|
280
260
|
|
|
281
|
-
|
|
282
|
-
|
|
261
|
+
case 'OpenNodeTag': {
|
|
262
|
+
let flags = get('flags', node);
|
|
263
|
+
let type = get('type', node);
|
|
264
|
+
let attributes = get('attributes', node);
|
|
283
265
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
attributes = reifyExpression(attributes?.node);
|
|
266
|
+
flags = reifyNodeFlags(flags);
|
|
267
|
+
type = reifyExpression(type);
|
|
268
|
+
attributes = reifyExpression(attributes);
|
|
288
269
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
value: { flags, language, type, attributes },
|
|
292
|
-
};
|
|
293
|
-
}
|
|
270
|
+
return buildOpenNodeTag(flags, type, attributes);
|
|
271
|
+
}
|
|
294
272
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
273
|
+
case 'CloseNodeTag': {
|
|
274
|
+
return buildCloseNodeTag();
|
|
275
|
+
}
|
|
298
276
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
277
|
+
case 'Integer': {
|
|
278
|
+
return parseInt([...list('digits', node)].map((digit) => getCooked(digit)).join(''), 10);
|
|
279
|
+
}
|
|
303
280
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
281
|
+
case 'Infinity': {
|
|
282
|
+
return getCooked(get('sign', node)) === '-' ? -Infinity : Infinity;
|
|
283
|
+
}
|
|
307
284
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
285
|
+
case 'Punctuator': {
|
|
286
|
+
return getCooked(node);
|
|
287
|
+
}
|
|
311
288
|
|
|
312
|
-
|
|
313
|
-
|
|
289
|
+
case 'GapTag':
|
|
290
|
+
return buildGapTag();
|
|
314
291
|
|
|
315
|
-
|
|
316
|
-
|
|
292
|
+
case 'InitializerTag':
|
|
293
|
+
return buildInitializerTag();
|
|
317
294
|
|
|
318
|
-
|
|
319
|
-
|
|
295
|
+
case 'BindingTag':
|
|
296
|
+
let languagePath = get('languagePath', node);
|
|
320
297
|
|
|
321
|
-
|
|
322
|
-
return { type: ShiftTag, value: undefined };
|
|
298
|
+
return buildBindingTag(reifyExpression(languagePath));
|
|
323
299
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
}
|
|
300
|
+
case 'NullTag':
|
|
301
|
+
return buildNullTag();
|
|
328
302
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
'https://bablr.org/languages/core/en/bablr-vm-instruction',
|
|
332
|
-
'https://bablr.org/languages/core/en/cstml-json',
|
|
333
|
-
'https://bablr.org/languages/core/en/cstml',
|
|
334
|
-
'https://bablr.org/languages/core/en/spamex',
|
|
335
|
-
].includes(node.language)
|
|
336
|
-
) {
|
|
337
|
-
return node;
|
|
338
|
-
}
|
|
303
|
+
case 'ShiftTag':
|
|
304
|
+
return buildShiftTag();
|
|
339
305
|
|
|
340
|
-
switch (printType(node.type)) {
|
|
341
306
|
case 'String':
|
|
342
|
-
return
|
|
307
|
+
return get('content', node) ? getCooked(get('content', node)) : '';
|
|
343
308
|
|
|
344
309
|
case 'SpamexString': {
|
|
345
|
-
return buildEmbeddedMatcher(
|
|
310
|
+
return buildEmbeddedMatcher(get('content', node));
|
|
346
311
|
}
|
|
347
312
|
|
|
348
313
|
case 'RegexString': {
|
|
349
|
-
return buildEmbeddedRegex(
|
|
314
|
+
return buildEmbeddedRegex(get('content', node));
|
|
350
315
|
}
|
|
351
316
|
|
|
352
317
|
case 'OpenNodeMatcher': {
|
|
353
|
-
let
|
|
318
|
+
let flags = get('flags', node);
|
|
319
|
+
let type = get('type', node);
|
|
320
|
+
let attributes = get('attributes', node);
|
|
321
|
+
let literalValue = get('literalValue', node);
|
|
354
322
|
|
|
355
|
-
flags = (flags && reifyNodeFlags(flags
|
|
356
|
-
language = language && reifyLanguage(language.node);
|
|
323
|
+
flags = (flags && reifyNodeFlags(flags)) || {};
|
|
357
324
|
type =
|
|
358
|
-
type.
|
|
359
|
-
? getCooked(type
|
|
360
|
-
: reifyExpression(type
|
|
361
|
-
attributes = attributes ? reifyExpression(attributes
|
|
362
|
-
|
|
325
|
+
type.type === Symbol.for('String')
|
|
326
|
+
? getCooked(get('content', type))
|
|
327
|
+
: reifyExpression(type);
|
|
328
|
+
attributes = attributes ? reifyExpression(attributes) : {};
|
|
329
|
+
literalValue = literalValue && reifyExpression(literalValue);
|
|
363
330
|
|
|
364
|
-
return { flags,
|
|
331
|
+
return { flags, type, literalValue, attributes };
|
|
365
332
|
}
|
|
366
333
|
|
|
367
334
|
case 'FragmentMatcher': {
|
|
368
|
-
let
|
|
335
|
+
let flags = get('flags', node);
|
|
369
336
|
|
|
370
|
-
flags = (flags && reifyNodeFlags(flags
|
|
337
|
+
flags = (flags && reifyNodeFlags(flags)) || {};
|
|
371
338
|
|
|
372
339
|
return {
|
|
373
340
|
flags,
|
|
374
|
-
language: null,
|
|
375
341
|
type: Symbol.for('@bablr/fragment'),
|
|
376
|
-
|
|
342
|
+
literalValue: null,
|
|
377
343
|
attributes: null,
|
|
378
344
|
};
|
|
379
345
|
}
|
|
380
346
|
|
|
381
347
|
case 'BasicNodeMatcher': {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
return reifyExpression(open.node);
|
|
348
|
+
return reifyExpression(get('open', node));
|
|
385
349
|
}
|
|
386
350
|
|
|
387
351
|
case 'PropertyMatcher': {
|
|
388
|
-
let
|
|
352
|
+
let refMatcher = get('refMatcher', node);
|
|
353
|
+
let bindingMatcher = get('bindingMatcher', node);
|
|
354
|
+
let nodeMatcher = get('nodeMatcher', node);
|
|
389
355
|
|
|
390
|
-
refMatcher = refMatcher ? reifyExpression(refMatcher
|
|
391
|
-
|
|
356
|
+
refMatcher = refMatcher ? reifyExpression(refMatcher) : null;
|
|
357
|
+
bindingMatcher = bindingMatcher ? reifyExpression(bindingMatcher) : null;
|
|
358
|
+
nodeMatcher = reifyExpression(nodeMatcher);
|
|
392
359
|
|
|
393
|
-
return { refMatcher, nodeMatcher };
|
|
360
|
+
return { refMatcher, bindingMatcher, nodeMatcher };
|
|
394
361
|
}
|
|
395
362
|
|
|
396
363
|
case 'ReferenceMatcher': {
|
|
397
|
-
let
|
|
364
|
+
let type = get('type', node);
|
|
365
|
+
let name = get('name', node);
|
|
366
|
+
let isArray = !isNull(get('openIndexToken', node));
|
|
367
|
+
let flags = get('flags', node);
|
|
368
|
+
|
|
369
|
+
type = type && reifyExpression(type);
|
|
370
|
+
name = name && reifyExpression(name);
|
|
371
|
+
flags = (flags && reifyReferenceFlags(flags)) || referenceFlags;
|
|
372
|
+
|
|
373
|
+
return { type, name, isArray, flags };
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
case 'BindingMatcher': {
|
|
377
|
+
let languagePath = get('languagePath', node);
|
|
398
378
|
|
|
399
|
-
|
|
400
|
-
let isArray = !isNull(openIndexToken?.node);
|
|
401
|
-
flags = (flags && reifyReferenceFlags(flags?.node)) || referenceFlags;
|
|
379
|
+
languagePath = languagePath && reifyExpression(languagePath);
|
|
402
380
|
|
|
403
|
-
return {
|
|
381
|
+
return { languagePath };
|
|
404
382
|
}
|
|
405
383
|
|
|
406
384
|
case 'GapNodeMatcher':
|
|
@@ -413,44 +391,34 @@ export const reifyExpression = (node) => {
|
|
|
413
391
|
return [];
|
|
414
392
|
|
|
415
393
|
case 'Call': {
|
|
416
|
-
const
|
|
394
|
+
const verb = get('verb', node);
|
|
417
395
|
|
|
418
|
-
const
|
|
396
|
+
const args = [...list('arguments', node)].map((el) => reifyExpression(el));
|
|
419
397
|
|
|
420
|
-
return { verb: reifyExpression(verb
|
|
398
|
+
return { verb: reifyExpression(verb), arguments: args };
|
|
421
399
|
}
|
|
422
400
|
|
|
423
401
|
case 'Object': {
|
|
424
|
-
const { properties } = node.properties;
|
|
425
|
-
|
|
426
402
|
return Object.fromEntries(
|
|
427
|
-
[...
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
},
|
|
432
|
-
} = property;
|
|
433
|
-
return [getCooked(key.node), reifyExpression(value.node)];
|
|
403
|
+
[...list('properties', node)].map((property) => {
|
|
404
|
+
const key = get('key', property);
|
|
405
|
+
const value = get('value', property);
|
|
406
|
+
return [reifyExpression(key), reifyExpression(value)];
|
|
434
407
|
}),
|
|
435
408
|
);
|
|
436
409
|
}
|
|
437
410
|
|
|
438
411
|
case 'Array': {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
return [...btree.traverse(elements)].map((el) => reifyExpression(el.node));
|
|
412
|
+
return [...list('elements', node)].map((el) => reifyExpression(el));
|
|
442
413
|
}
|
|
443
414
|
|
|
444
415
|
case 'Punctuator':
|
|
445
416
|
case 'Keyword':
|
|
446
417
|
return getCooked(node);
|
|
447
418
|
|
|
448
|
-
case 'Identifier':
|
|
449
|
-
return getCooked(node.properties.content.node);
|
|
450
|
-
|
|
451
419
|
case 'Boolean': {
|
|
452
420
|
// prettier-ignore
|
|
453
|
-
switch (getCooked(
|
|
421
|
+
switch (getCooked(get('sigilToken', node))) {
|
|
454
422
|
case 'true': return true;
|
|
455
423
|
case 'false': return false;
|
|
456
424
|
default: throw new Error();
|
|
@@ -467,61 +435,6 @@ export const reifyExpression = (node) => {
|
|
|
467
435
|
return undefined;
|
|
468
436
|
|
|
469
437
|
default:
|
|
470
|
-
|
|
471
|
-
}
|
|
472
|
-
};
|
|
473
|
-
|
|
474
|
-
export const reifyExpressionShallow = (node) => {
|
|
475
|
-
if (!node || isNullNode(node)) return null;
|
|
476
|
-
|
|
477
|
-
if (
|
|
478
|
-
![
|
|
479
|
-
'https://bablr.org/languages/core/en/bablr-vm-instruction',
|
|
480
|
-
'https://bablr.org/languages/core/en/cstml',
|
|
481
|
-
'https://bablr.org/languages/core/en/cstml-json',
|
|
482
|
-
'https://bablr.org/languages/core/en/spamex',
|
|
483
|
-
].includes(node.language)
|
|
484
|
-
) {
|
|
485
|
-
return node;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
switch (printType(node.type)) {
|
|
489
|
-
case 'String':
|
|
490
|
-
case 'SpamexString':
|
|
491
|
-
case 'RegexString': {
|
|
492
|
-
return reifyExpression(node);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
case 'Object': {
|
|
496
|
-
const { properties } = node.properties;
|
|
497
|
-
|
|
498
|
-
return Object.fromEntries(
|
|
499
|
-
[...btree.traverse(properties)].map(
|
|
500
|
-
({
|
|
501
|
-
node: {
|
|
502
|
-
properties: { key, value },
|
|
503
|
-
},
|
|
504
|
-
}) => [getCooked(key.node), value.node],
|
|
505
|
-
),
|
|
506
|
-
);
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
case 'Array':
|
|
510
|
-
return [...btree.traverse(node.properties.elements)].map((prop) => prop.node);
|
|
511
|
-
|
|
512
|
-
case 'Boolean': {
|
|
513
|
-
// prettier-ignore
|
|
514
|
-
switch (getCooked(node.properties.sigilToken.node)) {
|
|
515
|
-
case 'true': return true;
|
|
516
|
-
case 'false': return false;
|
|
517
|
-
default: throw new Error();
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
case 'Null':
|
|
522
|
-
return null;
|
|
523
|
-
|
|
524
|
-
default:
|
|
525
|
-
return reifyExpression(node);
|
|
438
|
+
return node;
|
|
526
439
|
}
|
|
527
440
|
};
|
package/lib/print.js
CHANGED
|
@@ -3,34 +3,27 @@ import {
|
|
|
3
3
|
printTag,
|
|
4
4
|
printExpression as printExpression_,
|
|
5
5
|
} from '@bablr/agast-helpers/tree';
|
|
6
|
-
import {
|
|
7
|
-
EmbeddedNode,
|
|
8
|
-
EmbeddedTag,
|
|
9
|
-
EmbeddedObject,
|
|
10
|
-
EmbeddedMatcher,
|
|
11
|
-
EmbeddedRegex,
|
|
12
|
-
EmbeddedInstruction,
|
|
13
|
-
} from './symbols.js';
|
|
6
|
+
import { Node, Tag, EmbeddedObject, Matcher, Regex, Instruction } from './symbols.js';
|
|
14
7
|
|
|
15
8
|
export const printEmbedded = (value) => {
|
|
16
9
|
switch (value.type) {
|
|
17
|
-
case
|
|
10
|
+
case Tag:
|
|
18
11
|
return `t\`${printTag(value.value)}\``;
|
|
19
12
|
|
|
20
|
-
case
|
|
13
|
+
case Matcher:
|
|
21
14
|
return `m\`${printSource(value.value)}\``;
|
|
22
15
|
|
|
23
|
-
case
|
|
16
|
+
case Regex:
|
|
24
17
|
return `re\`${printSource(value.value)}\``;
|
|
25
18
|
|
|
26
|
-
case
|
|
19
|
+
case Instruction:
|
|
27
20
|
return `i\`${printCall(value.value)}\``;
|
|
28
21
|
|
|
29
22
|
case EmbeddedObject: {
|
|
30
23
|
return printObject(value.value);
|
|
31
24
|
}
|
|
32
25
|
|
|
33
|
-
case
|
|
26
|
+
case Node: {
|
|
34
27
|
return printSource(value.value);
|
|
35
28
|
}
|
|
36
29
|
|
package/lib/stream.js
CHANGED
|
@@ -7,14 +7,12 @@ import {
|
|
|
7
7
|
NullTag,
|
|
8
8
|
OpenNodeTag,
|
|
9
9
|
ReferenceTag,
|
|
10
|
-
TokenGroup,
|
|
11
10
|
} from './symbols.js';
|
|
12
11
|
import {
|
|
13
12
|
getStreamIterator,
|
|
14
|
-
prettyGroupTags,
|
|
15
|
-
printSelfClosingNodeTag,
|
|
16
13
|
printTag,
|
|
17
14
|
StreamIterable,
|
|
15
|
+
prettyGroupTags,
|
|
18
16
|
} from '@bablr/agast-helpers/stream';
|
|
19
17
|
import { buildWriteEffect } from './builders.js';
|
|
20
18
|
import { getCooked } from '@bablr/agast-helpers/tree';
|
|
@@ -117,12 +115,7 @@ function* __writeCSTMLStrategy(tags) {
|
|
|
117
115
|
continue;
|
|
118
116
|
}
|
|
119
117
|
|
|
120
|
-
|
|
121
|
-
const intrinsicValue = getCooked(tag.value);
|
|
122
|
-
yield buildWriteEffect(printSelfClosingNodeTag(tag.value[0], intrinsicValue));
|
|
123
|
-
} else {
|
|
124
|
-
yield buildWriteEffect(printTag(tag));
|
|
125
|
-
}
|
|
118
|
+
yield buildWriteEffect(printTag(tag));
|
|
126
119
|
|
|
127
120
|
prevTag = tag;
|
|
128
121
|
}
|
|
@@ -182,7 +175,7 @@ function* __writePrettyCSTMLStrategy(tags, options) {
|
|
|
182
175
|
(tag.type === NullTag ||
|
|
183
176
|
tag.type === GapTag ||
|
|
184
177
|
tag.type === InitializerTag ||
|
|
185
|
-
tag.type ===
|
|
178
|
+
(tag.type === OpenNodeTag && tag.value.selfClosing));
|
|
186
179
|
|
|
187
180
|
if (!first && !inline) {
|
|
188
181
|
yield buildWriteEffect('\n');
|
|
@@ -203,20 +196,14 @@ function* __writePrettyCSTMLStrategy(tags, options) {
|
|
|
203
196
|
yield buildWriteEffect(' ');
|
|
204
197
|
}
|
|
205
198
|
|
|
206
|
-
|
|
207
|
-
ref = null;
|
|
208
|
-
const intrinsicValue = tag.value[0].value.flags.token ? getCooked(tag.value) : null;
|
|
209
|
-
yield buildWriteEffect(printSelfClosingNodeTag(tag.value[0], intrinsicValue));
|
|
210
|
-
} else {
|
|
211
|
-
yield buildWriteEffect(printTag(tag));
|
|
212
|
-
}
|
|
199
|
+
yield buildWriteEffect(printTag(tag));
|
|
213
200
|
|
|
214
201
|
if (tag.type === ReferenceTag) {
|
|
215
202
|
inline = true;
|
|
216
203
|
ref = tag;
|
|
217
204
|
}
|
|
218
205
|
|
|
219
|
-
if (tag.type === OpenNodeTag) {
|
|
206
|
+
if (tag.type === OpenNodeTag && !tag.value.literalValue) {
|
|
220
207
|
indentLevel++;
|
|
221
208
|
}
|
|
222
209
|
|
package/lib/symbols.js
CHANGED
|
@@ -3,8 +3,9 @@ export * from '@bablr/agast-helpers/symbols';
|
|
|
3
3
|
export const node = Symbol.for('@bablr/node');
|
|
4
4
|
export const fragment = Symbol.for('@bablr/fragment');
|
|
5
5
|
|
|
6
|
-
export const
|
|
7
|
-
export const
|
|
8
|
-
export const
|
|
9
|
-
export const
|
|
10
|
-
export const
|
|
6
|
+
export const Instruction = Symbol.for('Instruction');
|
|
7
|
+
export const Matcher = Symbol.for('Matcher');
|
|
8
|
+
export const Regex = Symbol.for('Regex');
|
|
9
|
+
export const Tag = Symbol.for('Tag');
|
|
10
|
+
export const Object = Symbol.for('Object');
|
|
11
|
+
export const EmbeddedObject = Object;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bablr/agast-vm-helpers",
|
|
3
3
|
"description": "Helper functions for working with the BABLR VM",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.0",
|
|
5
5
|
"author": "Conrad Buck<conartist6@gmail.com>",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
},
|
|
23
23
|
"sideEffects": false,
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@bablr/agast-helpers": "0.
|
|
25
|
+
"@bablr/agast-helpers": "0.9.0",
|
|
26
26
|
"@bablr/coroutine": "0.1.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@bablr/eslint-config-base": "github:bablr-lang/eslint-config-base#
|
|
29
|
+
"@bablr/eslint-config-base": "github:bablr-lang/eslint-config-base#c97bfa4b3663f8378e9b3e42bb5a41e685406cf9",
|
|
30
30
|
"enhanced-resolve": "^5.12.0",
|
|
31
31
|
"eslint": "^8.32.0",
|
|
32
32
|
"eslint-import-resolver-enhanced-resolve": "^1.0.5",
|