@bablr/boot 0.6.0 → 0.6.2

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
@@ -220,7 +220,7 @@ const getAgASTValue = (language, miniNode) => {
220
220
  const str = buildTag(cstml, 'String');
221
221
  const num = buildTag(cstml, 'Integer');
222
222
  const cst = buildTag(cstml, 'Node');
223
- const spam = buildTag(spamex, 'Pattern');
223
+ const spam = buildTag(spamex, 'Matcher');
224
224
  const re = buildTag(regex, 'Pattern');
225
225
  const i = buildTag(instruction, 'Call');
226
226
 
@@ -7,6 +7,7 @@ const _ = /\s+/y;
7
7
  const PN = 'Punctuator';
8
8
  const ID = 'Identifier';
9
9
  const KW = 'Keyword';
10
+ const LIT = 'Literal';
10
11
 
11
12
  const name = 'CSTML';
12
13
 
@@ -66,9 +67,12 @@ const covers = buildCovers({
66
67
  'NullTag',
67
68
  'GapTag',
68
69
  'Node',
70
+ 'Fragment',
69
71
  'IdentifierPath',
70
72
  'OpenNodeTag',
71
73
  'CloseNodeTag',
74
+ 'OpenFragmentTag',
75
+ 'CloseFragmentTag',
72
76
  'Tag',
73
77
  'Number',
74
78
  'Digit',
@@ -76,10 +80,26 @@ const covers = buildCovers({
76
80
  'Content',
77
81
  'UnsignedInteger',
78
82
  'Flags',
83
+ 'Array',
84
+ 'Object',
85
+ 'Boolean',
86
+ 'Null',
87
+ 'Identifier',
88
+ 'JSONProperty',
89
+ 'JSONExpression',
79
90
  ],
80
91
  [sym.fragment]: ['Attributes'],
81
92
  Attribute: ['MappingAttribute', 'BooleanAttribute'],
82
- AttributeValue: ['String', 'Number'],
93
+ JSONExpression: [
94
+ 'Boolean',
95
+ 'Null',
96
+ 'Number',
97
+ 'String',
98
+ 'Array',
99
+ 'Object',
100
+ 'Identifier',
101
+ 'Separator',
102
+ ],
83
103
  TagType: ['Identifier', 'GlobalIdentifier'],
84
104
  Tag: ['LiteralTag', 'Trivia'],
85
105
  PropertyValue: ['GapTag', 'Node', 'NullTag'],
@@ -92,7 +112,7 @@ const grammar = class CSTMLMiniparserGrammar {
92
112
  Document(p) {
93
113
  p.eatProduction('DoctypeTag', { path: 'doctype' });
94
114
  p.eatMatchTrivia(_);
95
- p.eatProduction('Node', { path: 'tree' });
115
+ p.eatProduction('Fragment', { path: 'tree' });
96
116
  }
97
117
 
98
118
  // @Node
@@ -163,6 +183,25 @@ const grammar = class CSTMLMiniparserGrammar {
163
183
  }
164
184
  }
165
185
 
186
+ // @Node
187
+ Fragment(p) {
188
+ let open = p.eatProduction('OpenFragmentTag', { path: 'open' });
189
+
190
+ p.eatMatchTrivia(_);
191
+
192
+ if (open.properties.flags?.token) {
193
+ p.eatProduction('NodeChild', { path: 'children[]' }, { token: true });
194
+ p.eatMatchTrivia(_);
195
+ }
196
+
197
+ while (!(p.match('</') || p.done)) {
198
+ p.eatProduction('NodeChild', { path: 'children[]' });
199
+ p.eatMatchTrivia(_);
200
+ }
201
+
202
+ p.eatProduction('CloseFragmentTag', { path: 'close' });
203
+ }
204
+
166
205
  // @Node
167
206
  Property(p) {
168
207
  p.eatProduction('ReferenceTag', { path: 'reference' });
@@ -237,6 +276,27 @@ const grammar = class CSTMLMiniparserGrammar {
237
276
  p.eat('>', PN, { path: 'closeToken', endSpan: 'Tag', balancer: true });
238
277
  }
239
278
 
279
+ // @Node
280
+ OpenFragmentTag(p) {
281
+ p.eat('<', PN, { path: 'openToken', startSpan: 'Tag', balanced: '>' });
282
+
283
+ let flags = null;
284
+ if (!p.atExpression) {
285
+ flags = p.eatProduction('Flags', { path: 'flags' });
286
+ }
287
+
288
+ if (p.done) {
289
+ p.eat('>', PN, { path: 'closeToken', endSpan: 'Tag', balancer: true });
290
+ return;
291
+ }
292
+ }
293
+
294
+ // @Node
295
+ CloseFragmentTag(p) {
296
+ p.eat('</', PN, { path: 'openToken', startSpan: 'Tag', balanced: '>' });
297
+ p.eat('>', PN, { path: 'closeToken', endSpan: 'Tag', balancer: true });
298
+ }
299
+
240
300
  // @Fragment
241
301
  Attributes(p) {
242
302
  let sp = true;
@@ -275,20 +335,28 @@ const grammar = class CSTMLMiniparserGrammar {
275
335
  p.eatMatchTrivia(_);
276
336
  p.eat('=', PN, { path: 'mapToken' });
277
337
  p.eatMatchTrivia(_);
278
- p.eatProduction('AttributeValue', { path: 'value' });
338
+ p.eatProduction('JSONExpression', { path: 'value' });
279
339
  }
280
340
 
281
341
  // @Cover
282
- AttributeValue(p) {
342
+ JSONExpression(p) {
283
343
  if (p.match(/['"]/y)) {
284
344
  p.eatProduction('String');
285
345
  } else if (p.match(/[\d+-]/y)) {
286
346
  p.eatProduction('Number');
347
+ } else if (p.match('[')) {
348
+ p.eatProduction('Array');
349
+ } else if (p.match('{')) {
350
+ p.eatProduction('Object');
351
+ } else if (p.match(/true|false/y)) {
352
+ p.eatProduction('Boolean');
353
+ } else if (p.match('null')) {
354
+ p.eatProduction('Null');
287
355
  }
288
356
  }
289
357
 
290
358
  TagType(p) {
291
- if (p.match(/[a-zA-Z\.]+:/y)) {
359
+ if (p.match(/['"]|[a-zA-Z\.]+:/y)) {
292
360
  p.eatProduction('LanguageReference', { path: 'language' });
293
361
  p.eat(':', PN, { path: 'namespaceSeparatorToken' });
294
362
  p.eatProduction('Identifier', { path: 'type' });
@@ -352,10 +420,73 @@ const grammar = class CSTMLMiniparserGrammar {
352
420
  }
353
421
 
354
422
  // @Node
355
- Literal(p) {
356
- p.eatProduction('String', { path: 'value' });
423
+ Array(p) {
424
+ p.eat('[', PN, { path: 'openToken', balanced: ']' });
425
+
426
+ p.eatMatchTrivia(_);
427
+
428
+ let first = true;
429
+ let sep;
430
+ while (first || (sep && (p.match(/./y) || p.atExpression))) {
431
+ p.eatProduction('JSONExpression', { path: 'elements[]' });
432
+ if (p.match(/\s*,?/y)) {
433
+ sep = p.eatProduction('Separator', { path: 'separators[]' });
434
+ }
435
+
436
+ first = false;
437
+ }
438
+
439
+ p.eat(']', PN, { path: 'closeToken', balancer: true });
440
+ }
441
+
442
+ // @Node
443
+ Object(p) {
444
+ p.eat('{', PN, { path: 'openToken', balanced: '}' });
445
+
446
+ p.eatMatchTrivia(_);
447
+
448
+ let first = true;
449
+ let sep;
450
+ while (first || (sep && (p.match(/./y) || p.atExpression))) {
451
+ p.eatProduction('JSONProperty', { path: 'properties[]' });
452
+ if (p.match(/\s*,?/y)) {
453
+ sep = p.eatProduction('Separator', { path: 'separators[]' });
454
+ }
455
+ first = false;
456
+ }
457
+
458
+ p.eatMatchTrivia(_);
459
+
460
+ p.eat('}', PN, { path: 'closeToken', balancer: true });
461
+ }
462
+
463
+ // @Node
464
+ JSONProperty(p) {
465
+ p.eat(/[a-zA-Z]+/y, LIT, { path: 'key' });
466
+ p.eatMatchTrivia(_);
467
+ p.eat(':', PN, { path: 'mapToken' });
468
+ p.eatMatchTrivia(_);
469
+ p.eatProduction('JSONExpression', { path: 'value' });
470
+ }
471
+
472
+ // @Node
473
+ Boolean(p) {
474
+ p.eat(/true|false/y, KW, { path: 'sigilToken' });
475
+ }
476
+
477
+ // @Node
478
+ Null(p) {
479
+ p.eat('null', KW, { path: 'sigilToken' });
480
+ }
481
+
482
+ //@Node
483
+ Separator(p) {
484
+ p.eatMatchTrivia(_);
485
+ p.eatMatch(/,/y, PN, { path: 'separators[]' });
486
+ p.eatMatchTrivia(_);
357
487
  }
358
488
 
489
+ //@Node
359
490
  Number(p) {
360
491
  if (p.match(/-?\d/y)) {
361
492
  p.eatProduction('Integer');
@@ -29,6 +29,7 @@ const covers = buildCovers({
29
29
  'Boolean',
30
30
  'Null',
31
31
  'Spamex:Matcher',
32
+ 'Separator',
32
33
  ],
33
34
  });
34
35
 
@@ -75,7 +76,9 @@ const grammar = class InstructionMiniparserGrammar {
75
76
  let sep;
76
77
  while (first || (sep && (p.match(/./y) || p.atExpression))) {
77
78
  p.eatProduction('Property', { path: 'properties[]' });
78
- sep = p.eatMatchTrivia(_);
79
+ if (p.match(/\s*,?/y)) {
80
+ sep = p.eatProduction('Separator', { path: 'separators[]' });
81
+ }
79
82
  first = false;
80
83
  }
81
84
 
@@ -103,7 +106,10 @@ const grammar = class InstructionMiniparserGrammar {
103
106
  let sep;
104
107
  while (first || (sep && (p.match(/./y) || p.atExpression))) {
105
108
  p.eatProduction('Expression', { path: 'elements[]' });
106
- sep = p.eatMatchTrivia(_);
109
+ if (p.match(/\s*,?/y)) {
110
+ sep = p.eatProduction('Separator', { path: 'separators[]' });
111
+ }
112
+
107
113
  first = false;
108
114
  }
109
115
 
@@ -114,12 +120,14 @@ const grammar = class InstructionMiniparserGrammar {
114
120
  Tuple(p) {
115
121
  p.eat('(', PN, { path: 'openToken', balanced: ')' });
116
122
 
117
- let sep = p.eatMatchTrivia(_);
123
+ let sep;
118
124
 
119
125
  let i = 0;
120
126
  while (i === 0 || (sep && (p.match(/./y) || p.atExpression))) {
121
127
  p.eatProduction('Expression', { path: 'values[]' });
122
- sep = p.eatMatchTrivia(_);
128
+ if (p.match(/\s*,?/y)) {
129
+ sep = p.eatProduction('Separator', { path: 'separators[]' });
130
+ }
123
131
  i++;
124
132
  }
125
133
 
@@ -131,6 +139,13 @@ const grammar = class InstructionMiniparserGrammar {
131
139
  p.eat(/true|false/y, KW, { path: 'sigilToken' });
132
140
  }
133
141
 
142
+ //@Node
143
+ Separator(p) {
144
+ p.eatMatchTrivia(_);
145
+ p.eatMatch(/,/y, PN, { path: 'separators[]' });
146
+ p.eatMatchTrivia(_);
147
+ }
148
+
134
149
  // @Node
135
150
  Null(p) {
136
151
  p.eat('null', KW, { path: 'sigilToken' });
@@ -14,18 +14,22 @@ const canonicalURL = 'https://bablr.org/languages/core/en/spamex';
14
14
  const dependencies = { CSTML, Regex };
15
15
 
16
16
  const covers = buildCovers({
17
- [sym.node]: ['Attribute', 'Identifier', 'Pattern', 'Matcher', 'Literal', 'CSTML:Flags'],
17
+ [sym.node]: [
18
+ 'Attribute',
19
+ 'Identifier',
20
+ 'Matcher',
21
+ 'OpenNodeMatcher',
22
+ 'CloseNodeMatcher',
23
+ 'Literal',
24
+ 'CSTML:Flags',
25
+ ],
18
26
  Attribute: ['MappingAttribute', 'BooleanAttribute'],
19
27
  AttributeValue: ['CSTML:String', 'CSTML:Number'],
20
- Matcher: ['NodeMatcher', 'OpenNodeMatcher', 'CloseNodeMatcher', 'StringMatcher'],
28
+ Matcher: ['NodeMatcher', 'StringMatcher'],
21
29
  StringMatcher: ['CSTML:String', 'Regex:Pattern'],
22
30
  });
23
31
 
24
32
  const grammar = class SpamexMiniparserGrammar {
25
- Pattern(p) {
26
- p.eatProduction('Matcher', { path: 'matcher' });
27
- }
28
-
29
33
  // @Cover
30
34
  Matcher(p) {
31
35
  if (p.match(/<[^!/]/y)) {
@@ -67,10 +71,8 @@ const grammar = class SpamexMiniparserGrammar {
67
71
  p.eatProduction('CSTML:Flags', { path: 'flags' });
68
72
  }
69
73
 
70
- if (p.match(/[a-zA-Z]+:/y)) {
71
- p.eat(/[a-zA-Z]+/y, ID, { path: 'language' });
72
- p.eat(':', PN, { path: 'namespaceSeparatorToken' });
73
- p.eat(/[a-zA-Z]+/y, ID, { path: 'type' });
74
+ if (p.match(/['"]|[a-zA-Z]+:/y)) {
75
+ p.eatProduction('CSTML:TagType', { path: 'type' });
74
76
  } else if (p.match('?')) {
75
77
  p.eat('?', PN, { path: 'type' });
76
78
  } else if (p.match(' ')) {
package/lib/miniparser.js CHANGED
@@ -9,6 +9,8 @@ const { parsePath } = require('./path.js');
9
9
  const { set, isRegex, isArray, getPrototypeOf, buildNode } = require('./utils.js');
10
10
  const { ReferenceTag, LiteralTag, Escape } = require('@bablr/boot-helpers/symbols');
11
11
 
12
+ const { hasOwn } = Object;
13
+
12
14
  class TemplateParser {
13
15
  constructor(rootLanguage, quasis, expressions) {
14
16
  if (!quasis) throw new Error();
@@ -197,6 +199,10 @@ class TemplateParser {
197
199
  this.spans.push({ type: 'Bare', guard: null });
198
200
  }
199
201
 
202
+ if (!hasOwn(getPrototypeOf(grammar), type)) {
203
+ throw new Error(`Unknown production {type: ${type}}`);
204
+ }
205
+
200
206
  const result = getPrototypeOf(grammar)[type].call(grammar, this, props);
201
207
 
202
208
  if (isEmbedded) {
@@ -319,7 +325,7 @@ class TemplateParser {
319
325
 
320
326
  const result = this.matchSticky(pattern, attrs, this);
321
327
 
322
- if (!result) throw new Error('miniparser: parsing failed');
328
+ if (!result) this.fail();
323
329
 
324
330
  this.idx += result.length;
325
331
 
@@ -367,7 +373,7 @@ class TemplateParser {
367
373
  eatTrivia(pattern) {
368
374
  const result = this.matchSticky(pattern, {}, this);
369
375
 
370
- if (!result) throw new Error('miniparser: parsing failed');
376
+ if (!result) this.fail();
371
377
 
372
378
  this.idx += result.length;
373
379
 
@@ -391,7 +397,7 @@ class TemplateParser {
391
397
  eatEscape(pattern) {
392
398
  const result = this.matchSticky(pattern, {}, this);
393
399
 
394
- if (!result) throw new Error('miniparser: parsing failed');
400
+ if (!result) this.fail();
395
401
 
396
402
  this.idx += result.length;
397
403
 
@@ -415,7 +421,7 @@ class TemplateParser {
415
421
  eatLiteral(pattern) {
416
422
  const result = this.matchSticky(pattern, {}, this);
417
423
 
418
- if (!result) throw new Error('miniparser: parsing failed');
424
+ if (!result) this.fail();
419
425
 
420
426
  this.idx += result.length;
421
427
 
@@ -451,6 +457,10 @@ class TemplateParser {
451
457
  this.spans.pop();
452
458
  this.spans.push(span);
453
459
  }
460
+
461
+ fail() {
462
+ throw new Error(`miniparser: parsing \`${this.quasis}\` failed`);
463
+ }
454
464
  }
455
465
 
456
466
  module.exports = { TemplateParser };
package/lib/utils.js CHANGED
@@ -69,7 +69,7 @@ const set = (obj, path, value) => {
69
69
  obj[name].push(value);
70
70
  } else {
71
71
  if (hasOwn(obj, name)) {
72
- throw new Error('duplicate child name');
72
+ throw new Error(`duplicate child name \`${name}\``);
73
73
  }
74
74
 
75
75
  obj[name] = value;
package/package.json CHANGED
@@ -1,23 +1,22 @@
1
1
  {
2
2
  "name": "@bablr/boot",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Compile-time tools for bootstrapping BABLR VM",
5
5
  "engines": {
6
6
  "node": ">=12.0.0"
7
7
  },
8
8
  "exports": {
9
9
  ".": {
10
- "require": "./lib/index.js",
11
- "import": "./lib/index.mjs"
10
+ "require": "./dist/cjs.bundle.js",
11
+ "import": "./dist/esm.bundle.js"
12
12
  },
13
13
  "./shorthand.macro": "./shorthand.macro.js"
14
14
  },
15
- "files": [
16
- "lib/**/*.js",
17
- "lib/**/*.mjs",
18
- "shorthand.macro.js"
19
- ],
15
+ "files": ["lib/**/*.js", "lib/**/*.mjs", "shorthand.macro.js"],
20
16
  "sideEffects": false,
17
+ "scripts": {
18
+ "build": "rollup -c"
19
+ },
21
20
  "dependencies": {
22
21
  "@babel/helper-module-imports": "^7.22.15",
23
22
  "@babel/template": "^7.22.15",
@@ -26,7 +25,8 @@
26
25
  "@iter-tools/imm-stack": "1.1.0",
27
26
  "escape-string-regexp": "4.0.0",
28
27
  "iter-tools": "^7.5.3",
29
- "jest-diff": "29.7.0"
28
+ "jest-diff": "29.7.0",
29
+ "rollup": "^4.27.3"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@babel/cli": "^7.23.0",
@@ -34,12 +34,16 @@
34
34
  "@babel/plugin-proposal-decorators": "^7.23.2",
35
35
  "@babel/plugin-transform-runtime": "^7.23.2",
36
36
  "@bablr/eslint-config-base": "github:bablr-lang/eslint-config-base#a49dbe6861a82d96864ee89fbf0ec1844a8a5e8e",
37
+ "@rollup/plugin-commonjs": "^28.0.1",
38
+ "@rollup/plugin-node-resolve": "^15.3.0",
37
39
  "babel-plugin-macros": "^3.1.0",
38
40
  "enhanced-resolve": "^5.12.0",
39
41
  "eslint": "^8.47.0",
40
42
  "eslint-import-resolver-enhanced-resolve": "^1.0.5",
41
43
  "eslint-plugin-import": "^2.27.5",
42
44
  "expect": "^29.6.2",
45
+ "install": "^0.13.0",
46
+ "npm": "^10.9.0",
43
47
  "prettier": "^2.0.5"
44
48
  },
45
49
  "repository": "git@github.com:bablr-lang/boot.git",