@bablr/boot 0.10.0 → 0.11.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/index.js CHANGED
@@ -1,26 +1,39 @@
1
- import * as cstmll from './languages/cstml.js';
2
- import * as spamex from './languages/spamex.js';
3
- import * as regex from './languages/regex.js';
4
- import * as instruction from './languages/instruction.js';
1
+ import cstmll from './languages/cstml.js';
2
+ import spamex from './languages/spamex.js';
3
+ import regex from './languages/regex.js';
4
+ import instruction from './languages/instruction.js';
5
5
 
6
6
  import { TemplateParser } from './miniparser.js';
7
7
  import { buildEmbeddedMatcher, buildEmbeddedRegex } from '@bablr/agast-vm-helpers/builders';
8
+ import { reifyExpression } from '@bablr/agast-vm-helpers';
9
+ import { interpolate } from '@bablr/agast-helpers/template';
10
+ import { buildGapTag } from '@bablr/agast-helpers/builders';
11
+ import { buildNode } from '@bablr/agast-helpers/path';
8
12
 
9
13
  const trees = new WeakMap();
10
14
 
11
15
  export const buildTag = (language, defaultType) => {
12
16
  const defaultTag = (quasis, ...exprs) => {
13
17
  let tree;
14
- if (trees.has(quasis) && !exprs.length) {
18
+ if (trees.has(quasis)) {
15
19
  tree = trees.get(quasis);
16
20
  } else {
17
- tree = new TemplateParser(language, quasis.raw, exprs).eval({
21
+ tree = new TemplateParser(
22
+ language,
23
+ quasis.raw,
24
+ exprs.map((e) => buildNode(buildGapTag())),
25
+ ).eatProduction({
18
26
  language: language.name,
19
- type: defaultType,
27
+ name: defaultType,
20
28
  });
21
29
 
22
30
  trees.set(quasis, tree);
23
31
  }
32
+
33
+ if (exprs.length) {
34
+ tree = interpolate(tree, exprs);
35
+ }
36
+
24
37
  return tree;
25
38
  };
26
39
 
@@ -29,21 +42,30 @@ export const buildTag = (language, defaultType) => {
29
42
  return defaultTag.apply(receiver, argsList);
30
43
  },
31
44
 
32
- get(_, type) {
45
+ get(_, name) {
33
46
  const trees = new WeakMap();
34
47
 
35
48
  return (quasis, ...exprs) => {
36
49
  let tree;
37
- if (trees.has(quasis) && !exprs.length) {
50
+ if (trees.has(quasis)) {
38
51
  tree = trees.get(quasis);
39
52
  } else {
40
- tree = new TemplateParser(language, quasis.raw, exprs).eval({
53
+ tree = new TemplateParser(
54
+ language,
55
+ quasis.raw,
56
+ exprs.map((e) => buildNode(buildGapTag())),
57
+ ).eatProduction({
41
58
  language: language.name,
42
- type,
59
+ name,
43
60
  });
44
61
 
45
62
  trees.set(quasis, tree);
46
63
  }
64
+
65
+ if (exprs.length) {
66
+ tree = interpolate(tree, exprs);
67
+ }
68
+
47
69
  return tree;
48
70
  };
49
71
  },
@@ -52,7 +74,7 @@ export const buildTag = (language, defaultType) => {
52
74
 
53
75
  export const parse = (language, type, sourceText, expressions = []) => {
54
76
  let source = Array.isArray(sourceText) ? sourceText : [sourceText];
55
- return new TemplateParser(language, source, expressions).eval({
77
+ return new TemplateParser(language, source, expressions).eatProduction({
56
78
  language: language.name,
57
79
  type,
58
80
  });
@@ -60,12 +82,19 @@ export const parse = (language, type, sourceText, expressions = []) => {
60
82
 
61
83
  export const str = buildTag(cstmll, 'String');
62
84
  export const num = buildTag(cstmll, 'Integer');
63
- export const cst = buildTag(cstmll, 'Node');
85
+ export const cst = buildTag(cstmll, 'Document');
86
+ export const t_ = buildTag(cstmll, 'Tag');
64
87
  export const cstml = cst;
65
- export const spam_ = buildTag(spamex, 'Matcher');
88
+ export const spam_ = buildTag(spamex, 'PropertyMatcher');
66
89
  export const re_ = buildTag(regex, 'Pattern');
67
90
  export const i = buildTag(instruction, 'Call');
68
91
 
92
+ export const t = new Proxy(t_, {
93
+ apply(tag, _, args) {
94
+ return reifyExpression(tag(...args));
95
+ },
96
+ });
97
+
69
98
  export const spam = new Proxy(spam_, {
70
99
  apply(tag, _, args) {
71
100
  return buildEmbeddedMatcher(tag(...args));
@@ -1,9 +1,8 @@
1
- import * as sym from '@bablr/agast-vm-helpers/symbols';
2
- import * as JSON from './json.js';
3
- import { get, sourceTextFor } from '@bablr/agast-helpers/tree';
1
+ import JSON from './json.js';
2
+ import { get } from '@bablr/agast-helpers/tree';
4
3
 
5
4
  const _ = /\s+/y;
6
- const PN = 'Punctuator';
5
+ const PN = null;
7
6
  const KW = 'Keyword';
8
7
 
9
8
  export const name = 'CSTML';
@@ -16,11 +15,11 @@ export const dependencies = {
16
15
 
17
16
  export const covers = new Map([
18
17
  [
19
- sym.node,
18
+ Symbol.for('@bablr/node'),
20
19
  new Set([
21
20
  'Document',
22
- 'DocumentVersion',
23
21
  'DoctypeTag',
22
+ 'BoundNode',
24
23
  'Property',
25
24
  'ReferenceTag',
26
25
  'ReferenceFlags',
@@ -29,31 +28,50 @@ export const covers = new Map([
29
28
  'GlobalIdentifier',
30
29
  'NullTag',
31
30
  'GapTag',
32
- 'Node',
31
+ 'ShiftTag',
32
+ 'TreeNode',
33
+ 'NullNode',
34
+ 'GapNode',
33
35
  'IdentifierPath',
36
+ 'BindingSegment',
34
37
  'OpenNodeTag',
35
38
  'CloseNodeTag',
36
39
  'LiteralTag',
37
40
  'BindingTag',
38
- 'InitializerTag',
39
41
  'AttributeDefinition',
40
42
  'Number',
41
43
  'Digit',
42
- 'Content',
43
44
  'NodeFlags',
44
45
  ]),
45
46
  ],
47
+ [
48
+ 'Tag',
49
+ new Set([
50
+ 'DoctypeTag',
51
+ 'ReferenceTag',
52
+ 'NullTag',
53
+ 'GapTag',
54
+ 'ShiftTag',
55
+ 'OpenNodeTag',
56
+ 'CloseNodeTag',
57
+ 'LiteralTag',
58
+ 'BindingTag',
59
+ 'AttributeDefinition',
60
+ ]),
61
+ ],
62
+ [
63
+ 'Expression',
64
+ new Set(['ShiftExpression', 'BindingExpression', 'TreeNode', 'NullNode', 'GapNode']),
65
+ ],
46
66
  ]);
47
67
 
48
68
  export const grammar = class CSTMLMiniparserGrammar {
49
- // @Node
50
69
  Document(p) {
51
70
  p.eatProduction('DoctypeTag', { path: 'doctype' });
52
71
  p.eatMatchTrivia(_);
53
- p.eatProduction('Node', { path: 'tree' }, { forceFragment: true });
72
+ p.eatProduction('Expression', { path: 'tree' });
54
73
  }
55
74
 
56
- // @Node
57
75
  DoctypeTag(p) {
58
76
  p.eat('<!', PN, { path: 'openToken' });
59
77
  p.eatProduction('JSON:UnsignedInteger', { path: 'version' });
@@ -70,39 +88,24 @@ export const grammar = class CSTMLMiniparserGrammar {
70
88
  p.eat('>', PN, { path: 'closeToken' });
71
89
  }
72
90
 
73
- // @Node
74
91
  NullTag(p) {
75
92
  p.eat('null', KW, { path: 'sigilToken' });
76
93
  }
77
94
 
78
- // @Node
79
95
  GapTag(p) {
80
96
  p.eat('<//>', PN, { path: 'sigilToken' });
81
97
  }
82
98
 
83
- // @Node
84
99
  LiteralTag(p) {
85
100
  p.eatProduction('JSON:String', { path: 'value' });
86
101
  }
87
102
 
88
- //@Node
89
- InitializerTag(p) {
90
- let isArray;
91
- if ((isArray = p.match('['))) {
92
- p.eat('[]', PN, { path: 'sigilToken' });
93
- } else {
94
- p.eat('undefined', PN, { path: 'sigilToken' });
95
- }
96
- return { attrs: { isArray } };
97
- }
98
-
99
- // @Node
100
- Node(p, props) {
101
- let open = p.eatProduction('OpenNodeTag', { path: 'open', noInterpolate: true }, props);
103
+ TreeNode(p, props) {
104
+ let open = p.eatProduction('OpenNodeTag', { path: 'openTag', noInterpolate: true }, props);
102
105
 
103
106
  p.eatMatchTrivia(_);
104
107
 
105
- if (open.attributes.balanced) {
108
+ if (open.value.attributes.selfClosing) {
106
109
  let token = !!get(['flags', 'token'], open);
107
110
 
108
111
  while (p.atExpression || !(p.match(/<\/[^/]/y) || p.done)) {
@@ -110,7 +113,7 @@ export const grammar = class CSTMLMiniparserGrammar {
110
113
  p.eatMatchTrivia(_);
111
114
  }
112
115
 
113
- p.eatProduction('CloseNodeTag', { path: 'close', noInterpolate: true });
116
+ p.eatProduction('CloseNodeTag', { path: 'closeTag', noInterpolate: true });
114
117
  }
115
118
  }
116
119
 
@@ -138,9 +141,8 @@ export const grammar = class CSTMLMiniparserGrammar {
138
141
  }
139
142
  }
140
143
 
141
- // @Node
142
144
  AttributeDefinition(p) {
143
- p.eat('{', PN, { path: 'openToken', balanced: '}' });
145
+ p.eat('{', PN, { path: 'openToken' });
144
146
  p.eatMatchTrivia(_);
145
147
  p.eatProduction('IdentifierPath', { path: 'key' });
146
148
  p.eatMatchTrivia(_);
@@ -148,88 +150,79 @@ export const grammar = class CSTMLMiniparserGrammar {
148
150
  p.eatMatchTrivia(_);
149
151
  p.eatProduction('JSON:Expression', { path: 'value' });
150
152
  p.eatMatchTrivia(_);
151
- p.eat('}', PN, { path: 'closeToken', balancer: true });
153
+ p.eat('}', PN, { path: 'closeToken' });
152
154
  }
153
155
 
154
- // @Node
155
156
  Property(p) {
156
- let ref = null;
157
- if (p.match(/[a-zA-Z`\\\u{80}-\u{10ffff}.]|[.#@_]/uy)) {
158
- ref = p.eatProduction('ReferenceTag', { path: 'reference' });
157
+ if (p.match(/[a-zA-Z`\\\u{80}-\u{10ffff}.#@_]/uy)) {
158
+ p.eatProduction('ReferenceTag', { path: 'referenceTag' });
159
159
  }
160
160
  p.eatMatchTrivia(_);
161
- if (p.match(':')) {
162
- p.eatProduction('BindingTag', { path: 'binding' });
163
- p.eatMatchTrivia(_);
164
- }
165
- let refType = ref && get('type', ref);
166
- p.eatProduction('PropertyValue', {
161
+ p.eatProduction('Expression', {
167
162
  path: 'value',
168
- allowFragment: refType && sourceTextFor(refType) === '_',
169
163
  });
170
164
  }
171
165
 
172
- PropertyValue(p, { allowFragment }) {
166
+ NullNode(p) {
167
+ p.eatProduction('NullTag', { path: 'sigilTag' });
168
+ }
169
+
170
+ GapNode(p) {
171
+ p.eatProduction('GapTag', { path: 'sigilTag' });
172
+ }
173
+
174
+ Node(p) {
173
175
  if (p.match('null')) {
174
- p.eatProduction('NullTag');
175
- } else if (p.match(/\[\]|undefined/y)) {
176
- p.eatProduction('InitializerTag');
176
+ p.eatProduction('NullNode');
177
177
  } else if (p.match('<//>')) {
178
- p.eatProduction('GapTag');
178
+ p.eatProduction('GapNode');
179
+ } else if (p.match('</>') || p.match('<!')) {
180
+ p.fail();
179
181
  } else {
180
- p.eatProduction('Node', { allowFragment, propertyValue: true });
182
+ p.eatProduction('TreeNode', { propertyValue: true });
181
183
  }
182
184
  }
183
185
 
184
- // @Node
185
- NodeFlags(p) {
186
- p.eatMatch('*', PN, { path: 'tokenToken' });
187
- p.eatMatch('$', PN, { path: 'hasGapToken' });
188
- p.eatMatch('_', PN, { path: 'fragmentToken' });
189
- p.eatMatch('_', PN, { path: 'multiFragmentToken' });
186
+ NodeFlags(p, props) {
187
+ let token = !!(p.eatMatch('*', PN, { path: 'tokenToken' }) || props.token);
188
+ let hasGap = !!p.eatMatch('$', PN, { path: 'hasGapToken' });
189
+
190
+ return { attrs: { token, hasGap } };
190
191
  }
191
192
 
192
- // @Node
193
- OpenNodeTag(p, { forceFragment = false, allowFragment = true, propertyValue = false } = {}) {
193
+ OpenNodeTag(p) {
194
194
  if (p.match(/['"]/y)) {
195
+ p.eatProduction('NodeFlags', { path: 'flags' }, { token: true });
195
196
  p.eatProduction('JSON:String', { path: 'literalValue' });
196
197
  return;
197
198
  }
198
199
 
199
- p.eat('<', PN, { path: 'openToken', startSpan: 'Tag', balanced: '>' });
200
+ p.eat('<', PN, { path: 'openToken' });
200
201
 
201
- let flags = null;
202
202
  if (!p.atExpression) {
203
- flags = p.eatProduction('NodeFlags', { path: 'flags' });
203
+ p.eatProduction('NodeFlags', { path: 'flags' });
204
204
  }
205
205
 
206
206
  let sp = null;
207
207
 
208
- let fragmentFlag = get('fragmentToken', flags);
209
- let multiFragmentFlag = get('multiFragmentFlag', flags);
210
- let tokenFlag = get('tokenToken', flags);
211
-
212
- if (propertyValue && fragmentFlag && !multiFragmentFlag) throw new Error();
213
-
214
- if (forceFragment && !fragmentFlag) throw new Error();
215
-
216
- if (!fragmentFlag && !p.match(/./sy)) {
217
- throw new Error();
208
+ let type;
209
+ if ((type = p.match(/__|_/y))) {
210
+ p.eat(type, null, { path: 'type' });
218
211
  }
219
212
 
220
- if (fragmentFlag && !allowFragment) {
213
+ if (!type && !p.match(/./sy)) {
221
214
  throw new Error();
222
215
  }
223
216
 
224
- if (!fragmentFlag) {
225
- p.eatProduction('Identifier', { path: 'type' });
226
-
227
- sp = p.eatMatchTrivia(_);
217
+ if (type !== '__' && p.match(/[a-zA-Z`u{80}-\u{10ffff}]/uy)) {
218
+ p.eatProduction('Identifier', { path: 'name' });
219
+ }
228
220
 
229
- let iv;
221
+ sp = p.eatMatchTrivia(_);
230
222
 
223
+ if (!type) {
231
224
  if (sp && (p.match(/['"]/y) || p.atExpression)) {
232
- iv = p.eatProduction('JSON:String', { path: 'literalValue' });
225
+ p.eatProduction('JSON:String', { path: 'literalValue' });
233
226
 
234
227
  sp = p.eatMatchTrivia(_);
235
228
  }
@@ -242,48 +235,92 @@ export const grammar = class CSTMLMiniparserGrammar {
242
235
  p.eatMatchTrivia(_);
243
236
  }
244
237
  let sc = p.eatMatch('/', PN, { path: 'selfClosingToken' });
245
- p.eat('>', PN, { path: 'closeToken', endSpan: 'Tag', balancer: true });
238
+ p.eat('>', PN, { path: 'closeToken' });
246
239
 
247
- const balanced = !sc && (p.path.depth > 0 || p.span.type !== 'Bare');
240
+ const selfClosing = !sc && (p.path.depth > 0 || p.span.type !== 'Bare');
248
241
 
249
- return { attrs: { balanced } };
242
+ return { attrs: { selfClosing } };
250
243
  }
251
244
 
252
- // @Node
253
245
  CloseNodeTag(p) {
254
- p.eat('</', PN, { path: 'openToken', startSpan: 'Tag', balanced: '>' });
255
- p.eat('>', PN, { path: 'closeToken', endSpan: 'Tag', balancer: true });
246
+ p.eat('</', PN, { path: 'openToken' });
247
+ p.eat('>', PN, { path: 'closeToken' });
248
+ }
249
+
250
+ Expression(p) {
251
+ p.eatProduction('BoundNode');
252
+
253
+ p.eatMatchTrivia('_');
254
+
255
+ if (p.match('^^^')) {
256
+ return { shift: 'ShiftExpression' };
257
+ }
258
+ }
259
+
260
+ BoundNode(p) {
261
+ while (p.match(':')) {
262
+ p.eatProduction('BindingTag', { path: 'bindingTags' });
263
+ p.eatMatchTrivia(_);
264
+ }
265
+ p.eatProduction('Node', { path: 'node' });
266
+ }
267
+
268
+ ShiftExpression(p) {
269
+ p.eatProduction('BoundNode', { path: 'original' });
270
+ p.eatMatchTrivia(_);
271
+ p.eatProduction('ShiftTag', { path: 'sigilTag' });
272
+ p.eatMatchTrivia(_);
273
+ p.eatProduction('TreeNode', { path: 'value' });
256
274
  }
257
275
 
258
- // @Node
259
276
  BindingTag(p) {
260
- p.eat(':', PN, { path: 'openToken', startSpan: 'Tag', balanced: ':' });
261
- if (!p.match(':')) {
262
- p.eatProduction('IdentifierPath');
277
+ p.eat(':', PN, { path: 'openToken' });
278
+
279
+ p.eatMatchTrivia(_);
280
+ let first = true;
281
+ while (!p.match(':') && (first || p.match('/'))) {
282
+ if (!first) {
283
+ p.eat('/', PN, { path: '#separatorTokens' });
284
+ }
285
+ p.eatProduction('BindingSegment', { path: 'segments[]' });
286
+ p.eatMatchTrivia(_);
287
+ first = false;
288
+ }
289
+ p.eat(':', PN, { path: 'closeToken' });
290
+ }
291
+
292
+ BindingSegment(p) {
293
+ p.eatMatchTrivia(_);
294
+ if (p.match('..')) {
295
+ p.eat('..', PN, { path: 'path' });
296
+ } else {
297
+ p.eatProduction('Identifier', { path: 'path' });
263
298
  }
264
- p.eat(':', PN, { path: 'closeToken', endSpan: 'Tag', balancer: true });
299
+ p.eatMatchTrivia(_);
265
300
  }
266
301
 
267
302
  IdentifierPath(p) {
268
- p.eatProduction('Identifier', { path: 'segments[]' });
269
- while (p.match('.')) {
270
- p.eat('.', PN, { path: 'separatorTokens[]' });
303
+ let first = true;
304
+ while (first || p.match('.')) {
305
+ if (!first) {
306
+ p.eat('.', PN, { path: '#separatorTokens' });
307
+ }
308
+
271
309
  p.eatProduction('Identifier', { path: 'segments[]' });
310
+ first = false;
272
311
  }
273
312
  }
274
313
 
275
- // @Node
276
314
  Identifier(p) {
277
315
  let res, q;
278
316
  q = p.match('`');
279
- if (q) p.eat('`', PN, { path: 'openToken', balanced: '`' });
317
+ if (q) p.eat('`', PN, { path: 'openToken' });
280
318
 
281
- p.eatProduction('IdentifierContent', { path: 'content', span: 'Identifier' }, { quoted: !!q });
319
+ p.eatProduction('IdentifierContent', { path: 'content' }, { quoted: !!q });
282
320
 
283
- if (q) p.eat('`', PN, { path: 'closeToken', balancer: true });
321
+ if (q) p.eat('`', PN, { path: 'closeToken' });
284
322
  }
285
323
 
286
- // @Node
287
324
  IdentifierContent(p, props) {
288
325
  let { quoted = false } = props || {};
289
326
 
@@ -301,19 +338,37 @@ export const grammar = class CSTMLMiniparserGrammar {
301
338
  } while (lit || esc);
302
339
  }
303
340
 
304
- // @Cover
305
341
  Tag(p) {
306
- if (p.match(/['"]/y)) {
342
+ p.eatMatchTrivia(_);
343
+ if (p.match('{')) {
344
+ p.eatProduction('AttributeDefinition');
345
+ } else if (p.match('null')) {
346
+ p.eatProduction('NullTag');
347
+ } else if (p.match(/[.#@_a-zA-Z\u0060\u{80}-\u{10ffff}]/uy)) {
348
+ p.eatProduction('ReferenceTag');
349
+ } else if (p.match(':')) {
350
+ p.eatProduction('BindingTag');
351
+ } else if (p.match('<!')) {
352
+ p.eatProduction('DoctypeTag');
353
+ } else if (p.match('<//>')) {
354
+ p.eatProduction('GapTag');
355
+ } else if (p.match('^^^')) {
356
+ p.eatProduction('ShiftTag');
357
+ } else if (p.match('</')) {
358
+ p.eatProduction('CloseNodeTag');
359
+ } else if (p.match('<')) {
360
+ p.eatProduction('OpenNodeTag');
361
+ } else if (p.match(/['"]/y)) {
307
362
  p.eatProduction('LiteralTag');
308
363
  } else {
309
364
  throw new Error();
310
365
  }
366
+ p.eatMatchTrivia(_);
311
367
  }
312
368
 
313
- // @Node
314
369
  ReferenceTag(p) {
315
370
  let type;
316
- if ((type = p.match(/[.#@_]/y))) {
371
+ if ((type = p.match(/\.\.|[.#@_]/y))) {
317
372
  p.eat(type, PN, { path: 'type' });
318
373
  }
319
374
 
@@ -322,16 +377,22 @@ export const grammar = class CSTMLMiniparserGrammar {
322
377
  }
323
378
  p.eatMatchTrivia(_);
324
379
 
325
- if (p.match(/[+$]/y)) {
326
- p.eatProduction('ReferenceFlags', { path: 'flags' });
327
- p.eatMatchTrivia(_);
328
- }
380
+ p.eatProduction('ReferenceFlags', { path: 'flags' });
381
+ p.eatMatchTrivia(_);
329
382
  p.eat(':', PN, { path: 'mapToken' });
330
383
  }
331
384
 
332
- // @Node
333
385
  ReferenceFlags(p) {
386
+ p.eatMatch('[]', PN, { path: 'arrayToken' });
334
387
  p.eatMatch('+', PN, { path: 'expressionToken' });
335
- p.eatMatch('$', PN, { path: 'hasGapToken' });
388
+ let i = p.eatMatch('*', PN, { path: 'intrinsicToken' });
389
+ let g = p.eatMatch('$', PN, { path: 'hasGapToken' });
390
+ if (i && g) p.fail();
391
+ }
392
+
393
+ ShiftTag(p) {
394
+ p.eat('^^^', PN, { path: 'sigilToken' });
336
395
  }
337
396
  };
397
+
398
+ export default { name, canonicalURL, dependencies, covers, grammar };
@@ -1,11 +1,10 @@
1
- import * as sym from '@bablr/agast-vm-helpers/symbols';
2
- import * as Spamex from './spamex.js';
3
- import * as CSTML from './cstml.js';
4
- import * as Regex from './regex.js';
5
- import * as BaseJSON from './json.js';
1
+ import Spamex from './spamex.js';
2
+ import CSTML from './cstml.js';
3
+ import Regex from './regex.js';
4
+ import BaseJSON from './json.js';
6
5
 
7
6
  const _ = /\s+/y;
8
- const PN = 'Punctuator';
7
+ const PN = null;
9
8
  const ID = 'Identifier';
10
9
  const KW = 'Keyword';
11
10
 
@@ -31,7 +30,7 @@ const JSON = {
31
30
  export const dependencies = { Spamex, CSTML, Regex, JSON };
32
31
 
33
32
  export const covers = new Map([
34
- [sym.node, new Set(['Call', 'Punctuator'])],
33
+ [Symbol.for('@bablr/node'), new Set(['Call'])],
35
34
  [
36
35
  'Expression',
37
36
  new Set([
@@ -42,7 +41,8 @@ export const covers = new Map([
42
41
  'CSTML:GapTag',
43
42
  'RegexString',
44
43
  'SpamexString',
45
- 'CSTMLString',
44
+ 'TagString',
45
+ 'NodeString',
46
46
  'Boolean',
47
47
  'Null',
48
48
  ]),
@@ -50,12 +50,11 @@ export const covers = new Map([
50
50
  ]);
51
51
 
52
52
  export const grammar = class InstructionMiniparserGrammar {
53
- // @Node
54
53
  Call(p) {
55
54
  p.eat(/[a-zA-Z]+/y, ID, { path: 'verb' });
56
55
  p.eatMatchTrivia(_);
57
56
 
58
- p.eat('(', PN, { path: 'openToken', balanced: ')' });
57
+ p.eat('(', PN, { path: 'openToken' });
59
58
 
60
59
  let sep = p.eatMatchTrivia(_);
61
60
 
@@ -66,40 +65,45 @@ export const grammar = class InstructionMiniparserGrammar {
66
65
  i++;
67
66
  }
68
67
 
69
- p.eat(')', PN, { path: 'closeToken', balancer: true });
68
+ p.eat(')', PN, { path: 'closeToken' });
70
69
  }
71
70
 
72
- // @Node
73
71
  SpamexString(p) {
74
72
  p.eat('m', KW, { path: 'sigilToken' });
75
73
  let quot = p.match(/['"`]/);
76
- p.eat(quot, PN, { path: 'openToken', balanced: quot });
74
+ p.eat(quot, PN, { path: 'openToken' });
77
75
  p.eatProduction('Spamex:Matcher', { path: 'content' });
78
76
 
79
- p.eat(quot, PN, { path: 'closeToken', balancer: true });
77
+ p.eat(quot, PN, { path: 'closeToken' });
80
78
  }
81
79
 
82
- // @Node
83
- CSTMLString(p) {
80
+ TagString(p) {
84
81
  p.eat('t', KW, { path: 'sigilToken' });
85
82
  let quot = p.match(/['"`]/);
86
- p.eat(quot, PN, { path: 'openToken', balanced: quot });
83
+ p.eat(quot, PN, { path: 'openToken' });
87
84
  p.eatProduction('CSTML:Tag', { path: 'content' });
88
85
 
89
- p.eat(quot, PN, { path: 'closeToken', balancer: true });
86
+ p.eat(quot, PN, { path: 'closeToken' });
87
+ }
88
+
89
+ NodeString(p) {
90
+ p.eat('n', KW, { path: 'sigilToken' });
91
+ let quot = p.match(/['"`]/);
92
+ p.eat(quot, PN, { path: 'openToken' });
93
+ p.eatProduction('CSTML:Node', { path: 'content' });
94
+
95
+ p.eat(quot, PN, { path: 'closeToken' });
90
96
  }
91
97
 
92
- // @Node
93
98
  RegexString(p) {
94
99
  p.eat('re', KW, { path: 'sigilToken' });
95
100
  let quot = p.match(/['"`]/);
96
- p.eat(quot, PN, { path: 'openToken', balanced: quot });
101
+ p.eat(quot, PN, { path: 'openToken' });
97
102
  p.eatProduction('Regex:Pattern', { path: 'content' });
98
103
 
99
- p.eat(quot, PN, { path: 'closeToken', balancer: true });
104
+ p.eat(quot, PN, { path: 'closeToken' });
100
105
  }
101
106
 
102
- // @Cover
103
107
  Expression(p) {
104
108
  if (p.match('[')) {
105
109
  p.eatProduction('JSON:Array');
@@ -111,6 +115,10 @@ export const grammar = class InstructionMiniparserGrammar {
111
115
  p.eatProduction('RegexString');
112
116
  } else if (p.match(/m['"`]/y)) {
113
117
  p.eatProduction('SpamexString');
118
+ } else if (p.match(/t['"`]/y)) {
119
+ p.eatProduction('TagString');
120
+ } else if (p.match(/n['"`]/y)) {
121
+ p.eatProduction('NodeString');
114
122
  } else if (p.match(/true|false/y)) {
115
123
  p.eatProduction('JSON:Boolean');
116
124
  } else if (p.match('null')) {
@@ -118,3 +126,5 @@ export const grammar = class InstructionMiniparserGrammar {
118
126
  }
119
127
  }
120
128
  };
129
+
130
+ export default { name, canonicalURL, dependencies, covers, grammar };