@bablr/boot 0.1.8 → 0.2.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/README.md +19 -0
- package/lib/builders.js +422 -0
- package/lib/index.js +124 -19
- package/lib/languages/cstml.js +258 -93
- package/lib/languages/instruction.js +10 -5
- package/lib/languages/regex.js +124 -36
- package/lib/languages/spamex.js +31 -60
- package/lib/miniparser.js +12 -10
- package/lib/path.js +3 -3
- package/lib/print.js +352 -0
- package/lib/utils.js +9 -8
- package/package.json +8 -5
- package/shorthand.macro.js +201 -91
- package/lib/languages/number.js +0 -38
- package/lib/languages/string.js +0 -88
package/lib/languages/cstml.js
CHANGED
|
@@ -1,118 +1,198 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
const Number = require('./number.js');
|
|
1
|
+
const objectEntries = require('iter-tools-es/methods/object-entries');
|
|
2
|
+
|
|
4
3
|
const { buildCovers } = require('../utils.js');
|
|
5
4
|
const sym = require('../symbols.js');
|
|
6
5
|
|
|
7
6
|
const _ = /\s+/y;
|
|
8
7
|
const PN = 'Punctuator';
|
|
9
8
|
const ID = 'Identifier';
|
|
9
|
+
const KW = 'Keyword';
|
|
10
10
|
const LIT = 'Literal';
|
|
11
11
|
|
|
12
12
|
const name = 'CSTML';
|
|
13
13
|
|
|
14
|
-
const
|
|
14
|
+
const canonicalURL = 'https://bablr.org/languages/core/cstml';
|
|
15
|
+
|
|
16
|
+
const dependencies = {};
|
|
17
|
+
|
|
18
|
+
const escapables = new Map(
|
|
19
|
+
objectEntries({
|
|
20
|
+
n: '\n',
|
|
21
|
+
r: '\r',
|
|
22
|
+
t: '\t',
|
|
23
|
+
0: '\0',
|
|
24
|
+
}),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const cookEscape = (escape, span) => {
|
|
28
|
+
let hexMatch;
|
|
29
|
+
|
|
30
|
+
if (!escape.startsWith('\\')) {
|
|
31
|
+
throw new Error('string escape must start with \\');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if ((hexMatch = /\\u([0-9a-f]{4})/iy.exec(escape))) {
|
|
35
|
+
//continue
|
|
36
|
+
} else if ((hexMatch = /\\u{([0-9a-f]+)}/iy.exec(escape))) {
|
|
37
|
+
//continue
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (hexMatch) {
|
|
41
|
+
return String.fromCodePoint(parseInt(hexMatch[1], 16));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const litPattern = span === 'Single' ? /\\([\\gnrt0'])/y : /\\([\\gnrt0"])/y;
|
|
45
|
+
const litMatch = litPattern.exec(escape);
|
|
46
|
+
|
|
47
|
+
if (litMatch) {
|
|
48
|
+
if (litMatch[1] === 'g') {
|
|
49
|
+
return null;
|
|
50
|
+
} else {
|
|
51
|
+
return escapables.get(litMatch[1]) || litMatch[1];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
throw new Error('unable to cook string escape');
|
|
56
|
+
};
|
|
15
57
|
|
|
16
58
|
const covers = buildCovers({
|
|
17
59
|
[sym.node]: [
|
|
60
|
+
'Document',
|
|
61
|
+
'DocumentVersion',
|
|
62
|
+
'DoctypeTag',
|
|
18
63
|
'Attribute',
|
|
19
64
|
'Property',
|
|
65
|
+
'Reference',
|
|
20
66
|
'TagType',
|
|
67
|
+
'Null',
|
|
68
|
+
'Gap',
|
|
21
69
|
'Node',
|
|
22
|
-
'
|
|
23
|
-
'
|
|
70
|
+
'IdentifierPath',
|
|
71
|
+
'OpenFragmentTag',
|
|
24
72
|
'OpenNodeTag',
|
|
25
73
|
'CloseNodeTag',
|
|
74
|
+
'CloseFragmentTag',
|
|
26
75
|
'Terminal',
|
|
76
|
+
'Number',
|
|
77
|
+
'Digit',
|
|
78
|
+
'String',
|
|
79
|
+
'Content',
|
|
80
|
+
'UnsignedInteger',
|
|
27
81
|
],
|
|
28
82
|
[sym.fragment]: ['Attributes', 'Fragment'],
|
|
29
83
|
Attribute: ['MappingAttribute', 'BooleanAttribute'],
|
|
30
|
-
AttributeValue: ['String
|
|
84
|
+
AttributeValue: ['String', 'Number'],
|
|
31
85
|
TagType: ['Identifier', 'GlobalIdentifier'],
|
|
32
86
|
Terminal: ['Literal', 'Trivia', 'Escape'],
|
|
87
|
+
PropertyValue: ['Gap', 'Node', 'Null'],
|
|
33
88
|
EmbeddedTerminal: ['Literal', 'Escape'],
|
|
89
|
+
Number: ['Integer', 'Infinity'],
|
|
34
90
|
});
|
|
35
91
|
|
|
36
92
|
const grammar = class CSTMLMiniparserGrammar {
|
|
37
93
|
Fragment(p) {
|
|
38
94
|
p.eatMatchTrivia(_);
|
|
39
|
-
p.eatProduction('
|
|
40
|
-
p.eatProduction('FragmentChildren');
|
|
41
|
-
p.eatProduction('CloseNodeTag', { path: 'close' });
|
|
42
|
-
p.eatMatchTrivia(_);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
FragmentChildren(p) {
|
|
95
|
+
p.eatProduction('OpenFragmentTag', { path: 'open' });
|
|
46
96
|
p.eatMatchTrivia(_);
|
|
47
|
-
while (p.match(
|
|
48
|
-
|
|
49
|
-
p.eatProduction('Trivia', { path: 'children[]' });
|
|
50
|
-
} else {
|
|
51
|
-
p.eatProduction('Property', { path: 'children[]' });
|
|
52
|
-
}
|
|
97
|
+
while (p.match(/<[^/]/y) || p.atExpression) {
|
|
98
|
+
p.eatProduction('Node', { path: 'root' });
|
|
53
99
|
p.eatMatchTrivia(_);
|
|
54
100
|
}
|
|
101
|
+
p.eatProduction('CloseFragmentTag', { path: 'close' });
|
|
102
|
+
p.eatMatchTrivia(_);
|
|
55
103
|
}
|
|
56
104
|
|
|
57
105
|
// @Node
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
106
|
+
Document(p) {
|
|
107
|
+
p.eatProduction('DoctypeTag', { path: 'doctype' });
|
|
108
|
+
p.eatProduction('Fragment', { path: 'tree' });
|
|
109
|
+
}
|
|
61
110
|
|
|
62
|
-
|
|
111
|
+
// @Node
|
|
112
|
+
DoctypeTag(p) {
|
|
113
|
+
p.eat('<!', PN, { path: 'open' });
|
|
114
|
+
p.eatProduction('UnsignedInteger', { path: 'version' });
|
|
115
|
+
p.eat(':', PN, { path: 'versionSeparator' });
|
|
116
|
+
p.eat('cstml', KW, { path: 'doctype' });
|
|
63
117
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
p.eatProduction('
|
|
118
|
+
let sp = p.eatMatchTrivia(_);
|
|
119
|
+
|
|
120
|
+
if ((sp && p.match(/\w+/y)) || p.atExpression) {
|
|
121
|
+
p.eatProduction('Attributes');
|
|
122
|
+
sp = p.eatMatchTrivia(_);
|
|
68
123
|
}
|
|
124
|
+
|
|
125
|
+
p.eat('>', PN, { path: 'close' });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// @Node
|
|
129
|
+
Null(p) {
|
|
130
|
+
p.eat('null', KW, { path: 'value' });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// @Node
|
|
134
|
+
Gap(p) {
|
|
135
|
+
p.eat('<//>', PN, { path: 'value' });
|
|
69
136
|
}
|
|
70
137
|
|
|
71
|
-
|
|
72
|
-
|
|
138
|
+
// @Node
|
|
139
|
+
Node(p) {
|
|
140
|
+
if (p.match('<>')) throw new Error('Fragment is not a node');
|
|
141
|
+
|
|
142
|
+
let open = p.eatProduction('OpenNodeTag', { path: 'open' });
|
|
73
143
|
|
|
74
144
|
p.eatMatchTrivia(_);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
} else {
|
|
79
|
-
p.eatProduction('Property', { path: 'children[]' });
|
|
80
|
-
properties++;
|
|
81
|
-
}
|
|
145
|
+
|
|
146
|
+
if (open.properties.flags?.token) {
|
|
147
|
+
p.eatProduction('NodeChild', { path: 'children[]' }, { token: true });
|
|
82
148
|
p.eatMatchTrivia(_);
|
|
149
|
+
} else {
|
|
150
|
+
while (!p.match('</')) {
|
|
151
|
+
p.eatProduction('NodeChild', { path: 'children[]' });
|
|
152
|
+
p.eatMatchTrivia(_);
|
|
153
|
+
}
|
|
83
154
|
}
|
|
84
155
|
|
|
85
|
-
|
|
156
|
+
p.eatProduction('CloseNodeTag', { path: 'close' });
|
|
86
157
|
}
|
|
87
158
|
|
|
88
|
-
|
|
89
|
-
|
|
159
|
+
NodeChild(p, _, props) {
|
|
160
|
+
const { token } = props || {};
|
|
90
161
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
162
|
+
if (token) {
|
|
163
|
+
p.eatProduction('Literal');
|
|
164
|
+
} else {
|
|
165
|
+
if (p.match(/<\*?#/y)) {
|
|
166
|
+
p.eatProduction('Node');
|
|
167
|
+
} else if (p.match(/\w/y)) {
|
|
168
|
+
p.eatProduction('Property');
|
|
169
|
+
} else if (p.match(/['"]/y)) {
|
|
170
|
+
p.eatProduction('Literal');
|
|
98
171
|
}
|
|
99
|
-
p.eatMatchTrivia(_);
|
|
100
172
|
}
|
|
101
|
-
|
|
102
|
-
if (!properties) throw new Error('Nodes must match text');
|
|
103
173
|
}
|
|
104
174
|
|
|
105
175
|
// @Node
|
|
106
176
|
Property(p) {
|
|
107
|
-
p.
|
|
177
|
+
p.eatProduction('Reference', { path: 'reference' });
|
|
108
178
|
p.eatMatchTrivia(_);
|
|
109
179
|
p.eat(':', PN, { path: 'mapOperator' });
|
|
110
180
|
p.eatMatchTrivia(_);
|
|
111
|
-
p.eatProduction('
|
|
181
|
+
p.eatProduction('PropertyValue', { path: 'value' });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
PropertyValue(p) {
|
|
185
|
+
if (p.match('null')) {
|
|
186
|
+
p.eatProduction('Null');
|
|
187
|
+
} else if (p.match('<//>')) {
|
|
188
|
+
p.eatProduction('Gap');
|
|
189
|
+
} else {
|
|
190
|
+
p.eatProduction('Node');
|
|
191
|
+
}
|
|
112
192
|
}
|
|
113
193
|
|
|
114
194
|
// @Node
|
|
115
|
-
|
|
195
|
+
OpenFragmentTag(p) {
|
|
116
196
|
p.eat('<', PN, { path: 'open', startSpan: 'Tag', balanced: '>' });
|
|
117
197
|
p.eat('>', PN, { path: 'close', endSpan: 'Tag', balancer: true });
|
|
118
198
|
}
|
|
@@ -120,30 +200,22 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
120
200
|
// @Node
|
|
121
201
|
OpenNodeTag(p) {
|
|
122
202
|
p.eat('<', PN, { path: 'open', startSpan: 'Tag', balanced: '>' });
|
|
123
|
-
p.eatProduction('TagType', { path: 'type' });
|
|
124
203
|
|
|
125
|
-
let
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
sp = p.eatMatchTrivia(_);
|
|
130
|
-
}
|
|
204
|
+
let tr = p.eatMatch('#', PN, { path: 'triviaFlag' });
|
|
205
|
+
let tok = p.eatMatch('*', PN, { path: 'tokenFlag' });
|
|
206
|
+
let esc = p.eatMatch('@', PN, { path: 'escapeFlag' });
|
|
207
|
+
let exp = p.eatMatch('+', PN, { path: 'expressionFlag' });
|
|
131
208
|
|
|
132
|
-
|
|
133
|
-
p.eat('>', PN, { path: 'close', endSpan: 'Tag', balancer: true });
|
|
134
|
-
}
|
|
209
|
+
if ((tr && esc) || (exp && (tr || esc))) throw new Error();
|
|
135
210
|
|
|
136
|
-
// @Node
|
|
137
|
-
OpenTerminalNodeTag(p) {
|
|
138
|
-
p.eat('<|', PN, { path: 'open', startSpan: 'Tag', balanced: '>' });
|
|
139
|
-
p.eatMatchTrivia(_);
|
|
140
211
|
p.eatProduction('TagType', { path: 'type' });
|
|
141
212
|
|
|
142
213
|
let sp = p.eatMatchTrivia(_);
|
|
143
214
|
|
|
144
|
-
let
|
|
145
|
-
if (sp && p.match(/['"/]/y)) {
|
|
146
|
-
|
|
215
|
+
let iv;
|
|
216
|
+
if (tok && sp && (p.match(/['"/]/y) || p.atExpression)) {
|
|
217
|
+
iv = p.eatProduction('String', { path: 'intrinsicValue' });
|
|
218
|
+
|
|
147
219
|
sp = p.eatMatchTrivia(_);
|
|
148
220
|
}
|
|
149
221
|
|
|
@@ -153,15 +225,21 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
153
225
|
}
|
|
154
226
|
|
|
155
227
|
p.eatMatchTrivia(_);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
228
|
+
if (iv) {
|
|
229
|
+
p.eat('/', PN, { path: 'selfClosingToken' });
|
|
230
|
+
}
|
|
231
|
+
p.eat('>', PN, { path: 'close', endSpan: 'Tag', balancer: true });
|
|
159
232
|
}
|
|
160
233
|
|
|
161
234
|
// @Node
|
|
162
235
|
CloseNodeTag(p) {
|
|
163
236
|
p.eat('</', PN, { path: 'open', startSpan: 'Tag', balanced: '>' });
|
|
164
|
-
|
|
237
|
+
p.eat('>', PN, { path: 'close', endSpan: 'Tag', balancer: true });
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// @Node
|
|
241
|
+
CloseFragmentTag(p) {
|
|
242
|
+
p.eat('</', PN, { path: 'open', startSpan: 'Tag', balanced: '>' });
|
|
165
243
|
p.eat('>', PN, { path: 'close', endSpan: 'Tag', balancer: true });
|
|
166
244
|
}
|
|
167
245
|
|
|
@@ -184,7 +262,7 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
184
262
|
|
|
185
263
|
// @Cover
|
|
186
264
|
Attribute(p) {
|
|
187
|
-
if (p.match(/\w
|
|
265
|
+
if (p.match(/\w[\w-_]*\s*=/y)) {
|
|
188
266
|
p.eatProduction('MappingAttribute');
|
|
189
267
|
} else {
|
|
190
268
|
p.eatProduction('BooleanAttribute');
|
|
@@ -193,6 +271,7 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
193
271
|
|
|
194
272
|
// @Node
|
|
195
273
|
BooleanAttribute(p) {
|
|
274
|
+
p.eat('!', KW, { path: 'negated' });
|
|
196
275
|
p.eat(/\w+/y, ID, { path: 'key' });
|
|
197
276
|
}
|
|
198
277
|
|
|
@@ -208,31 +287,41 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
208
287
|
// @Cover
|
|
209
288
|
AttributeValue(p) {
|
|
210
289
|
if (p.match(/['"]/y)) {
|
|
211
|
-
p.eatProduction('String
|
|
212
|
-
} else if (p.match(
|
|
213
|
-
p.eatProduction('Number
|
|
290
|
+
p.eatProduction('String');
|
|
291
|
+
} else if (p.match(/[\d+-]/y)) {
|
|
292
|
+
p.eatProduction('Number');
|
|
214
293
|
}
|
|
215
294
|
}
|
|
216
295
|
|
|
217
|
-
// @Cover
|
|
218
296
|
TagType(p) {
|
|
219
|
-
if (p.match(
|
|
220
|
-
p.eatProduction('
|
|
297
|
+
if (p.match(/[\w.]+:/y)) {
|
|
298
|
+
p.eatProduction('LanguageReference', { path: 'language' });
|
|
299
|
+
p.eat(':', PN, { path: 'namespaceOperator' });
|
|
300
|
+
p.eatProduction('Identifier', { path: 'type' });
|
|
221
301
|
} else {
|
|
222
|
-
p.
|
|
302
|
+
p.eatProduction('Identifier', { path: 'type' });
|
|
223
303
|
}
|
|
224
304
|
}
|
|
225
305
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
306
|
+
LanguageReference(p) {
|
|
307
|
+
if (p.match(/['"]/y)) {
|
|
308
|
+
p.eatProduction('String');
|
|
309
|
+
} else {
|
|
310
|
+
p.eatProduction('IdentifierPath');
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
IdentifierPath(p) {
|
|
315
|
+
p.eatProduction('Identifier', { path: 'segments[]' });
|
|
316
|
+
while (p.match('.')) {
|
|
317
|
+
p.eat('.', PN, { path: 'separators[]' });
|
|
318
|
+
p.eatProduction('Identifier', { path: 'segments[]' });
|
|
319
|
+
}
|
|
231
320
|
}
|
|
232
321
|
|
|
233
322
|
// @Node
|
|
234
323
|
Identifier(p) {
|
|
235
|
-
p.eatLiteral(/\w
|
|
324
|
+
p.eatLiteral(/\w[\w-_]*/y);
|
|
236
325
|
}
|
|
237
326
|
|
|
238
327
|
// @Cover
|
|
@@ -248,6 +337,13 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
248
337
|
}
|
|
249
338
|
}
|
|
250
339
|
|
|
340
|
+
// @Node
|
|
341
|
+
Reference(p) {
|
|
342
|
+
p.eatProduction('Identifier', { path: 'name' });
|
|
343
|
+
p.eatMatchTrivia(_);
|
|
344
|
+
p.eatMatch('[]', PN, { path: 'arrayOperator' });
|
|
345
|
+
}
|
|
346
|
+
|
|
251
347
|
// @Cover
|
|
252
348
|
EmbeddedTerminal(p) {
|
|
253
349
|
if (p.match(/!['"]/y)) {
|
|
@@ -262,22 +358,91 @@ const grammar = class CSTMLMiniparserGrammar {
|
|
|
262
358
|
// @Node
|
|
263
359
|
Escape(p) {
|
|
264
360
|
p.eat('!', PN, { path: 'escapeOperator' });
|
|
265
|
-
p.eatProduction('String
|
|
361
|
+
p.eatProduction('String', { path: 'rawValue' });
|
|
266
362
|
p.eatMatchTrivia(_);
|
|
267
363
|
p.eat(':', PN, { path: 'rawOperator' });
|
|
268
|
-
p.eatProduction('String
|
|
364
|
+
p.eatProduction('String', { path: 'value' });
|
|
269
365
|
}
|
|
270
366
|
|
|
271
367
|
// @Node
|
|
272
368
|
Trivia(p) {
|
|
273
369
|
p.eat('#', PN, { path: 'trivializeOperator' });
|
|
274
|
-
p.eatProduction('String
|
|
370
|
+
p.eatProduction('String', { path: 'value' });
|
|
275
371
|
}
|
|
276
372
|
|
|
277
373
|
// @Node
|
|
278
374
|
Literal(p) {
|
|
279
|
-
p.eatProduction('String
|
|
375
|
+
p.eatProduction('String', { path: 'value' });
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
Number(p) {
|
|
379
|
+
if (p.match(/-?\d/y)) {
|
|
380
|
+
p.eatProduction('Integer');
|
|
381
|
+
} else {
|
|
382
|
+
p.eatProduction('Infinity');
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// @Node
|
|
387
|
+
Integer(p) {
|
|
388
|
+
p.eatMatch('-', 'Punctuator', { path: 'negative' });
|
|
389
|
+
p.eatProduction('Digits', { path: 'digits[]' });
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// @Node
|
|
393
|
+
UnsignedInteger(p) {
|
|
394
|
+
p.eatProduction('Digits', { path: 'digits[]' });
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// @Node
|
|
398
|
+
Infinity(p) {
|
|
399
|
+
p.eatMatch(/[+-]/, 'Punctuator', { path: 'sign' });
|
|
400
|
+
p.eat('Infinity', 'Keyword', { path: 'value' });
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
Digits(p) {
|
|
404
|
+
while (p.match(/\d/y)) {
|
|
405
|
+
p.eatProduction('Digit');
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// @Node
|
|
410
|
+
Digit(p) {
|
|
411
|
+
p.eatLiteral(/\d/y);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// @Node
|
|
415
|
+
String(p) {
|
|
416
|
+
const q = p.match(/['"]/y) || '"';
|
|
417
|
+
|
|
418
|
+
const span = q === '"' ? 'Double' : 'Single';
|
|
419
|
+
|
|
420
|
+
p.eat(q, PN, { path: 'open', startSpan: span, balanced: q });
|
|
421
|
+
while (p.match(/./sy) || p.atExpression) {
|
|
422
|
+
p.eatProduction('Content', { path: 'content' });
|
|
423
|
+
}
|
|
424
|
+
p.eat(q, PN, { path: 'close', endSpan: span, balancer: true });
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// @Node
|
|
428
|
+
Content(p) {
|
|
429
|
+
let esc, lit;
|
|
430
|
+
let i = 0;
|
|
431
|
+
do {
|
|
432
|
+
esc =
|
|
433
|
+
p.span.type === 'Single'
|
|
434
|
+
? p.eatMatchEscape(/\\(u(\{\d{1,6}\}|\d{4})|[\\gnrt0'])/y)
|
|
435
|
+
: p.eatMatchEscape(/\\(u(\{\d{1,6}\}|\d{4})|[\\gnrt0"])/y);
|
|
436
|
+
lit =
|
|
437
|
+
p.span.type === 'Single'
|
|
438
|
+
? p.eatMatchLiteral(/[^\r\n\0\\']+/y)
|
|
439
|
+
: p.eatMatchLiteral(/[^\r\n\0\\"]+/y);
|
|
440
|
+
i++;
|
|
441
|
+
} while (esc || lit);
|
|
442
|
+
if (i === 1 && !esc && !lit) {
|
|
443
|
+
throw new Error('Invalid string content');
|
|
444
|
+
}
|
|
280
445
|
}
|
|
281
446
|
};
|
|
282
447
|
|
|
283
|
-
module.exports = { name, dependencies, covers, grammar };
|
|
448
|
+
module.exports = { name, canonicalURL, dependencies, covers, grammar, cookEscape, escapables };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const Spamex = require('./spamex.js');
|
|
2
|
+
const CSTML = require('./cstml.js');
|
|
2
3
|
const Regex = require('./regex.js');
|
|
3
|
-
const StringLanguage = require('./string.js');
|
|
4
4
|
const { node } = require('../symbols.js');
|
|
5
5
|
const { buildCovers } = require('../utils.js');
|
|
6
6
|
|
|
@@ -12,7 +12,9 @@ const LIT = 'Literal';
|
|
|
12
12
|
|
|
13
13
|
const name = 'Instruction';
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const canonicalURL = 'https://bablr.org/languages/core/bablr-vm-instruction';
|
|
16
|
+
|
|
17
|
+
const dependencies = { Spamex, CSTML, Regex };
|
|
16
18
|
|
|
17
19
|
const covers = buildCovers({
|
|
18
20
|
[node]: ['Call', 'Punctuator', 'Property', 'Expression'],
|
|
@@ -21,7 +23,8 @@ const covers = buildCovers({
|
|
|
21
23
|
'Array',
|
|
22
24
|
'Tuple',
|
|
23
25
|
'Identifier',
|
|
24
|
-
'
|
|
26
|
+
'CSTML:String',
|
|
27
|
+
'CSTML:Gap',
|
|
25
28
|
'Regex:Pattern',
|
|
26
29
|
'Boolean',
|
|
27
30
|
'Null',
|
|
@@ -47,7 +50,9 @@ const grammar = class InstructionMiniparserGrammar {
|
|
|
47
50
|
} else if (p.match('(')) {
|
|
48
51
|
p.eatProduction('Tuple');
|
|
49
52
|
} else if (p.match(/['"]/y)) {
|
|
50
|
-
p.eatProduction('
|
|
53
|
+
p.eatProduction('CSTML:String');
|
|
54
|
+
} else if (p.match('<//>')) {
|
|
55
|
+
p.eatProduction('CSTML:Gap');
|
|
51
56
|
} else if (p.match('/')) {
|
|
52
57
|
p.eatProduction('Regex:Pattern');
|
|
53
58
|
} else if (p.match(/true|false/y)) {
|
|
@@ -133,4 +138,4 @@ const grammar = class InstructionMiniparserGrammar {
|
|
|
133
138
|
}
|
|
134
139
|
};
|
|
135
140
|
|
|
136
|
-
module.exports = { name, dependencies, covers, grammar };
|
|
141
|
+
module.exports = { name, canonicalURL, dependencies, covers, grammar };
|