@bablr/boot 0.2.3 → 0.3.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 +0 -14
- package/lib/index.js +6 -2
- package/lib/languages/cstml.js +16 -44
- package/lib/languages/instruction.js +5 -5
- package/lib/languages/regex.js +7 -5
- package/lib/languages/spamex.js +20 -14
- package/lib/miniparser.js +5 -3
- package/lib/path.js +1 -1
- package/lib/print.js +5 -24
- package/lib/utils.js +4 -4
- package/package.json +2 -2
- package/shorthand.macro.js +13 -13
package/lib/builders.js
CHANGED
|
@@ -70,18 +70,10 @@ const buildNodeOpenTag = (flags, type, attributes = {}) => {
|
|
|
70
70
|
return freeze({ type: 'OpenNodeTag', value: freeze({ flags, type, attributes }) });
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
-
const buildFragmentOpenTag = (flags = {}, language) => {
|
|
74
|
-
return freeze({ type: 'OpenFragmentTag', value: freeze({ flags: freeze(flags), language }) });
|
|
75
|
-
};
|
|
76
|
-
|
|
77
73
|
const buildNodeCloseTag = (type) => {
|
|
78
74
|
return freeze({ type: 'CloseNodeTag', value: freeze({ type }) });
|
|
79
75
|
};
|
|
80
76
|
|
|
81
|
-
const buildFragmentCloseTag = () => {
|
|
82
|
-
return freeze({ type: 'CloseFragmentTag', value: freeze({}) });
|
|
83
|
-
};
|
|
84
|
-
|
|
85
77
|
const buildLiteral = (value) => {
|
|
86
78
|
return freeze({ type: 'Literal', value });
|
|
87
79
|
};
|
|
@@ -374,9 +366,7 @@ const lit = (str) => buildLiteral(stripArray(str));
|
|
|
374
366
|
|
|
375
367
|
const gap = buildGap;
|
|
376
368
|
const nodeOpen = buildNodeOpenTag;
|
|
377
|
-
const fragOpen = buildFragmentOpenTag;
|
|
378
369
|
const nodeClose = buildNodeCloseTag;
|
|
379
|
-
const fragClose = buildFragmentCloseTag;
|
|
380
370
|
const node = buildNode;
|
|
381
371
|
const s_node = buildSyntacticNode;
|
|
382
372
|
const e_node = buildEscapeNode;
|
|
@@ -398,9 +388,7 @@ module.exports = {
|
|
|
398
388
|
buildReference,
|
|
399
389
|
buildGap,
|
|
400
390
|
buildNodeOpenTag,
|
|
401
|
-
buildFragmentOpenTag,
|
|
402
391
|
buildNodeCloseTag,
|
|
403
|
-
buildFragmentCloseTag,
|
|
404
392
|
buildLiteral,
|
|
405
393
|
buildNode,
|
|
406
394
|
buildSyntacticNode,
|
|
@@ -411,9 +399,7 @@ module.exports = {
|
|
|
411
399
|
lit,
|
|
412
400
|
gap,
|
|
413
401
|
nodeOpen,
|
|
414
|
-
fragOpen,
|
|
415
402
|
nodeClose,
|
|
416
|
-
fragClose,
|
|
417
403
|
node,
|
|
418
404
|
s_node,
|
|
419
405
|
e_node,
|
package/lib/index.js
CHANGED
|
@@ -66,6 +66,10 @@ const parse = (language, type, sourceText) => {
|
|
|
66
66
|
const getAgASTValue = (language, miniNode) => {
|
|
67
67
|
if (!miniNode) return miniNode;
|
|
68
68
|
|
|
69
|
+
if (isArray(miniNode)) {
|
|
70
|
+
return miniNode.map((node) => getAgASTValue(node));
|
|
71
|
+
}
|
|
72
|
+
|
|
69
73
|
const { language: languageName, type, attributes } = miniNode;
|
|
70
74
|
const flags = { escape: false, trivia: false, token: false, intrinsic: false };
|
|
71
75
|
const properties = {};
|
|
@@ -106,7 +110,7 @@ const getAgASTValue = (language, miniNode) => {
|
|
|
106
110
|
type: 'Embedded',
|
|
107
111
|
value: {
|
|
108
112
|
flags: { escape: false, token: true, trivia: true, intrinsic: false },
|
|
109
|
-
language: 'https://bablr.org/languages/core/space-tab-newline',
|
|
113
|
+
language: 'https://bablr.org/languages/core/en/space-tab-newline',
|
|
110
114
|
type: 'Space',
|
|
111
115
|
children: [buildLiteral(child.value)],
|
|
112
116
|
properties: {},
|
|
@@ -138,7 +142,7 @@ const getAgASTValue = (language, miniNode) => {
|
|
|
138
142
|
|
|
139
143
|
const str = buildTag(cstml, 'String');
|
|
140
144
|
const num = buildTag(cstml, 'Integer');
|
|
141
|
-
const cst = buildTag(cstml, '
|
|
145
|
+
const cst = buildTag(cstml, 'Node');
|
|
142
146
|
const re = buildTag(regex, 'Pattern');
|
|
143
147
|
const i = buildTag(instruction, 'Call');
|
|
144
148
|
|
package/lib/languages/cstml.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const objectEntries = require('iter-tools
|
|
1
|
+
const objectEntries = require('iter-tools/methods/object-entries');
|
|
2
2
|
|
|
3
3
|
const { buildCovers } = require('../utils.js');
|
|
4
4
|
const sym = require('../symbols.js');
|
|
@@ -11,7 +11,7 @@ const LIT = 'Literal';
|
|
|
11
11
|
|
|
12
12
|
const name = 'CSTML';
|
|
13
13
|
|
|
14
|
-
const canonicalURL = 'https://bablr.org/languages/core/cstml';
|
|
14
|
+
const canonicalURL = 'https://bablr.org/languages/core/en/cstml';
|
|
15
15
|
|
|
16
16
|
const dependencies = {};
|
|
17
17
|
|
|
@@ -68,10 +68,8 @@ const covers = buildCovers({
|
|
|
68
68
|
'Gap',
|
|
69
69
|
'Node',
|
|
70
70
|
'IdentifierPath',
|
|
71
|
-
'OpenFragmentTag',
|
|
72
71
|
'OpenNodeTag',
|
|
73
72
|
'CloseNodeTag',
|
|
74
|
-
'CloseFragmentTag',
|
|
75
73
|
'Terminal',
|
|
76
74
|
'Number',
|
|
77
75
|
'Digit',
|
|
@@ -80,7 +78,7 @@ const covers = buildCovers({
|
|
|
80
78
|
'UnsignedInteger',
|
|
81
79
|
'Flags',
|
|
82
80
|
],
|
|
83
|
-
[sym.fragment]: ['Attributes'
|
|
81
|
+
[sym.fragment]: ['Attributes'],
|
|
84
82
|
Attribute: ['MappingAttribute', 'BooleanAttribute'],
|
|
85
83
|
AttributeValue: ['String', 'Number'],
|
|
86
84
|
TagType: ['Identifier', 'GlobalIdentifier'],
|
|
@@ -91,22 +89,10 @@ const covers = buildCovers({
|
|
|
91
89
|
});
|
|
92
90
|
|
|
93
91
|
const grammar = class CSTMLMiniparserGrammar {
|
|
94
|
-
Fragment(p) {
|
|
95
|
-
p.eatMatchTrivia(_);
|
|
96
|
-
p.eatProduction('OpenFragmentTag', { path: 'open' });
|
|
97
|
-
p.eatMatchTrivia(_);
|
|
98
|
-
while (p.match(/<[^/]/y) || p.atExpression) {
|
|
99
|
-
p.eatProduction('Node', { path: 'root' });
|
|
100
|
-
p.eatMatchTrivia(_);
|
|
101
|
-
}
|
|
102
|
-
p.eatProduction('CloseFragmentTag', { path: 'close' });
|
|
103
|
-
p.eatMatchTrivia(_);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
92
|
// @Node
|
|
107
93
|
Document(p) {
|
|
108
94
|
p.eatProduction('DoctypeTag', { path: 'doctype' });
|
|
109
|
-
p.eatProduction('
|
|
95
|
+
p.eatProduction('Node', { path: 'tree' });
|
|
110
96
|
}
|
|
111
97
|
|
|
112
98
|
// @Node
|
|
@@ -118,7 +104,7 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
118
104
|
|
|
119
105
|
let sp = p.eatMatchTrivia(_);
|
|
120
106
|
|
|
121
|
-
if ((sp && p.match(
|
|
107
|
+
if ((sp && p.match(/[a-zA-Z]+/y)) || p.atExpression) {
|
|
122
108
|
p.eatProduction('Attributes');
|
|
123
109
|
sp = p.eatMatchTrivia(_);
|
|
124
110
|
}
|
|
@@ -138,8 +124,6 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
138
124
|
|
|
139
125
|
// @Node
|
|
140
126
|
Node(p) {
|
|
141
|
-
if (p.match('<>')) throw new Error('Fragment is not a node');
|
|
142
|
-
|
|
143
127
|
let open = p.eatProduction('OpenNodeTag', { path: 'open' });
|
|
144
128
|
|
|
145
129
|
p.eatMatchTrivia(_);
|
|
@@ -169,7 +153,7 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
169
153
|
} else {
|
|
170
154
|
if (p.match(/<\*?#/y)) {
|
|
171
155
|
p.eatProduction('Node');
|
|
172
|
-
} else if (p.match(
|
|
156
|
+
} else if (p.match(/[a-zA-Z]/y)) {
|
|
173
157
|
p.eatProduction('Property');
|
|
174
158
|
} else if (p.match(/['"]/y)) {
|
|
175
159
|
p.eatProduction('Literal');
|
|
@@ -181,8 +165,6 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
181
165
|
Property(p) {
|
|
182
166
|
p.eatProduction('Reference', { path: 'reference' });
|
|
183
167
|
p.eatMatchTrivia(_);
|
|
184
|
-
p.eat(':', PN, { path: 'mapToken' });
|
|
185
|
-
p.eatMatchTrivia(_);
|
|
186
168
|
p.eatProduction('PropertyValue', { path: 'value' });
|
|
187
169
|
}
|
|
188
170
|
|
|
@@ -196,12 +178,6 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
196
178
|
}
|
|
197
179
|
}
|
|
198
180
|
|
|
199
|
-
// @Node
|
|
200
|
-
OpenFragmentTag(p) {
|
|
201
|
-
p.eat('<', PN, { path: 'openToken', startSpan: 'Tag', balanced: '>' });
|
|
202
|
-
p.eat('>', PN, { path: 'closeToken', endSpan: 'Tag', balancer: true });
|
|
203
|
-
}
|
|
204
|
-
|
|
205
181
|
// @Node
|
|
206
182
|
Flags(p) {
|
|
207
183
|
let tr = p.eatMatch('#', PN, { path: 'triviaToken' });
|
|
@@ -233,7 +209,7 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
233
209
|
sp = p.eatMatchTrivia(_);
|
|
234
210
|
}
|
|
235
211
|
|
|
236
|
-
if ((sp && p.match(
|
|
212
|
+
if ((sp && p.match(/[a-zA-Z]+/y)) || p.atExpression) {
|
|
237
213
|
p.eatProduction('Attributes');
|
|
238
214
|
sp = p.eatMatchTrivia(_);
|
|
239
215
|
}
|
|
@@ -251,22 +227,16 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
251
227
|
p.eat('>', PN, { path: 'closeToken', endSpan: 'Tag', balancer: true });
|
|
252
228
|
}
|
|
253
229
|
|
|
254
|
-
// @Node
|
|
255
|
-
CloseFragmentTag(p) {
|
|
256
|
-
p.eat('</', PN, { path: 'openToken', startSpan: 'Tag', balanced: '>' });
|
|
257
|
-
p.eat('>', PN, { path: 'closeToken', endSpan: 'Tag', balancer: true });
|
|
258
|
-
}
|
|
259
|
-
|
|
260
230
|
// @Fragment
|
|
261
231
|
Attributes(p) {
|
|
262
232
|
let sp = true;
|
|
263
|
-
while (sp && (p.match(
|
|
233
|
+
while (sp && (p.match(/[a-zA-Z]+/y) || p.atExpression)) {
|
|
264
234
|
if (p.atExpression) {
|
|
265
235
|
p.eatProduction('Attributes'); // ??
|
|
266
236
|
} else {
|
|
267
237
|
p.eatProduction('Attribute', { path: 'attributes[]' });
|
|
268
238
|
}
|
|
269
|
-
if (p.match(/\s
|
|
239
|
+
if (p.match(/\s+[a-zA-Z]/y) || (p.match(/\s+$/y) && !p.quasisDone)) {
|
|
270
240
|
sp = p.eatMatchTrivia(_);
|
|
271
241
|
} else {
|
|
272
242
|
sp = false;
|
|
@@ -276,7 +246,7 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
276
246
|
|
|
277
247
|
// @Cover
|
|
278
248
|
Attribute(p) {
|
|
279
|
-
if (p.match(
|
|
249
|
+
if (p.match(/[a-zA-Z][[a-zA-Z]-_]*\s*=/y)) {
|
|
280
250
|
p.eatProduction('MappingAttribute');
|
|
281
251
|
} else {
|
|
282
252
|
p.eatProduction('BooleanAttribute');
|
|
@@ -286,12 +256,12 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
286
256
|
// @Node
|
|
287
257
|
BooleanAttribute(p) {
|
|
288
258
|
p.eat('!', KW, { path: 'negateToken' });
|
|
289
|
-
p.eat(
|
|
259
|
+
p.eat(/[a-zA-Z]+/y, ID, { path: 'key' });
|
|
290
260
|
}
|
|
291
261
|
|
|
292
262
|
// @Node
|
|
293
263
|
MappingAttribute(p) {
|
|
294
|
-
p.eat(
|
|
264
|
+
p.eat(/[a-zA-Z]+/y, LIT, { path: 'key' });
|
|
295
265
|
p.eatMatchTrivia(_);
|
|
296
266
|
p.eat('=', PN, { path: 'mapToken' });
|
|
297
267
|
p.eatMatchTrivia(_);
|
|
@@ -308,7 +278,7 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
308
278
|
}
|
|
309
279
|
|
|
310
280
|
TagType(p) {
|
|
311
|
-
if (p.match(/[
|
|
281
|
+
if (p.match(/[[a-zA-Z].]+:/y)) {
|
|
312
282
|
p.eatProduction('LanguageReference', { path: 'language' });
|
|
313
283
|
p.eat(':', PN, { path: 'namespaceSeparatorToken' });
|
|
314
284
|
p.eatProduction('Identifier', { path: 'type' });
|
|
@@ -335,7 +305,7 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
335
305
|
|
|
336
306
|
// @Node
|
|
337
307
|
Identifier(p) {
|
|
338
|
-
p.eatLiteral(
|
|
308
|
+
p.eatLiteral(/[a-zA-Z][[a-zA-Z]-_]*/y);
|
|
339
309
|
}
|
|
340
310
|
|
|
341
311
|
// @Cover
|
|
@@ -352,6 +322,8 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
352
322
|
p.eatProduction('Identifier', { path: 'name' });
|
|
353
323
|
p.eatMatchTrivia(_);
|
|
354
324
|
p.eatMatch('[]', PN, { path: 'arrayToken' });
|
|
325
|
+
p.eatMatchTrivia(_);
|
|
326
|
+
p.eat(':', PN, { path: 'mapToken' });
|
|
355
327
|
}
|
|
356
328
|
|
|
357
329
|
// @Cover
|
|
@@ -12,7 +12,7 @@ const LIT = 'Literal';
|
|
|
12
12
|
|
|
13
13
|
const name = 'Instruction';
|
|
14
14
|
|
|
15
|
-
const canonicalURL = 'https://bablr.org/languages/core/bablr-vm-instruction';
|
|
15
|
+
const canonicalURL = 'https://bablr.org/languages/core/en/bablr-vm-instruction';
|
|
16
16
|
|
|
17
17
|
const dependencies = { Spamex, CSTML, Regex };
|
|
18
18
|
|
|
@@ -35,7 +35,7 @@ const covers = buildCovers({
|
|
|
35
35
|
const grammar = class InstructionMiniparserGrammar {
|
|
36
36
|
// @Node
|
|
37
37
|
Call(p) {
|
|
38
|
-
p.eat(
|
|
38
|
+
p.eat(/[a-zA-Z]+/y, ID, { path: 'verb' });
|
|
39
39
|
p.eatMatchTrivia(_);
|
|
40
40
|
p.eatProduction('Tuple', { path: 'arguments' });
|
|
41
41
|
}
|
|
@@ -58,8 +58,8 @@ const grammar = class InstructionMiniparserGrammar {
|
|
|
58
58
|
p.eatProduction('Boolean');
|
|
59
59
|
} else if (p.match('null')) {
|
|
60
60
|
p.eatProduction('Null');
|
|
61
|
-
} else if (p.match(
|
|
62
|
-
p.eat(
|
|
61
|
+
} else if (p.match(/[a-zA-Z]/y)) {
|
|
62
|
+
p.eat(/[a-zA-Z]+/y, ID, p.m.attributes);
|
|
63
63
|
} else if (p.match('<')) {
|
|
64
64
|
p.eatProduction('Spamex:Matcher');
|
|
65
65
|
}
|
|
@@ -86,7 +86,7 @@ const grammar = class InstructionMiniparserGrammar {
|
|
|
86
86
|
|
|
87
87
|
// @Node
|
|
88
88
|
Property(p) {
|
|
89
|
-
p.eat(
|
|
89
|
+
p.eat(/[a-zA-Z]+/y, LIT, { path: 'key' });
|
|
90
90
|
p.eatMatchTrivia(_);
|
|
91
91
|
p.eat(':', PN, { path: 'mapToken' });
|
|
92
92
|
p.eatMatchTrivia(_);
|
package/lib/languages/regex.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
const when = require('iter-tools
|
|
1
|
+
const when = require('iter-tools/methods/when');
|
|
2
2
|
const { escapables } = require('./cstml.js');
|
|
3
3
|
const { buildCovers } = require('../utils.js');
|
|
4
4
|
const { node } = require('../symbols.js');
|
|
5
5
|
|
|
6
6
|
const name = 'Regex';
|
|
7
7
|
|
|
8
|
-
const canonicalURL = 'https://bablr.org/languages/core/bablr-regex-pattern';
|
|
8
|
+
const canonicalURL = 'https://bablr.org/languages/core/en/bablr-regex-pattern';
|
|
9
9
|
|
|
10
10
|
const dependencies = {};
|
|
11
11
|
|
|
@@ -96,10 +96,10 @@ const cookEscape = (escape, span) => {
|
|
|
96
96
|
return String.fromCodePoint(parseInt(hexMatch[1], 16));
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
let litMatch = /\\([nrt0])/y.exec(escape);
|
|
99
|
+
let litMatch = /\\([\\nrt0])/y.exec(escape);
|
|
100
100
|
|
|
101
101
|
if (litMatch) {
|
|
102
|
-
return escapables.get(litMatch[1]);
|
|
102
|
+
return escapables.get(litMatch[1]) || litMatch[1];
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
let specialMatch = getSpecialPattern(span).exec(escape.slice(1));
|
|
@@ -154,7 +154,7 @@ const grammar = class RegexMiniparserGrammar {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
Elements(p) {
|
|
157
|
-
while (p.match(/[^|]/y)) {
|
|
157
|
+
while (p.match(/[^|]/y || p.atExpression)) {
|
|
158
158
|
p.eatProduction('Element');
|
|
159
159
|
}
|
|
160
160
|
}
|
|
@@ -247,6 +247,8 @@ const grammar = class RegexMiniparserGrammar {
|
|
|
247
247
|
)
|
|
248
248
|
) {
|
|
249
249
|
// done
|
|
250
|
+
} else if (p.eatMatchEscape(new RegExp(String.raw`\\${specialPattern.source}`, 'y'))) {
|
|
251
|
+
// done
|
|
250
252
|
} else {
|
|
251
253
|
throw new Error('escape required');
|
|
252
254
|
}
|
package/lib/languages/spamex.js
CHANGED
|
@@ -10,7 +10,7 @@ const LIT = 'Literal';
|
|
|
10
10
|
|
|
11
11
|
const name = 'Spamex';
|
|
12
12
|
|
|
13
|
-
const canonicalURL = 'https://bablr.org/languages/core/spamex';
|
|
13
|
+
const canonicalURL = 'https://bablr.org/languages/core/en/spamex';
|
|
14
14
|
|
|
15
15
|
const dependencies = { CSTML, Regex };
|
|
16
16
|
|
|
@@ -25,7 +25,7 @@ const covers = buildCovers({
|
|
|
25
25
|
const grammar = class SpamexMiniparserGrammar {
|
|
26
26
|
// @Cover
|
|
27
27
|
Matcher(p) {
|
|
28
|
-
if (p.match(/<
|
|
28
|
+
if (p.match(/<[^!/]/y)) {
|
|
29
29
|
p.eatProduction('NodeMatcher');
|
|
30
30
|
} else if (p.match(/['"]/y)) {
|
|
31
31
|
p.eatProduction('CSTML:String');
|
|
@@ -40,14 +40,20 @@ const grammar = class SpamexMiniparserGrammar {
|
|
|
40
40
|
NodeMatcher(p) {
|
|
41
41
|
p.eat('<', PN, { path: 'openToken', startSpan: 'Tag', balanced: '>' });
|
|
42
42
|
|
|
43
|
-
p.
|
|
43
|
+
if (!p.atExpression) {
|
|
44
|
+
p.eatProduction('CSTML:Flags', { path: 'flags' });
|
|
45
|
+
}
|
|
44
46
|
|
|
45
|
-
if (p.match(
|
|
46
|
-
p.eat(
|
|
47
|
+
if (p.match(/[a-zA-Z]+:/y)) {
|
|
48
|
+
p.eat(/[a-zA-Z]+/y, ID, { path: 'language' });
|
|
47
49
|
p.eat(':', PN, { path: 'namespaceSeparatorToken' });
|
|
48
|
-
p.eat(
|
|
50
|
+
p.eat(/[a-zA-Z]+/y, ID, { path: 'type' });
|
|
49
51
|
} else {
|
|
50
|
-
p.
|
|
52
|
+
if (p.atExpression) {
|
|
53
|
+
p.eatProduction('Identifier', { path: 'type' });
|
|
54
|
+
} else {
|
|
55
|
+
p.eatMatch(/[a-zA-Z]+/y, ID, { path: 'type' });
|
|
56
|
+
}
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
let sp = p.eatMatchTrivia(_);
|
|
@@ -58,7 +64,7 @@ const grammar = class SpamexMiniparserGrammar {
|
|
|
58
64
|
sp = p.eatMatchTrivia(_);
|
|
59
65
|
}
|
|
60
66
|
|
|
61
|
-
if ((sp && p.match(
|
|
67
|
+
if ((sp && p.match(/[a-zA-Z]+/y)) || p.atExpression) {
|
|
62
68
|
p.eatProduction('Attributes', { path: 'attributes[]' });
|
|
63
69
|
sp = p.eatMatchTrivia(_);
|
|
64
70
|
}
|
|
@@ -69,9 +75,9 @@ const grammar = class SpamexMiniparserGrammar {
|
|
|
69
75
|
|
|
70
76
|
Attributes(p) {
|
|
71
77
|
let sp = true;
|
|
72
|
-
while (sp && (p.match(
|
|
78
|
+
while (sp && (p.match(/[a-zA-Z]+/y) || p.atExpression)) {
|
|
73
79
|
p.eatProduction('Attribute');
|
|
74
|
-
if (p.match(/\s
|
|
80
|
+
if (p.match(/\s+[a-zA-Z]/y)) {
|
|
75
81
|
sp = p.eatMatchTrivia(_);
|
|
76
82
|
}
|
|
77
83
|
}
|
|
@@ -79,7 +85,7 @@ const grammar = class SpamexMiniparserGrammar {
|
|
|
79
85
|
|
|
80
86
|
// @Cover
|
|
81
87
|
Attribute(p) {
|
|
82
|
-
if (p.match(
|
|
88
|
+
if (p.match(/[a-zA-Z]+\s*=/y)) {
|
|
83
89
|
p.eatProduction('MappingAttribute');
|
|
84
90
|
} else {
|
|
85
91
|
p.eatProduction('BooleanAttribute');
|
|
@@ -88,12 +94,12 @@ const grammar = class SpamexMiniparserGrammar {
|
|
|
88
94
|
|
|
89
95
|
// @Node
|
|
90
96
|
BooleanAttribute(p) {
|
|
91
|
-
p.eat(
|
|
97
|
+
p.eat(/[a-zA-Z]+/y, LIT, { path: 'key' });
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
// @Node
|
|
95
101
|
MappingAttribute(p) {
|
|
96
|
-
p.eat(
|
|
102
|
+
p.eat(/[a-zA-Z]+/y, LIT, { path: 'key' });
|
|
97
103
|
p.eatMatchTrivia(_);
|
|
98
104
|
p.eat('=', PN, { path: 'mapToken' });
|
|
99
105
|
p.eatMatchTrivia(_);
|
|
@@ -120,7 +126,7 @@ const grammar = class SpamexMiniparserGrammar {
|
|
|
120
126
|
|
|
121
127
|
// @Node
|
|
122
128
|
Identifier(p) {
|
|
123
|
-
p.eatLiteral(
|
|
129
|
+
p.eatLiteral(/[a-zA-Z]+/y);
|
|
124
130
|
}
|
|
125
131
|
};
|
|
126
132
|
|
package/lib/miniparser.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const { ref, lit, trivia, esc } = require('@bablr/boot-helpers/types');
|
|
2
2
|
const escapeRegex = require('escape-string-regexp');
|
|
3
|
-
const arrayLast = require('iter-tools
|
|
4
|
-
const isString = require('iter-tools
|
|
5
|
-
const isObject = require('iter-tools
|
|
3
|
+
const arrayLast = require('iter-tools/methods/array-last');
|
|
4
|
+
const isString = require('iter-tools/methods/is-string');
|
|
5
|
+
const isObject = require('iter-tools/methods/is-object');
|
|
6
6
|
const sym = require('./symbols.js');
|
|
7
7
|
const { Match } = require('./match.js');
|
|
8
8
|
const { parsePath } = require('./path.js');
|
|
@@ -10,6 +10,8 @@ const { set, isRegex, isArray, getPrototypeOf, buildNode } = require('./utils.js
|
|
|
10
10
|
|
|
11
11
|
class TemplateParser {
|
|
12
12
|
constructor(rootLanguage, quasis, expressions) {
|
|
13
|
+
if (!quasis) throw new Error();
|
|
14
|
+
|
|
13
15
|
this.rootLanguage = rootLanguage;
|
|
14
16
|
this.spans = [];
|
|
15
17
|
this.quasis = quasis;
|
package/lib/path.js
CHANGED
|
@@ -15,7 +15,7 @@ const stripPathBraces = (str) => (str.endsWith('[]') ? str.slice(0, -2) : str);
|
|
|
15
15
|
const parsePath = (str) => {
|
|
16
16
|
const name = stripPathBraces(str);
|
|
17
17
|
|
|
18
|
-
if (
|
|
18
|
+
if (!/[a-zA-Z]+$/.test(name)) throw new Error();
|
|
19
19
|
|
|
20
20
|
return { isArray: name !== str, name };
|
|
21
21
|
};
|
package/lib/print.js
CHANGED
|
@@ -84,7 +84,7 @@ const buildDoctypeTag = () => {
|
|
|
84
84
|
return freeze({ type: 'DoctypeTag', value: { doctype: 'cstml', version: 0 } });
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
-
const buildNodeOpenTag = (flags, language, type, attributes = {}) => {
|
|
87
|
+
const buildNodeOpenTag = (flags = {}, language = null, type = null, attributes = {}) => {
|
|
88
88
|
let { token, trivia, escape } = flags;
|
|
89
89
|
|
|
90
90
|
token = !!token;
|
|
@@ -97,27 +97,17 @@ const buildNodeOpenTag = (flags, language, type, attributes = {}) => {
|
|
|
97
97
|
});
|
|
98
98
|
};
|
|
99
99
|
|
|
100
|
-
const nodeFlags = freeze({ escape: false, trivia: false, token: false });
|
|
101
|
-
|
|
102
|
-
const buildFragmentOpenTag = (flags = nodeFlags) => {
|
|
103
|
-
return freeze({ type: 'OpenFragmentTag', value: freeze({ flags: freeze(flags) }) });
|
|
104
|
-
};
|
|
105
|
-
|
|
106
100
|
const buildNodeCloseTag = (type = null, language = null) => {
|
|
107
101
|
return freeze({ type: 'CloseNodeTag', value: freeze({ language, type }) });
|
|
108
102
|
};
|
|
109
103
|
|
|
110
|
-
const buildFragmentCloseTag = () => {
|
|
111
|
-
return freeze({ type: 'CloseFragmentTag', value: freeze({}) });
|
|
112
|
-
};
|
|
113
|
-
|
|
114
104
|
function* streamFromTree(rootNode) {
|
|
115
105
|
if (!rootNode || rootNode.type === 'Gap') {
|
|
116
106
|
return rootNode;
|
|
117
107
|
}
|
|
118
108
|
|
|
119
109
|
yield buildDoctypeTag();
|
|
120
|
-
yield
|
|
110
|
+
yield buildNodeOpenTag(undefined, rootNode.language[0]);
|
|
121
111
|
|
|
122
112
|
let stack = emptyStack.push(buildFrame(rootNode));
|
|
123
113
|
|
|
@@ -173,7 +163,7 @@ function* streamFromTree(rootNode) {
|
|
|
173
163
|
|
|
174
164
|
stack = stack.pop();
|
|
175
165
|
}
|
|
176
|
-
yield
|
|
166
|
+
yield buildNodeCloseTag();
|
|
177
167
|
}
|
|
178
168
|
|
|
179
169
|
const printExpression = (expr) => {
|
|
@@ -262,19 +252,10 @@ const printTerminal = (terminal) => {
|
|
|
262
252
|
return `<${printFlags(flags)}${printTagPath(tagLanguage, type)}${attributesFrag}>`;
|
|
263
253
|
}
|
|
264
254
|
|
|
265
|
-
case 'OpenFragmentTag': {
|
|
266
|
-
const { flags } = terminal.value;
|
|
267
|
-
return `<${printFlags(flags)}>`;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
255
|
case 'CloseNodeTag': {
|
|
271
256
|
return `</>`;
|
|
272
257
|
}
|
|
273
258
|
|
|
274
|
-
case 'CloseFragmentTag': {
|
|
275
|
-
return `</>`;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
259
|
default:
|
|
279
260
|
throw new Error();
|
|
280
261
|
}
|
|
@@ -296,7 +277,7 @@ const printPrettyCSTML = (tree, indent = ' ') => {
|
|
|
296
277
|
printed += '\n';
|
|
297
278
|
}
|
|
298
279
|
|
|
299
|
-
if (
|
|
280
|
+
if (terminal.type === 'CloseNodeTag') {
|
|
300
281
|
indentLevel--;
|
|
301
282
|
}
|
|
302
283
|
|
|
@@ -307,7 +288,7 @@ const printPrettyCSTML = (tree, indent = ' ') => {
|
|
|
307
288
|
}
|
|
308
289
|
printed += printTerminal(terminal);
|
|
309
290
|
|
|
310
|
-
if (
|
|
291
|
+
if (terminal.type === 'OpenNodeTag') {
|
|
311
292
|
indentLevel++;
|
|
312
293
|
}
|
|
313
294
|
|
package/lib/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const every = require('iter-tools
|
|
2
|
-
const isArray = require('iter-tools
|
|
3
|
-
const isString = require('iter-tools
|
|
1
|
+
const every = require('iter-tools/methods/every');
|
|
2
|
+
const isArray = require('iter-tools/methods/is-array');
|
|
3
|
+
const isString = require('iter-tools/methods/is-string');
|
|
4
4
|
|
|
5
5
|
const { hasOwn, getPrototypeOf, getOwnPropertySymbols } = Object;
|
|
6
6
|
const isSymbol = (value) => typeof value === 'symbol';
|
|
@@ -71,7 +71,7 @@ const set = (obj, path, value) => {
|
|
|
71
71
|
if (hasOwn(obj, name)) {
|
|
72
72
|
throw new Error('duplicate child name');
|
|
73
73
|
}
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
obj[name] = value;
|
|
76
76
|
}
|
|
77
77
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bablr/boot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Compile-time tools for bootstrapping BABLR VM",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=12.0.0"
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@babel/types": "7.23.0",
|
|
25
25
|
"@bablr/boot-helpers": "0.2.0",
|
|
26
26
|
"escape-string-regexp": "4.0.0",
|
|
27
|
-
"iter-tools
|
|
27
|
+
"iter-tools": "^7.5.3",
|
|
28
28
|
"jest-diff": "29.7.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
package/shorthand.macro.js
CHANGED
|
@@ -2,11 +2,11 @@ const { spawnSync } = require('node:child_process');
|
|
|
2
2
|
const t = require('@babel/types');
|
|
3
3
|
const { expression } = require('@babel/template');
|
|
4
4
|
const { diff } = require('jest-diff');
|
|
5
|
-
const isObject = require('iter-tools
|
|
6
|
-
const isUndefined = require('iter-tools
|
|
7
|
-
const isNull = require('iter-tools
|
|
8
|
-
const isString = require('iter-tools
|
|
9
|
-
const concat = require('iter-tools
|
|
5
|
+
const isObject = require('iter-tools/methods/is-object');
|
|
6
|
+
const isUndefined = require('iter-tools/methods/is-undefined');
|
|
7
|
+
const isNull = require('iter-tools/methods/is-null');
|
|
8
|
+
const isString = require('iter-tools/methods/is-string');
|
|
9
|
+
const concat = require('iter-tools/methods/concat');
|
|
10
10
|
const { createMacro } = require('babel-plugin-macros');
|
|
11
11
|
const { TemplateParser, set, getAgASTValue } = require('./lib/index.js');
|
|
12
12
|
const i = require('./lib/languages/instruction.js');
|
|
@@ -195,16 +195,16 @@ const getTopScope = (scope) => {
|
|
|
195
195
|
|
|
196
196
|
const namesFor = Object.fromEntries([
|
|
197
197
|
...[i, re, spam, cstml].map((l) => [l.canonicalURL, l.name]),
|
|
198
|
-
['https://bablr.org/languages/core/space-tab-newline', 'Space'],
|
|
198
|
+
['https://bablr.org/languages/core/en/space-tab-newline', 'Space'],
|
|
199
199
|
]);
|
|
200
200
|
|
|
201
201
|
const languages = {
|
|
202
|
-
i: '@bablr/language-bablr-vm-instruction',
|
|
203
|
-
re: '@bablr/language-regex-vm-pattern',
|
|
204
|
-
spam: '@bablr/language-spamex',
|
|
205
|
-
str: '@bablr/language-cstml',
|
|
206
|
-
num: '@bablr/language-cstml',
|
|
207
|
-
cst: '@bablr/language-cstml',
|
|
202
|
+
i: '@bablr/language-en-bablr-vm-instruction',
|
|
203
|
+
re: '@bablr/language-en-regex-vm-pattern',
|
|
204
|
+
spam: '@bablr/language-en-spamex',
|
|
205
|
+
str: '@bablr/language-en-cstml',
|
|
206
|
+
num: '@bablr/language-en-cstml',
|
|
207
|
+
cst: '@bablr/language-en-cstml',
|
|
208
208
|
};
|
|
209
209
|
|
|
210
210
|
const topTypes = {
|
|
@@ -213,7 +213,7 @@ const topTypes = {
|
|
|
213
213
|
spam: 'Matcher',
|
|
214
214
|
str: 'String',
|
|
215
215
|
num: 'Integer',
|
|
216
|
-
cst: '
|
|
216
|
+
cst: 'Node',
|
|
217
217
|
};
|
|
218
218
|
|
|
219
219
|
const miniLanguages = {
|