@bablr/boot 0.7.2 → 0.8.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
@@ -4,7 +4,7 @@ import * as regex from './languages/regex.js';
4
4
  import * as instruction from './languages/instruction.js';
5
5
 
6
6
  import { TemplateParser } from './miniparser.js';
7
- import { Resolver, buildEmbeddedMatcher, buildEmbeddedRegex } from '@bablr/agast-helpers/tree';
7
+ import { buildEmbeddedMatcher, buildEmbeddedRegex } from '@bablr/agast-vm-helpers/builders';
8
8
 
9
9
  export const buildTag = (language, defaultType) => {
10
10
  const defaultTag = (quasis, ...exprs) => {
@@ -57,4 +57,4 @@ export const re = new Proxy(re_, {
57
57
  },
58
58
  });
59
59
 
60
- export { TemplateParser, Resolver };
60
+ export { TemplateParser };
@@ -1,4 +1,4 @@
1
- import * as sym from '@bablr/agast-helpers/symbols';
1
+ import * as sym from '@bablr/agast-vm-helpers/symbols';
2
2
  import * as JSON from './json.js';
3
3
 
4
4
  const _ = /\s+/y;
@@ -24,6 +24,7 @@ export const covers = new Map([
24
24
  'ReferenceTag',
25
25
  'ReferenceFlags',
26
26
  'Identifier',
27
+ 'IdentifierContent',
27
28
  'GlobalIdentifier',
28
29
  'NullTag',
29
30
  'GapTag',
@@ -49,7 +50,7 @@ export const grammar = class CSTMLMiniparserGrammar {
49
50
  Document(p) {
50
51
  p.eatProduction('DoctypeTag', { path: 'doctype' });
51
52
  p.eatMatchTrivia(_);
52
- p.eatProduction('Node', { path: 'tree' });
53
+ p.eatProduction('Node', { path: 'tree' }, { fragment: true });
53
54
  }
54
55
 
55
56
  // @Node
@@ -80,8 +81,8 @@ export const grammar = class CSTMLMiniparserGrammar {
80
81
  }
81
82
 
82
83
  // @Node
83
- Node(p) {
84
- let open = p.eatProduction('OpenNodeTag', { path: 'open' });
84
+ Node(p, props) {
85
+ let open = p.eatProduction('OpenNodeTag', { path: 'open' }, props);
85
86
 
86
87
  p.eatMatchTrivia(_);
87
88
 
@@ -100,7 +101,7 @@ export const grammar = class CSTMLMiniparserGrammar {
100
101
  }
101
102
  }
102
103
 
103
- NodeChild(p, _, props) {
104
+ NodeChild(p, props) {
104
105
  const { token } = props || {};
105
106
 
106
107
  if (token) {
@@ -112,7 +113,7 @@ export const grammar = class CSTMLMiniparserGrammar {
112
113
  } else {
113
114
  if (p.match(/<\*?#/y)) {
114
115
  p.eatProduction('Node');
115
- } else if (p.match(/[a-zA-Z]|[.#@]/y)) {
116
+ } else if (p.match(/[a-zA-Z`\\\u{80}-\u{10ffff}.]|[.#@]/uy)) {
116
117
  p.eatProduction('Property');
117
118
  } else if (p.match(/['"]/y)) {
118
119
  p.eatProduction('LiteralTag');
@@ -141,10 +142,12 @@ export const grammar = class CSTMLMiniparserGrammar {
141
142
  NodeFlags(p) {
142
143
  p.eatMatch('*', PN, { path: 'tokenToken' });
143
144
  p.eatMatch('$', PN, { path: 'hasGapToken' });
145
+ p.eatMatch('_', PN, { path: 'fragmentToken' });
146
+ p.eatMatch('_', PN, { path: 'coverFragmentToken' });
144
147
  }
145
148
 
146
149
  // @Node
147
- OpenNodeTag(p) {
150
+ OpenNodeTag(p, { fragment } = {}) {
148
151
  p.eat('<', PN, { path: 'openToken', startSpan: 'Tag', balanced: '>' });
149
152
 
150
153
  let flags = null;
@@ -153,9 +156,14 @@ export const grammar = class CSTMLMiniparserGrammar {
153
156
  }
154
157
 
155
158
  let sp = null;
156
- let isFragment = !p.match(/['"a-zA-Z]/y);
157
159
 
158
- if (!isFragment) {
160
+ if (fragment && !flags.properties.fragmentToken) throw new Error();
161
+
162
+ if (!flags.properties.fragmentToken && !p.match(/./sy)) {
163
+ throw new Error();
164
+ }
165
+
166
+ if (!flags.properties.fragmentToken) {
159
167
  p.eatProduction('TagType', { path: 'type' });
160
168
 
161
169
  sp = p.eatMatchTrivia(_);
@@ -190,7 +198,10 @@ export const grammar = class CSTMLMiniparserGrammar {
190
198
  }
191
199
 
192
200
  TagType(p) {
193
- if (p.match(/['"]|[a-zA-Z.]+:/y) || (p.atExpression && p.quasis[p.quasiIdx + 1][0] === ':')) {
201
+ if (
202
+ p.match(/['"]|[a-zA-Z`\\\u{80}-\u{10ffff}.]+:/uy) ||
203
+ (p.atExpression && p.quasis[p.quasiIdx + 1][0] === ':')
204
+ ) {
194
205
  p.eatProduction('LanguageReference', { path: 'language' });
195
206
  p.eat(':', PN, { path: 'namespaceSeparatorToken' });
196
207
  p.eatProduction('Identifier', { path: 'type' });
@@ -217,7 +228,31 @@ export const grammar = class CSTMLMiniparserGrammar {
217
228
 
218
229
  // @Node
219
230
  Identifier(p) {
220
- p.eatLiteral(/[a-zA-Z][a-zA-Z-_]*/y);
231
+ let res, q;
232
+ q = p.match('`');
233
+ if (q) p.eat('`', PN, { path: 'openToken', balanced: '`' });
234
+
235
+ p.eatProduction('IdentifierContent', { path: 'content', span: 'Identifier' }, { quoted: !!q });
236
+
237
+ if (q) p.eat('`', PN, { path: 'closeToken', balancer: true });
238
+ }
239
+
240
+ // @Node
241
+ IdentifierContent(p, props) {
242
+ let { quoted = false } = props || {};
243
+
244
+ let lit, esc;
245
+ do {
246
+ if ((esc = p.match('\\'))) {
247
+ p.eatMatchEscape(/\\(u(\{[0-9a-fA-F]\}|\d{4}))/y);
248
+ } else {
249
+ if (!quoted) {
250
+ lit = p.eatMatchLiteral(/[a-zA-Z\u{80}-\u{10ffff}][a-zA-Z0-9_\u{80}-\u{10ffff}-]*/uy);
251
+ } else {
252
+ lit = p.eatMatchLiteral(/[^`\r\n]+/uy);
253
+ }
254
+ }
255
+ } while (lit || esc);
221
256
  }
222
257
 
223
258
  // @Cover
@@ -263,9 +298,4 @@ export const grammar = class CSTMLMiniparserGrammar {
263
298
  p.eatMatch('+', PN, { path: 'expressionToken' });
264
299
  p.eatMatch('$', PN, { path: 'hasGapToken' });
265
300
  }
266
-
267
- // @Node
268
- Literal(p) {
269
- p.eatProduction('JSON:String', { path: 'value' });
270
- }
271
301
  };
@@ -1,4 +1,4 @@
1
- import * as sym from '@bablr/agast-helpers/symbols';
1
+ import * as sym from '@bablr/agast-vm-helpers/symbols';
2
2
  import * as Spamex from './spamex.js';
3
3
  import * as CSTML from './cstml.js';
4
4
  import * as Regex from './regex.js';
@@ -1,5 +1,5 @@
1
1
  import objectEntries from 'iter-tools/methods/object-entries';
2
- import * as sym from '@bablr/agast-helpers/symbols';
2
+ import * as sym from '@bablr/agast-vm-helpers/symbols';
3
3
  import * as Spamex from './spamex.js';
4
4
  import * as CSTML from './cstml.js';
5
5
  import * as Regex from './regex.js';
@@ -28,7 +28,8 @@ export const covers = new Map([
28
28
  'Number',
29
29
  'UnsignedInteger',
30
30
  'Infinity',
31
- 'NaN',
31
+ 'NotANumber',
32
+ 'Undefined',
32
33
  'Digit',
33
34
  'Integer',
34
35
  'String',
@@ -36,7 +37,7 @@ export const covers = new Map([
36
37
  ]),
37
38
  ],
38
39
  ['Expression', new Set(['Object', 'Array', 'Boolean', 'Null', 'Number', 'String'])],
39
- ['Number', new Set(['Integer', 'Infinity', 'NaN'])],
40
+ ['Number', new Set(['Integer', 'Infinity', 'NotANumber'])],
40
41
  ]);
41
42
 
42
43
  export const escapables = new Map(
@@ -92,6 +93,8 @@ export const grammar = class JSONMiniparserGrammar {
92
93
  p.eatProduction('Boolean');
93
94
  } else if (p.match('null')) {
94
95
  p.eatProduction('Null');
96
+ } else if (p.match('undefined')) {
97
+ p.eatProduction('Undefined');
95
98
  } else if (p.match(/[+-]?(?:\d|Infinity)|NaN/y)) {
96
99
  p.eatProduction('Number');
97
100
  } else if (p.match(/['"]/y)) {
@@ -109,7 +112,7 @@ export const grammar = class JSONMiniparserGrammar {
109
112
  let sep;
110
113
  while (first || (sep && (p.match(/./y) || p.atExpression))) {
111
114
  p.eatProduction('Property', { path: 'properties[]' });
112
- if (p.match(/\s*,?/y)) {
115
+ if ((sep = p.match(/\s*,/y))) {
113
116
  sep = p.eatProduction('ListSeparator', { path: 'separators[]' });
114
117
  }
115
118
  first = false;
@@ -139,7 +142,7 @@ export const grammar = class JSONMiniparserGrammar {
139
142
  let sep;
140
143
  while (first || (sep && (p.match(/./y) || p.atExpression))) {
141
144
  p.eatProduction('Expression', { path: 'elements[]' });
142
- if (p.match(/\s*,?/y)) {
145
+ if (p.match(/\s*,/y)) {
143
146
  sep = p.eatProduction('ListSeparator', { path: 'separators[]' });
144
147
  }
145
148
 
@@ -161,7 +164,7 @@ export const grammar = class JSONMiniparserGrammar {
161
164
 
162
165
  ListSeparator(p) {
163
166
  p.eatMatchTrivia(_);
164
- p.eatMatch(/,/y, PN, { path: 'separators[]' });
167
+ p.eat(/,/y, PN, { path: 'separators[]' });
165
168
  p.eatMatchTrivia(_);
166
169
  }
167
170
 
@@ -193,10 +196,15 @@ export const grammar = class JSONMiniparserGrammar {
193
196
  }
194
197
 
195
198
  // @Node
196
- NaN(p) {
199
+ NotANumber(p) {
197
200
  p.eat('NaN', 'Keyword', { path: 'sigilToken' });
198
201
  }
199
202
 
203
+ // @Node
204
+ Undefined(p) {
205
+ p.eat('undefined', 'Keyword', { path: 'sigilToken' });
206
+ }
207
+
200
208
  Digits(p) {
201
209
  while (p.match(/\d/y)) {
202
210
  p.eatProduction('Digit');
@@ -228,8 +236,8 @@ export const grammar = class JSONMiniparserGrammar {
228
236
  do {
229
237
  esc =
230
238
  p.span.type === 'Single'
231
- ? p.eatMatchEscape(/\\(u(\{\d{1,6}\}|\d{4})|[\\gnrt0'])/y)
232
- : p.eatMatchEscape(/\\(u(\{\d{1,6}\}|\d{4})|[\\gnrt0"])/y);
239
+ ? p.eatMatchEscape(/\\(u(\{[0-9a-fA-F]{1,6}\}|\d{4})|[\\gnrt0'])/y)
240
+ : p.eatMatchEscape(/\\(u(\{[0-9a-fA-F]{1,6}\}|\d{4})|[\\gnrt0"])/y);
233
241
  lit =
234
242
  p.span.type === 'Single'
235
243
  ? p.eatMatchLiteral(/[^\r\n\0\\']+/y)
@@ -1,4 +1,4 @@
1
- import * as sym from '@bablr/agast-helpers/symbols';
1
+ import * as sym from '@bablr/agast-vm-helpers/symbols';
2
2
  import when from 'iter-tools/methods/when';
3
3
  import { escapables } from './json.js';
4
4
 
@@ -267,7 +267,7 @@ export const grammar = class RegexMiniparserGrammar {
267
267
  if (
268
268
  p.eatMatchEscape(
269
269
  new RegExp(
270
- String.raw`\\(u(\{\d{1,6}\}|\d{4})|x[0-9a-fA-F]{2}|[nrt0]|${specialPattern.source})`,
270
+ String.raw`\\(u(\{[0-9a-fA-F]{1,6}\}|[0-9a-fA-F]{4})|x[0-9a-fA-F]{2}|[nrt0]|${specialPattern.source})`,
271
271
  'y',
272
272
  ),
273
273
  )
@@ -276,7 +276,7 @@ export const grammar = class RegexMiniparserGrammar {
276
276
  } else if (p.eatMatchEscape(new RegExp(String.raw`\\${specialPattern.source}`, 'y'))) {
277
277
  // done
278
278
  } else {
279
- throw new Error('escape required');
279
+ throw new Error('escape not allowed');
280
280
  }
281
281
  } else {
282
282
  if (p.match(new RegExp(specialPattern, 'y'))) {
@@ -306,7 +306,7 @@ export const grammar = class RegexMiniparserGrammar {
306
306
 
307
307
  // @Cover
308
308
  CharacterClassElement(p, { first }) {
309
- if (p.match(/.-[^\]\n]/y)) {
309
+ 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
310
  p.eatProduction('CharacterClassRange', undefined, { first });
311
311
  } else if (p.match(/\\[dswp]/iy)) {
312
312
  p.eatProduction('CharacterSet');
@@ -1,4 +1,4 @@
1
- import * as sym from '@bablr/agast-helpers/symbols';
1
+ import * as sym from '@bablr/agast-vm-helpers/symbols';
2
2
  import * as Regex from './regex.js';
3
3
  import * as CSTML from './cstml.js';
4
4
  import * as JSON from './json.js';
@@ -17,7 +17,7 @@ export const covers = new Map([
17
17
  [
18
18
  sym.node,
19
19
  new Set([
20
- 'Identifier',
20
+ 'CSTML:Identifier',
21
21
  'PropertyMatcher',
22
22
  'JSON:String',
23
23
  'Regex:Pattern',
@@ -159,11 +159,7 @@ export const grammar = class SpamexMiniparserGrammar {
159
159
  } else if (p.match(' ')) {
160
160
  p.eatMatchTrivia(_);
161
161
  } else {
162
- if (p.atExpression) {
163
- p.eatProduction('Identifier', { path: 'type' });
164
- } else {
165
- p.eatMatch(/[a-zA-Z]+/y, ID, { path: 'type' });
166
- }
162
+ p.eatProduction('CSTML:Identifier', { path: 'type' });
167
163
  }
168
164
 
169
165
  let sp = p.eatMatchTrivia(_);
@@ -197,9 +193,4 @@ export const grammar = class SpamexMiniparserGrammar {
197
193
  p.eatProduction('Regex:Pattern');
198
194
  }
199
195
  }
200
-
201
- // @Node
202
- Identifier(p) {
203
- p.eatLiteral(/[a-zA-Z]+/y);
204
- }
205
196
  };
package/lib/match.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createNode } from '@bablr/agast-helpers/tree';
2
2
  import { Path } from './path.js';
3
3
  import { resolveDependentLanguage } from './utils.js';
4
- import * as sym from '@bablr/agast-helpers/symbols';
4
+ import * as sym from '@bablr/agast-vm-helpers/symbols';
5
5
 
6
6
  export class Match {
7
7
  constructor(parent, resolvedLanguage, id, attributes, path) {
package/lib/miniparser.js CHANGED
@@ -2,11 +2,13 @@ import escapeRegex from 'escape-string-regexp';
2
2
  import arrayLast from 'iter-tools/methods/array-last';
3
3
  import isString from 'iter-tools/methods/is-string';
4
4
  import isObject from 'iter-tools/methods/is-object';
5
- import * as sym from '@bablr/agast-helpers/symbols';
5
+ import find from 'iter-tools/methods/find';
6
+ import every from 'iter-tools/methods/every';
7
+ import * as sym from '@bablr/agast-vm-helpers/symbols';
6
8
  import { Match } from './match.js';
7
9
  import { parsePath } from './path.js';
8
10
  import { isRegex, isArray, getPrototypeOf } from './utils.js';
9
- import { ReferenceTag, LiteralTag, ShiftTag } from '@bablr/agast-helpers/symbols';
11
+ import { ReferenceTag, LiteralTag } from '@bablr/agast-helpers/symbols';
10
12
  import {
11
13
  buildCloseNodeTag,
12
14
  buildLiteralTag,
@@ -14,8 +16,8 @@ import {
14
16
  buildReferenceTag,
15
17
  nodeFlags,
16
18
  } from '@bablr/agast-helpers/builders';
17
- import { add, buildGapTag, buildShiftTag, buildToken } from '@bablr/agast-helpers/tree';
18
- import * as btree from '@bablr/agast-helpers/btree';
19
+ import { add, buildToken } from '@bablr/agast-helpers/tree';
20
+ import * as sumtree from '@bablr/agast-helpers/sumtree';
19
21
  import { get } from '@bablr/agast-helpers/path';
20
22
 
21
23
  const Escape = Symbol.for('Escape');
@@ -173,19 +175,19 @@ export class TemplateParser {
173
175
  this.idx = 0;
174
176
 
175
177
  if (parentPath?.node && (isNode || covers.has(type))) {
176
- const { properties, children } = parentPath.node;
178
+ const { node } = parentPath;
177
179
  const path = parsePath(this.m.attrs.path);
178
180
 
179
181
  if (isArray(result)) {
180
182
  for (const value of result) {
181
- children.push(path);
183
+ node.children = sumtree.push(node.children, path);
182
184
 
183
- add(parentPath.node, path, value);
185
+ add(node, path, value);
184
186
  }
185
187
  } else {
186
- children.push(path);
188
+ node.children = sumtree.push(node.children, path);
187
189
 
188
- add(parentPath.node, path, result);
190
+ add(node, path, result);
189
191
  }
190
192
  }
191
193
  } else {
@@ -199,7 +201,7 @@ export class TemplateParser {
199
201
 
200
202
  if (isNode) {
201
203
  let { node } = this.path;
202
- node.children = btree.push(
204
+ node.children = sumtree.push(
203
205
  node.children,
204
206
  buildOpenNodeTag(nodeFlags, node.language, node.type),
205
207
  );
@@ -215,16 +217,16 @@ export class TemplateParser {
215
217
  const { node } = this.path;
216
218
  if (result?.attrs) {
217
219
  node.attributes = result.attrs;
218
- node.children = btree.replaceAt(
220
+ node.children = sumtree.replaceAt(
219
221
  0,
220
222
  node.children,
221
223
  buildOpenNodeTag(nodeFlags, node.language, node.type, result.attrs),
222
224
  );
223
225
  }
224
226
 
225
- node.children = btree.push(node.children, buildCloseNodeTag());
227
+ node.children = sumtree.push(node.children, buildCloseNodeTag());
226
228
 
227
- if (parentPath?.node && !covers.has(type) && shift == null) {
229
+ if (parentPath?.node && !covers.has(type)) {
228
230
  const path = parsePath(this.m.attrs.path);
229
231
 
230
232
  add(parentPath.node, path, node, shift);
@@ -239,7 +241,7 @@ export class TemplateParser {
239
241
 
240
242
  const { children } = this.path.node;
241
243
 
242
- if (children.find(isTag) && !children.every(isTag)) {
244
+ if (find(isTag, sumtree.traverse(children)) && every(isTag, sumtree.traverse(children))) {
243
245
  throw new Error('strings must be wrapped in nodes');
244
246
  }
245
247
  }
@@ -279,20 +281,17 @@ export class TemplateParser {
279
281
  }
280
282
 
281
283
  eatHeldProduction(type, attrs) {
282
- const { children, properties } = this.node;
283
-
284
284
  if (!this.held) {
285
285
  throw new Error();
286
286
  }
287
287
 
288
- const { held } = this;
288
+ const { held, node } = this;
289
289
 
290
290
  this.held = null;
291
291
 
292
292
  const path = parsePath(attrs.path);
293
293
 
294
- children.push(path);
295
- add(this.node, path, held);
294
+ add(node, path, held, 0);
296
295
 
297
296
  return held;
298
297
  }
@@ -304,7 +303,7 @@ export class TemplateParser {
304
303
 
305
304
  // get the most recently produced node and detach it from its parent
306
305
 
307
- const ref = btree.getAt(-2, node.children);
306
+ const ref = sumtree.getAt(-2, node.children);
308
307
 
309
308
  if (!ref.value.flags.expression) throw new Error();
310
309
 
@@ -318,7 +317,7 @@ export class TemplateParser {
318
317
 
319
318
  const shifted = this.eval(id_, attrs, props, 1);
320
319
 
321
- add(node, ref, shifted, 1);
320
+ // add(node, ref, shifted, 1);
322
321
 
323
322
  return shifted;
324
323
  }
@@ -448,7 +447,7 @@ export class TemplateParser {
448
447
 
449
448
  this.idx += result.length;
450
449
 
451
- this.node.children.push(buildLiteralTag(result));
450
+ this.node.children = sumtree.push(this.node.children, buildLiteralTag(result));
452
451
 
453
452
  return result;
454
453
  }
@@ -459,7 +458,7 @@ export class TemplateParser {
459
458
  if (result) {
460
459
  this.idx += result.length;
461
460
 
462
- this.node.children.push(buildLiteralTag(result));
461
+ this.node.children = sumtree.push(this.node.children, buildLiteralTag(result));
463
462
  }
464
463
 
465
464
  return result;
package/package.json CHANGED
@@ -1,13 +1,18 @@
1
1
  {
2
2
  "name": "@bablr/boot",
3
- "version": "0.7.2",
3
+ "version": "0.8.0",
4
4
  "description": "Compile-time tools for bootstrapping BABLR VM",
5
5
  "engines": {
6
6
  "node": ">=12.0.0"
7
7
  },
8
8
  "type": "module",
9
9
  "exports": {
10
- ".": "./lib/index.js"
10
+ ".": "./lib/index.js",
11
+ "./languages/cstml": "./lib/languages/cstml.js",
12
+ "./languages/instruction": "./lib/languages/instruction.js",
13
+ "./languages/json": "./lib/languages/json.js",
14
+ "./languages/regex": "./lib/languages/regex.js",
15
+ "./languages/spamex": "./lib/languages/spamex.js"
11
16
  },
12
17
  "files": [
13
18
  "lib/**/*.js",
@@ -15,8 +20,8 @@
15
20
  ],
16
21
  "sideEffects": false,
17
22
  "dependencies": {
18
- "@bablr/agast-helpers": "0.6.1",
19
- "@bablr/agast-vm-helpers": "0.6.1",
23
+ "@bablr/agast-helpers": "0.7.0",
24
+ "@bablr/agast-vm-helpers": "0.7.0",
20
25
  "@iter-tools/imm-stack": "1.1.0",
21
26
  "escape-string-regexp": "5.0.0",
22
27
  "iter-tools": "^7.5.3"