@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.
@@ -1,11 +1,7 @@
1
1
  import objectEntries from 'iter-tools-es/methods/object-entries';
2
- import * as sym from '@bablr/agast-vm-helpers/symbols';
3
- import * as Spamex from './spamex.js';
4
- import * as CSTML from './cstml.js';
5
- import * as Regex from './regex.js';
6
2
 
7
3
  const _ = /\s+/y;
8
- const PN = 'Punctuator';
4
+ const PN = null;
9
5
  const KW = 'Keyword';
10
6
  const LIT = 'Identifier';
11
7
 
@@ -13,13 +9,12 @@ export const name = 'JSON';
13
9
 
14
10
  export const canonicalURL = 'https://bablr.org/languages/core/en/cstml-json';
15
11
 
16
- export const dependencies = { Spamex, CSTML, Regex };
12
+ export const dependencies = {};
17
13
 
18
14
  export const covers = new Map([
19
15
  [
20
- sym.node,
16
+ Symbol.for('@bablr/node'),
21
17
  new Set([
22
- 'Punctuator',
23
18
  'Property',
24
19
  'Object',
25
20
  'Array',
@@ -84,7 +79,6 @@ export const cookEscape = (escape, span) => {
84
79
  };
85
80
 
86
81
  export const grammar = class JSONMiniparserGrammar {
87
- // @Cover
88
82
  Expression(p) {
89
83
  if (p.match('[')) {
90
84
  p.eatProduction('Array');
@@ -103,9 +97,8 @@ export const grammar = class JSONMiniparserGrammar {
103
97
  }
104
98
  }
105
99
 
106
- // @Node
107
100
  Object(p) {
108
- p.eat('{', PN, { path: 'openToken', balanced: '}' });
101
+ p.eat('{', PN, { path: 'openToken' });
109
102
 
110
103
  p.eatMatchTrivia(_);
111
104
 
@@ -121,10 +114,9 @@ export const grammar = class JSONMiniparserGrammar {
121
114
 
122
115
  p.eatMatchTrivia(_);
123
116
 
124
- p.eat('}', PN, { path: 'closeToken', balancer: true });
117
+ p.eat('}', PN, { path: 'closeToken' });
125
118
  }
126
119
 
127
- // @Node
128
120
  Property(p) {
129
121
  if (p.match(/['"]/y)) {
130
122
  p.eatProduction('String', { path: 'key' });
@@ -137,9 +129,8 @@ export const grammar = class JSONMiniparserGrammar {
137
129
  p.eatProduction('Expression', { path: 'value' });
138
130
  }
139
131
 
140
- // @Node
141
132
  Array(p) {
142
- p.eat('[', PN, { path: 'openToken', balanced: ']' });
133
+ p.eat('[', PN, { path: 'openToken' });
143
134
 
144
135
  p.eatMatchTrivia(_);
145
136
 
@@ -154,15 +145,13 @@ export const grammar = class JSONMiniparserGrammar {
154
145
  first = false;
155
146
  }
156
147
 
157
- p.eat(']', PN, { path: 'closeToken', balancer: true });
148
+ p.eat(']', PN, { path: 'closeToken' });
158
149
  }
159
150
 
160
- // @Node
161
151
  Boolean(p) {
162
152
  p.eat(/true|false/y, KW, { path: 'sigilToken' });
163
153
  }
164
154
 
165
- // @Node
166
155
  Null(p) {
167
156
  p.eat('null', KW, { path: 'sigilToken' });
168
157
  }
@@ -183,29 +172,24 @@ export const grammar = class JSONMiniparserGrammar {
183
172
  }
184
173
  }
185
174
 
186
- // @Node
187
175
  Integer(p) {
188
- p.eatMatch('-', 'Punctuator', { path: 'negative' });
176
+ p.eatMatch('-', PN, { path: 'negative' });
189
177
  p.eatProduction('Digits', { path: 'digits[]' });
190
178
  }
191
179
 
192
- // @Node
193
180
  UnsignedInteger(p) {
194
181
  p.eatProduction('Digits', { path: 'digits[]' });
195
182
  }
196
183
 
197
- // @Node
198
184
  Infinity(p) {
199
- p.eatMatch(/[+-]/, 'Punctuator', { path: 'sign' });
185
+ p.eatMatch(/[+-]/y, PN, { path: 'sign' });
200
186
  p.eat('Infinity', 'Keyword', { path: 'sigilToken' });
201
187
  }
202
188
 
203
- // @Node
204
189
  NotANumber(p) {
205
190
  p.eat('NaN', 'Keyword', { path: 'sigilToken' });
206
191
  }
207
192
 
208
- // @Node
209
193
  Undefined(p) {
210
194
  p.eat('undefined', 'Keyword', { path: 'sigilToken' });
211
195
  }
@@ -216,17 +200,14 @@ export const grammar = class JSONMiniparserGrammar {
216
200
  }
217
201
  }
218
202
 
219
- // @Node
220
203
  Digit(p) {
221
204
  p.eatLiteral(/\d/y);
222
205
  }
223
206
 
224
- // @Node
225
207
  Identifier(p) {
226
208
  p.eat(/[a-zA-Z]+/y, LIT, { path: 'content' });
227
209
  }
228
210
 
229
- // @Node
230
211
  String(p) {
231
212
  const q = p.match(/['"]/y) || '"';
232
213
 
@@ -239,7 +220,6 @@ export const grammar = class JSONMiniparserGrammar {
239
220
  p.eat(q, PN, { path: 'closeToken', endSpan: span, balancer: true });
240
221
  }
241
222
 
242
- // @Node
243
223
  StringContent(p) {
244
224
  let esc, lit;
245
225
  let i = 0;
@@ -259,3 +239,5 @@ export const grammar = class JSONMiniparserGrammar {
259
239
  }
260
240
  }
261
241
  };
242
+
243
+ export default { name, canonicalURL, dependencies, covers, grammar, cookEscape };
@@ -1,4 +1,3 @@
1
- import * as sym from '@bablr/agast-vm-helpers/symbols';
2
1
  import when from 'iter-tools-es/methods/when';
3
2
  import { escapables } from './json.js';
4
3
 
@@ -10,7 +9,7 @@ export const dependencies = {};
10
9
 
11
10
  export const covers = new Map([
12
11
  [
13
- sym.node,
12
+ Symbol.for('@bablr/node'),
14
13
  new Set([
15
14
  'RegExpLiteral',
16
15
  'Flags',
@@ -29,7 +28,6 @@ export const covers = new Map([
29
28
  'SpaceCharacterSet',
30
29
  'DigitCharacterSet',
31
30
  'Quantifier',
32
- 'Punctuator',
33
31
  'Keyword',
34
32
  'Escape',
35
33
  'Number',
@@ -82,7 +80,7 @@ const flags = {
82
80
  sticky: 'y',
83
81
  };
84
82
 
85
- const PN = 'Punctuator';
83
+ const PN = null;
86
84
  const KW = 'Keyword';
87
85
  const ESC = 'Escape';
88
86
 
@@ -138,7 +136,6 @@ export const cookEscape = (escape, span) => {
138
136
  };
139
137
 
140
138
  export const grammar = class RegexMiniparserGrammar {
141
- // @Node
142
139
  Pattern(p) {
143
140
  p.eat('/', PN, { path: 'openToken', balanced: '/' });
144
141
  p.eatProduction('Alternatives', { path: 'alternatives[]' });
@@ -149,7 +146,6 @@ export const grammar = class RegexMiniparserGrammar {
149
146
  }
150
147
  }
151
148
 
152
- // @Node
153
149
  Flags(p) {
154
150
  const flagsStr = p.match(/[gimsuy]+/y) || '';
155
151
 
@@ -171,10 +167,9 @@ export const grammar = class RegexMiniparserGrammar {
171
167
  Alternatives(p) {
172
168
  do {
173
169
  p.eatProduction('Alternative');
174
- } while (p.eatMatch('|', PN, { path: 'separatorTokens[]' }));
170
+ } while (p.eatMatch('|', PN, { path: '#separatorTokens' }));
175
171
  }
176
172
 
177
- // @Node
178
173
  Alternative(p) {
179
174
  p.eatProduction('Elements', { path: 'elements[]+' });
180
175
  }
@@ -185,7 +180,6 @@ export const grammar = class RegexMiniparserGrammar {
185
180
  }
186
181
  }
187
182
 
188
- // @Cover
189
183
  Element(p) {
190
184
  if (p.match('[')) {
191
185
  p.eatProduction('CharacterClass');
@@ -210,14 +204,12 @@ export const grammar = class RegexMiniparserGrammar {
210
204
  }
211
205
  }
212
206
 
213
- // @Node
214
207
  Group(p) {
215
208
  p.eat('(?:', PN, { path: 'openToken', balanced: ')' });
216
209
  p.eatProduction('Alternatives', { path: 'alternatives[]' });
217
210
  p.eat(')', PN, { path: 'closeToken', balancer: true });
218
211
  }
219
212
 
220
- // @Node
221
213
  CapturingGroup(p) {
222
214
  p.eat('(', PN, { path: 'openToken', balanced: ')' });
223
215
  p.eatProduction('Alternatives', { path: 'alternatives[]' });
@@ -234,20 +226,14 @@ export const grammar = class RegexMiniparserGrammar {
234
226
  }
235
227
  }
236
228
 
237
- // @CoveredBy('Assertion')
238
- // @Node
239
229
  StartOfInputAssertion(p) {
240
230
  p.eat('^', KW, { path: 'sigilToken' });
241
231
  }
242
232
 
243
- // @CoveredBy('Assertion')
244
- // @Node
245
233
  EndOfInputAssertion(p) {
246
234
  p.eat('$', KW, { path: 'sigilToken' });
247
235
  }
248
236
 
249
- // @CoveredBy('Assertion')
250
- // @Node
251
237
  WordBoundaryAssertion(p) {
252
238
  let attrs;
253
239
  if (p.eatMatch('\\', ESC, { path: 'escapeToken' })) {
@@ -259,7 +245,6 @@ export const grammar = class RegexMiniparserGrammar {
259
245
  return { attrs };
260
246
  }
261
247
 
262
- // @Node
263
248
  Character(p) {
264
249
  const specialPattern = getSpecialPattern(p.span);
265
250
 
@@ -287,14 +272,13 @@ export const grammar = class RegexMiniparserGrammar {
287
272
  }
288
273
  }
289
274
 
290
- // @Node
291
275
  CharacterClass(p) {
292
276
  p.eat('[', PN, { path: 'openToken', balanced: ']', startSpan: 'CharacterClass' });
293
277
 
294
278
  const negate = !!p.eatMatch('^', KW, { path: 'negateToken', boolean: true });
295
279
 
296
280
  let first = !negate;
297
- while (p.match(/./sy)) {
281
+ while (p.match(/./sy) || p.atExpression) {
298
282
  p.eatProduction('CharacterClassElement', { path: 'elements[]' }, { first });
299
283
  first = false;
300
284
  }
@@ -304,7 +288,6 @@ export const grammar = class RegexMiniparserGrammar {
304
288
  return { attrs: { negate } };
305
289
  }
306
290
 
307
- // @Cover
308
291
  CharacterClassElement(p, { first }) {
309
292
  if (p.match(/(.|\\(u(\{[0-9a-fA-F]{1,6}\}|[0-9a-fA-F]{4})|x[0-9a-fA-F]{2}|\w))-[^\]\n]/y)) {
310
293
  p.eatProduction('CharacterClassRange', undefined, { first });
@@ -317,13 +300,11 @@ export const grammar = class RegexMiniparserGrammar {
317
300
  }
318
301
  }
319
302
 
320
- // @Node
321
303
  Gap(p) {
322
304
  p.eat('\\', PN, { path: 'escapeToken' });
323
305
  p.eat('g', KW, { path: 'value' });
324
306
  }
325
307
 
326
- // @Node
327
308
  CharacterClassRange(p, { first }) {
328
309
  p.eatProduction('Character', {
329
310
  path: 'min',
@@ -353,14 +334,10 @@ export const grammar = class RegexMiniparserGrammar {
353
334
  return { attrs };
354
335
  }
355
336
 
356
- // @CoveredBy('CharacterSet')
357
- // @Node
358
337
  AnyCharacterSet(p) {
359
338
  p.eat('.', KW, { path: 'sigilToken' });
360
339
  }
361
340
 
362
- // @CoveredBy('CharacterSet')
363
- // @Node
364
341
  WordCharacterSet(p) {
365
342
  p.eat('\\', PN, { path: 'escapeToken' });
366
343
 
@@ -375,8 +352,6 @@ export const grammar = class RegexMiniparserGrammar {
375
352
  return { attrs };
376
353
  }
377
354
 
378
- // @CoveredBy('CharacterSet')
379
- // @Node
380
355
  SpaceCharacterSet(p) {
381
356
  p.eat('\\', PN, { path: 'escapeToken' });
382
357
 
@@ -391,8 +366,6 @@ export const grammar = class RegexMiniparserGrammar {
391
366
  return { attrs };
392
367
  }
393
368
 
394
- // @CoveredBy('CharacterSet')
395
- // @Node
396
369
  DigitCharacterSet(p) {
397
370
  p.eat('\\', PN, { path: 'escapeToken' });
398
371
 
@@ -407,7 +380,6 @@ export const grammar = class RegexMiniparserGrammar {
407
380
  return { attrs };
408
381
  }
409
382
 
410
- // @Node
411
383
  Quantifier(p) {
412
384
  p.eatHeldProduction('Element', { path: 'element+' });
413
385
 
@@ -441,3 +413,5 @@ export const grammar = class RegexMiniparserGrammar {
441
413
  return { attrs };
442
414
  }
443
415
  };
416
+
417
+ export default { name, canonicalURL, dependencies, covers, grammar, cookEscape };
@@ -1,12 +1,10 @@
1
- import * as sym from '@bablr/agast-vm-helpers/symbols';
2
- import * as Regex from './regex.js';
3
- import * as CSTML from './cstml.js';
4
- import * as JSON from './json.js';
1
+ import Regex from './regex.js';
2
+ import CSTML from './cstml.js';
3
+ import JSON from './json.js';
5
4
  import { get } from '@bablr/agast-helpers/path';
6
5
 
7
6
  const _ = /\s+/y;
8
- const PN = 'Punctuator';
9
- const ID = 'Identifier';
7
+ const PN = null;
10
8
 
11
9
  export const name = 'Spamex';
12
10
 
@@ -16,85 +14,56 @@ export const dependencies = { CSTML, JSON, Regex };
16
14
 
17
15
  export const covers = new Map([
18
16
  [
19
- sym.node,
17
+ Symbol.for('@bablr/node'),
20
18
  new Set([
21
19
  'CSTML:Identifier',
22
20
  'PropertyMatcher',
23
21
  'JSON:String',
24
22
  'Regex:Pattern',
25
- 'BasicNodeMatcher',
23
+ 'TreeNodeMatcher',
26
24
  'GapNodeMatcher',
27
- 'ArrayNodeMatcher',
28
25
  'NullNodeMatcher',
29
26
  'ReferenceMatcher',
27
+ 'BoundNodeMatcher',
30
28
  'BindingMatcher',
31
- 'OpenNodeMatcher',
32
- 'CloseNodeMatcher',
29
+ 'TreeNodeMatcherOpen',
30
+ 'TreeNodeMatcherClose',
33
31
  'Literal',
34
32
  'CSTML:NodeFlags',
35
33
  ]),
36
34
  ],
37
35
  ['AttributeValue', new Set(['JSON:String', 'CSTML:Number'])],
38
- ['Matcher', new Set(['PropertyMatcher', 'JSON:String', 'Regex:Pattern'])],
39
- [
40
- 'NodeMatcher',
41
- new Set(['BasicNodeMatcher', 'GapNodeMatcher', 'ArrayNodeMatcher', 'NullNodeMatcher']),
42
- ],
36
+ ['Matcher', new Set(['BoundNodeMatcher'])],
37
+ ['NodeMatcher', new Set(['TreeNodeMatcher', 'GapNodeMatcher', 'NullNodeMatcher'])],
43
38
  ['StringMatcher', new Set(['JSON:String', 'Regex:Pattern'])],
44
39
  ]);
45
40
 
46
41
  export const grammar = class SpamexMiniparserGrammar {
47
- // @Cover
48
42
  Matcher(p) {
49
- if (p.match(/[a-zA-Z.#@<:]/y)) {
50
- p.eatProduction('PropertyMatcher');
51
- } else if (p.match(/['"/]/y)) {
52
- p.eatProduction('StringMatcher');
53
- } else {
54
- throw new Error(`Unexpected character ${p.chr}`);
55
- }
43
+ p.eatProduction('BoundNodeMatcher');
56
44
  }
57
45
 
58
- // @Node
59
- // @CoveredBy('NodeMatcher')
60
46
  GapNodeMatcher(p) {
61
47
  p.eat('<//>', PN, { path: 'sigilToken' });
62
48
  }
63
49
 
64
- // @Node
65
- // @CoveredBy('NodeMatcher')
66
- ArrayNodeMatcher(p) {
67
- p.eat('[]', PN, { path: 'sigilToken' });
68
- }
69
-
70
- // @Node
71
- // @CoveredBy('NodeMatcher')
72
50
  NullNodeMatcher(p) {
73
51
  p.eat('null', PN, { path: 'sigilToken' });
74
52
  }
75
53
 
76
- // @Node
77
- // @CoveredBy('Matcher')
78
54
  PropertyMatcher(p) {
79
- if (p.match(/[a-zA-Z.#@]/y)) {
55
+ if (p.match(/[a-zA-Z.#@_]/y) || p.atExpression || null) {
80
56
  p.eatProduction('ReferenceMatcher', { path: 'refMatcher' });
81
57
  }
82
58
 
83
59
  p.eatMatchTrivia(_);
84
60
 
85
- if (p.match(':')) {
86
- p.eatProduction('BindingMatcher', { path: 'bindingMatcher' });
87
- }
88
-
89
- p.eatMatchTrivia(_);
90
-
91
- p.eatProduction('NodeMatcher', { path: 'nodeMatcher' });
61
+ p.eatProduction('BoundNodeMatcher', { path: 'valueMatcher' });
92
62
  }
93
63
 
94
- // @Node
95
64
  ReferenceMatcher(p) {
96
65
  let name, type;
97
- if ((type = p.match(/[.#@]/y))) {
66
+ if ((type = p.match(/\.\.|[.#@_]/y))) {
98
67
  p.eat(type, PN, { path: 'type' });
99
68
  }
100
69
 
@@ -102,50 +71,64 @@ export const grammar = class SpamexMiniparserGrammar {
102
71
  name = p.eatProduction('CSTML:Identifier', { path: 'name' });
103
72
  }
104
73
 
105
- let open =
106
- (name || type) &&
107
- p.eatMatch('[', PN, { path: 'openIndexToken', startSpan: 'Index', balanced: ']' });
108
-
109
- if (open) {
110
- p.eatMatchTrivia(_);
111
- p.eat(']', PN, { path: 'closeIndexToken', endSpan: 'Index', balancer: true });
112
- }
113
-
114
74
  p.eatMatchTrivia(_);
115
- if (p.match(/[+$]/y)) {
75
+ if (!['#', '@'].includes(type)) {
116
76
  p.eatProduction('CSTML:ReferenceFlags', { path: 'flags' });
117
77
  p.eatMatchTrivia(_);
118
78
  }
119
79
  p.eat(':', PN, { path: 'mapToken' });
120
80
  }
121
81
 
122
- // @Node
82
+ BoundNodeMatcher(p) {
83
+ while (p.match(':')) {
84
+ p.eatProduction('BindingMatcher', { path: 'bindingMatchers[]' });
85
+ p.eatMatchTrivia(_);
86
+ }
87
+
88
+ p.eatProduction('NodeMatcher', { path: 'nodeMatcher', noInterpolate: true });
89
+ }
90
+
123
91
  BindingMatcher(p) {
124
92
  p.eat(':', PN, { path: 'openToken' });
93
+
125
94
  p.eatMatchTrivia(_);
126
- p.eatProduction('CSTML:IdentifierPath', { path: 'languagePath' });
127
- p.eatMatchTrivia(_);
95
+ let first = true;
96
+ while (!p.match(':') && (first || p.match('/'))) {
97
+ if (!first) {
98
+ p.eat('/', PN, { path: '#separatorTokens' });
99
+ }
100
+ p.eatProduction('CSTML:BindingSegment', { path: 'segments[]' });
101
+ p.eatMatchTrivia(_);
102
+ first = false;
103
+ }
128
104
  p.eat(':', PN, { path: 'closeToken' });
129
105
  }
130
106
 
131
107
  NodeMatcher(p) {
132
- if (p.match('<//>')) {
133
- p.eatProduction('GapNodeMatcher');
134
- } else if (p.match('<')) {
135
- p.eatProduction('BasicNodeMatcher');
136
- } else if (p.match('[')) {
137
- p.eatProduction('ArrayNodeMatcher');
138
- } else if (p.match('null')) {
139
- p.eatProduction('NullNodeMatcher');
140
- } else {
141
- p.fail();
108
+ let chrs = p.match(/<\/\/?>|<|null/y);
109
+ switch (chrs) {
110
+ case '<//>':
111
+ p.eatProduction('GapNodeMatcher');
112
+ break;
113
+ case '</>':
114
+ p.fail();
115
+ break;
116
+ case 'null':
117
+ p.eatProduction('NullNodeMatcher');
118
+ break;
119
+ default:
120
+ p.eatProduction('TreeNodeMatcher', { noInterpolate: true });
121
+ break;
142
122
  }
143
123
  }
144
124
 
145
- // @Node
146
- // @CoveredBy('NodeMatcher')
147
- BasicNodeMatcher(p) {
148
- let open = p.eatProduction('OpenNodeMatcher', { path: 'open' });
125
+ TreeNodeMatcher(p) {
126
+ if (p.match(/[a-zA-Z.#@]/y) || p.atExpression) {
127
+ p.eatProduction('PropertyMatcher', { path: 'children[]', noInterpolate: true });
128
+ return;
129
+ }
130
+
131
+ let open = p.eatProduction('TreeNodeMatcherOpen', { path: 'open' });
149
132
 
150
133
  if (!get('selfClosingToken', open)) {
151
134
  p.eatMatchTrivia(_);
@@ -160,24 +143,31 @@ export const grammar = class SpamexMiniparserGrammar {
160
143
  // }
161
144
  }
162
145
 
163
- p.eatProduction('CloseNodeMatcher', { path: 'close' });
146
+ p.eatProduction('TreeNodeMatcherClose', { path: 'close' });
164
147
  }
165
148
  }
166
149
 
167
- // @Node
168
- OpenNodeMatcher(p) {
169
- p.eat('<', PN, { path: 'openToken', startSpan: 'Tag', balanced: '>' });
150
+ TreeNodeMatcherOpen(p) {
151
+ if (p.match(/['"/]/y)) {
152
+ p.eatProduction('CSTML:NodeFlags', { path: 'flags', token: true });
153
+ p.eatProduction('StringMatcher', { path: 'literalValue' });
154
+
155
+ return { attrs: { selfClosing: true } };
156
+ }
157
+
158
+ p.eat('<', PN, { path: 'openToken' });
170
159
 
171
160
  if (!p.atExpression) {
172
161
  p.eatProduction('CSTML:NodeFlags', { path: 'flags' });
173
162
  }
174
163
 
164
+ let type;
165
+ if ((type = p.match(/[?]|__?/y))) {
166
+ p.eat(type, PN, { path: 'type' });
167
+ }
168
+
175
169
  if (p.match(/[a-zA-Z]/y) || p.atExpression) {
176
- p.eatProduction('CSTML:Identifier', { path: 'type' });
177
- } else if (p.match('?')) {
178
- p.eat('?', PN, { path: 'type' });
179
- } else if (p.match('_')) {
180
- p.eat('_', PN, { path: 'type' });
170
+ p.eatProduction('CSTML:Identifier', { path: 'name' });
181
171
  }
182
172
 
183
173
  let sp = p.eatMatchTrivia(_);
@@ -194,16 +184,17 @@ export const grammar = class SpamexMiniparserGrammar {
194
184
  }
195
185
 
196
186
  p.eatMatchTrivia(_);
197
- p.eatMatch('/', PN, { path: 'selfClosingToken' });
198
- p.eat('>', PN, { path: 'closeToken', endSpan: 'Tag', balancer: true });
187
+ let sc = p.eatMatch('/', PN, { path: 'selfClosingToken' });
188
+ p.eat('>', PN, { path: 'closeToken' });
189
+
190
+ return { attrs: { selfClosing: !!sc } };
199
191
  }
200
192
 
201
- CloseNodeMatcher(p) {
202
- p.eat('</', PN, { path: 'openToken', startSpan: 'Tag', balanced: '>' });
203
- p.eat('>', PN, { path: 'closeToken', endSpan: 'Tag', balancer: true });
193
+ TreeNodeMatcherClose(p) {
194
+ p.eat('</', PN, { path: 'openToken' });
195
+ p.eat('>', PN, { path: 'closeToken' });
204
196
  }
205
197
 
206
- // @Cover
207
198
  StringMatcher(p) {
208
199
  if (p.match(/['"]/y)) {
209
200
  p.eatProduction('JSON:String');
@@ -212,3 +203,5 @@ export const grammar = class SpamexMiniparserGrammar {
212
203
  }
213
204
  }
214
205
  };
206
+
207
+ export default { name, canonicalURL, dependencies, covers, grammar };
package/lib/match.js CHANGED
@@ -1,7 +1,8 @@
1
- import { createNode } from '@bablr/agast-helpers/tree';
2
1
  import { Path } from './path.js';
3
2
  import { resolveDependentLanguage } from './utils.js';
4
3
  import * as sym from '@bablr/agast-vm-helpers/symbols';
4
+ import { buildOpenCoverTag, buildOpenNodeTag, nodeFlags } from '@bablr/agast-helpers/builders';
5
+ import { buildNode } from '@bablr/agast-helpers/path';
5
6
 
6
7
  export class Match {
7
8
  constructor(parent, resolvedLanguage, id, attributes, path) {
@@ -18,10 +19,10 @@ export class Match {
18
19
  }
19
20
 
20
21
  get isNode() {
21
- const { type, resolvedLanguage } = this;
22
+ const { name, resolvedLanguage } = this;
22
23
  const { covers } = resolvedLanguage;
23
24
 
24
- return covers.get(sym.node).has(type) && !covers.has(type);
25
+ return covers.get(Symbol.for('@bablr/node')).has(name) && !covers.has(name);
25
26
  }
26
27
 
27
28
  get language() {
@@ -32,6 +33,10 @@ export class Match {
32
33
  return this.id.type;
33
34
  }
34
35
 
36
+ get name() {
37
+ return this.id.name;
38
+ }
39
+
35
40
  get attrs() {
36
41
  return this.attributes;
37
42
  }
@@ -39,20 +44,19 @@ export class Match {
39
44
  static from(language, id, attrs = {}) {
40
45
  const resolvedLanguage = resolveDependentLanguage(language, id.language);
41
46
  const { covers } = resolvedLanguage;
42
- const { type } = id;
43
- const isCover = covers.has(type);
44
- const isNode = covers.get(sym.node).has(type);
47
+ const { name } = id;
48
+ const isCover = covers.has(name);
49
+ const isNode = covers.get(Symbol.for('@bablr/node')).has(name);
45
50
 
46
51
  if (!isNode && !isCover) {
47
- throw new Error(`Top {type: ${type}} must be a node or fragment`);
52
+ throw new Error(`Top {type: ${name}} must be a node or fragment`);
48
53
  }
49
54
 
50
55
  const path = Path.from(id, attrs);
51
56
 
52
- if (isNode && !isCover) {
53
- path.node = createNode();
54
- path.node.type = Symbol.for(type);
55
- }
57
+ path.node = buildNode(
58
+ isCover ? buildOpenCoverTag(nodeFlags, name) : buildOpenNodeTag(nodeFlags, name),
59
+ );
56
60
 
57
61
  return new Match(null, resolvedLanguage, id, attrs, path);
58
62
  }
@@ -60,9 +64,9 @@ export class Match {
60
64
  generate(id, attrs) {
61
65
  const resolvedLanguage = resolveDependentLanguage(this.resolvedLanguage, id.language);
62
66
  const { covers } = resolvedLanguage;
63
- const { type } = id;
64
- const isCover = covers.has(type);
65
- const isNode = covers.get(sym.node).has(type) && !isCover;
67
+ const { name } = id;
68
+ const isCover = covers.has(name);
69
+ const isNode = covers.get(Symbol.for('@bablr/node')).has(name) && !isCover;
66
70
 
67
71
  const baseAttrs = this.isNode ? {} : this.attrs;
68
72
 
@@ -75,8 +79,7 @@ export class Match {
75
79
  } else {
76
80
  path = path.generate(id, attrs);
77
81
  }
78
- path.node = createNode();
79
- path.node.type = Symbol.for(type);
82
+ path.node = buildNode(buildOpenNodeTag(nodeFlags, name));
80
83
  }
81
84
 
82
85
  return new Match(this, resolvedLanguage, id, { ...baseAttrs, ...attrs }, path);