@bablr/helpers 0.16.0 → 0.18.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/enhancers.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  enhanceStrategyBuilderWithEmittedLogging as logEmitted,
4
4
  } from '@bablr/strategy_enhancer-debug-log';
5
5
  import { enhanceProductionWithDebugLogging as createProductionLogger } from '@bablr/language_enhancer-debug-log';
6
- import { getPrototypeOf } from './object.js';
6
+ import { getOwnPropertySymbols, getPrototypeOf } from './object.js';
7
7
 
8
8
  const { getOwnPropertyNames, hasOwn } = Object;
9
9
 
@@ -47,8 +47,8 @@ export const mapProductions = (fn, Grammar) => {
47
47
 
48
48
  const mapped = MappedGrammar.prototype;
49
49
 
50
- while (prototype) {
51
- for (const key of getOwnPropertyNames(prototype)) {
50
+ while (prototype && prototype !== Object.prototype) {
51
+ for (const key of [...getOwnPropertyNames(prototype), ...getOwnPropertySymbols(prototype)]) {
52
52
  if (!hasOwn(mapped, key)) {
53
53
  mapped[key] = fn(prototype[key], key);
54
54
  }
@@ -60,7 +60,7 @@ export const mapProductions = (fn, Grammar) => {
60
60
  };
61
61
 
62
62
  export const debugEnhancers = {
63
- agast: (strategy) => logEmitted(strategy, '<<< '),
63
+ // agast: (strategy) => logEmitted(strategy, '<<< '),
64
64
  createBablrStrategy: (strategy) => logStrategy(strategy, ' >>> '),
65
65
  bablrProduction: createProductionLogger('>>> '),
66
66
  };
package/lib/grammar.js CHANGED
@@ -1,12 +1,21 @@
1
1
  import every from 'iter-tools-es/methods/every';
2
2
  import isString from 'iter-tools-es/methods/is-string';
3
- import { objectEntries, getPrototypeOf } from './object.js';
3
+ import objectEntries from 'iter-tools-es/methods/object-entries';
4
+ import { getPrototypeOf } from './object.js';
4
5
 
5
6
  const { isArray } = Array;
6
7
  const isSymbol = (value) => typeof value === 'symbol';
7
8
  const isType = (value) => isString(value) || isSymbol(value);
8
9
 
9
- export const resolveLanguage = (language, path) => {
10
+ export const resolveLanguage = (context, language, path) => {
11
+ if (isString(path)) {
12
+ if (language.canonicalURL === path) {
13
+ return language;
14
+ } else {
15
+ throw new Error('absolute path resolution not implemented');
16
+ }
17
+ }
18
+
10
19
  let l = language;
11
20
 
12
21
  if (!l) {
@@ -28,6 +37,20 @@ export const resolveLanguage = (language, path) => {
28
37
  return l;
29
38
  };
30
39
 
40
+ export const unresolveLanguage = (context, baseLanguage, absoluteLanguage) => {
41
+ if (absoluteLanguage == null || absoluteLanguage === baseLanguage.canonicalURL) {
42
+ return null;
43
+ }
44
+
45
+ for (const { 0: key, 1: value } of objectEntries(baseLanguage.dependencies)) {
46
+ if (value.canonicalURL === absoluteLanguage) {
47
+ return [key];
48
+ }
49
+ }
50
+
51
+ throw new Error('Cannot currently unresolve nested deps');
52
+ };
53
+
31
54
  export const explodeSubtypes = (aliases, exploded, types) => {
32
55
  for (const type of types) {
33
56
  const explodedTypes = aliases.get(type);
@@ -4,9 +4,7 @@
4
4
  * This file is autogenerated. Please do not edit it directly.
5
5
  * When editing run `npx macrome watch` then change the file this is generated from.
6
6
  */
7
- import { interpolateString as _interpolateString } from "@bablr/agast-helpers/template";
8
- import { interpolateArrayChildren as _interpolateArrayChildren } from "@bablr/agast-helpers/template";
9
- import { interpolateArray as _interpolateArray } from "@bablr/agast-helpers/template";
7
+ import { interpolateArray as _interpolateArray, interpolateArrayChildren as _interpolateArrayChildren, interpolateString as _interpolateString } from "@bablr/agast-helpers/template";
10
8
  import * as _l from "@bablr/agast-vm-helpers/languages";
11
9
  import * as _t from "@bablr/agast-helpers/shorthand";
12
10
  export function* List({
package/lib/source.js CHANGED
@@ -9,7 +9,7 @@ const escapables = {
9
9
  0: '\0',
10
10
  };
11
11
 
12
- function* __sourceFromReadStream(stream) {
12
+ function* __readFromStream(stream) {
13
13
  let iter = stream[Symbol.asyncIterator]();
14
14
  let step;
15
15
 
@@ -26,12 +26,12 @@ function* __sourceFromReadStream(stream) {
26
26
  }
27
27
  }
28
28
 
29
- export const sourceFromReadStream = (stream) => new StreamIterable(__sourceFromReadStream(stream));
29
+ export const readFromStream = (stream) => new StreamIterable(__readFromStream(stream));
30
30
 
31
31
  const gapStr = '<//>';
32
32
 
33
- function* __embeddedSourceFromReadStream(stream) {
34
- let iter = getStreamIterator(sourceFromReadStream(stream));
33
+ function* __embeddedSourceFrom(iterable) {
34
+ let iter = getStreamIterator(iterable);
35
35
  let step;
36
36
  let escape = false;
37
37
  let gapMatchIdx = 0;
@@ -89,8 +89,7 @@ function* __embeddedSourceFromReadStream(stream) {
89
89
  }
90
90
  }
91
91
 
92
- export const embeddedSourceFromReadStream = (stream) =>
93
- new StreamIterable(__embeddedSourceFromReadStream(stream));
92
+ export const embeddedSourceFrom = (iterable) => new StreamIterable(__embeddedSourceFrom(iterable));
94
93
 
95
94
  function* __sourceFromTokenStream(terminals) {
96
95
  let iter = getStreamIterator(terminals);
@@ -142,9 +141,9 @@ function* __sourceFromQuasis(quasis) {
142
141
 
143
142
  export const sourceFromQuasis = (quasis) => new StreamIterable(__sourceFromQuasis(quasis));
144
143
 
145
- export function* fillGapsWith(expressions, stream) {
144
+ export function* fillGapsWith(expressions, iterable) {
146
145
  let exprIdx = 0;
147
- let iter = getStreamIterator(stream);
146
+ let iter = getStreamIterator(iterable);
148
147
  let holding = false;
149
148
 
150
149
  for (;;) {
@@ -183,8 +182,8 @@ export function* fillGapsWith(expressions, stream) {
183
182
 
184
183
  const none = Symbol('none');
185
184
 
186
- function* __stripTrailingNewline(stream) {
187
- const iter = getStreamIterator(stream);
185
+ function* __stripTrailingNewline(iterable) {
186
+ const iter = getStreamIterator(iterable);
188
187
  let step = iter.next();
189
188
  let lastValue = none;
190
189
 
@@ -214,4 +213,5 @@ function* __stripTrailingNewline(stream) {
214
213
  }
215
214
  }
216
215
 
217
- export const stripTrailingNewline = (stream) => new StreamIterable(__stripTrailingNewline(stream));
216
+ export const stripTrailingNewline = (iterable) =>
217
+ new StreamIterable(__stripTrailingNewline(iterable));
package/lib/stream.js ADDED
@@ -0,0 +1,85 @@
1
+ import { Coroutine } from '@bablr/coroutine';
2
+ import {
3
+ generatePrettyCSTMLStrategy as generatePrettyCSTML,
4
+ generateCSTMLStrategy as generateCSTML,
5
+ stringFromStream,
6
+ generateStandardOutput,
7
+ getStreamIterator,
8
+ StreamIterable,
9
+ } from '@bablr/agast-helpers/stream';
10
+ import isString from 'iter-tools-es/methods/is-string';
11
+ import emptyStack from '@iter-tools/imm-stack';
12
+
13
+ import { unresolveLanguage } from './grammar.js';
14
+
15
+ // bad: wrecks tree by breaking weak linkages
16
+ function* __resolveTerminals(ctx, terminals) {
17
+ const co = new Coroutine(getStreamIterator(terminals));
18
+ let languages = emptyStack;
19
+
20
+ for (;;) {
21
+ co.advance();
22
+
23
+ if (co.current instanceof Promise) {
24
+ co.current = yield co.current;
25
+ }
26
+
27
+ if (co.done) break;
28
+
29
+ const terminal = co.value;
30
+
31
+ if (terminal.type === 'DoctypeTag') {
32
+ languages = languages.push(ctx.languages.get(terminal.value.attributes['bablr-language']));
33
+ }
34
+
35
+ if (terminal.type === 'CloseNodeTag') {
36
+ languages = languages.pop();
37
+ }
38
+
39
+ if (terminal.type === 'OpenNodeTag') {
40
+ if (isString(terminal.value.language)) {
41
+ const currentLanguage = languages.value;
42
+ const nodeLanguageURL = terminal.value.language;
43
+ const nodeLanguage = ctx.languages.get(nodeLanguageURL);
44
+
45
+ languages = languages.push(nodeLanguage);
46
+
47
+ yield {
48
+ type: 'OpenNodeTag',
49
+ value: {
50
+ ...terminal.value,
51
+ language: unresolveLanguage(ctx, currentLanguage, nodeLanguageURL),
52
+ },
53
+ };
54
+ } else {
55
+ yield terminal;
56
+ }
57
+ } else {
58
+ yield terminal;
59
+ }
60
+ }
61
+ }
62
+
63
+ export const resolveTerminals = (ctx, terminals) => {
64
+ return new StreamIterable(__resolveTerminals(ctx, terminals));
65
+ };
66
+
67
+ export const generatePrettyCSTMLStrategy = (terminals, options = {}) => {
68
+ const { ctx } = options;
69
+
70
+ return generatePrettyCSTML(ctx ? resolveTerminals(ctx, terminals) : terminals, options);
71
+ };
72
+
73
+ export const printPrettyCSTML = (terminals, options = {}) => {
74
+ return stringFromStream(generateStandardOutput(generatePrettyCSTMLStrategy(terminals, options)));
75
+ };
76
+
77
+ export const generateCSTMLStrategy = (terminals, options = {}) => {
78
+ const { ctx } = options;
79
+
80
+ return generateCSTML(ctx ? resolveTerminals(ctx, terminals) : terminals, options);
81
+ };
82
+
83
+ export const printCSTML = (terminals, options = {}) => {
84
+ return stringFromStream(generateStandardOutput(generateCSTMLStrategy(terminals, options)));
85
+ };
package/lib/tree.js ADDED
@@ -0,0 +1,8 @@
1
+ import { streamFromTree } from '@bablr/agast-helpers/tree';
2
+
3
+ import { printPrettyCSTML as printPrettyCSTMLFromStream } from './stream.js';
4
+
5
+ export const printPrettyCSTML = (rootNode, options = {}) => {
6
+ // i need a context-aware streamFromTree here to build a stream with linked terminals...?
7
+ return printPrettyCSTMLFromStream(streamFromTree(rootNode), options);
8
+ };
package/lib/trivia.js CHANGED
@@ -7,7 +7,7 @@ const lookbehind = (context, s) => {
7
7
  while (
8
8
  token &&
9
9
  ['OpenNodeTag', 'CloseNodeTag', 'Reference'].includes(token.type) &&
10
- (token.type !== 'OpenNodeTag' || !token.value.intrinsicValue)
10
+ (token.type !== 'OpenNodeTag' || !(token.value.flags.intrinsic && token.value.flags.token))
11
11
  ) {
12
12
  const prevToken = context.getPreviousTerminal(token);
13
13
  if (!prevToken) break;
@@ -39,7 +39,7 @@ export const triviaEnhancer = ({ triviaIsAllowed, eatMatchTrivia }, grammar) =>
39
39
  case 'eatMatch':
40
40
  case 'match':
41
41
  case 'guard': {
42
- if (matcher && matcher.type && !matcher.flags.trivia) {
42
+ if (matcher && !matcher.flags?.trivia) {
43
43
  const previous = lookbehind(ctx, s);
44
44
  if (triviaIsAllowed(s) && (!previous || !matchedResults.has(previous))) {
45
45
  matchedResults.add(previous);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bablr/helpers",
3
3
  "description": "Command helpers for use in writing BABLR grammars",
4
- "version": "0.16.0",
4
+ "version": "0.18.0",
5
5
  "author": "Conrad Buck<conartist6@gmail.com>",
6
6
  "type": "module",
7
7
  "files": [
@@ -16,7 +16,9 @@
16
16
  "./productions": "./lib/productions.js",
17
17
  "./shorthand": "./lib/shorthand.js",
18
18
  "./source": "./lib/source.js",
19
+ "./stream": "./lib/stream.js",
19
20
  "./symbols": "./lib/symbols.js",
21
+ "./tree": "./lib/tree.js",
20
22
  "./trivia": "./lib/trivia.js"
21
23
  },
22
24
  "sideEffects": false,
@@ -26,17 +28,18 @@
26
28
  "clean": "macrome clean"
27
29
  },
28
30
  "dependencies": {
29
- "@bablr/language_enhancer-debug-log": "0.3.0",
30
- "@bablr/strategy_enhancer-debug-log": "0.2.0",
31
- "@bablr/agast-helpers": "0.1.6",
32
- "@bablr/agast-vm-helpers": "0.1.5",
31
+ "@bablr/language_enhancer-debug-log": "0.5.0",
32
+ "@bablr/strategy_enhancer-debug-log": "0.4.0",
33
+ "@bablr/agast-helpers": "0.3.1",
34
+ "@bablr/agast-vm-helpers": "0.3.1",
33
35
  "@bablr/coroutine": "0.1.0",
36
+ "@iter-tools/imm-stack": "1.1.0",
34
37
  "iter-tools-es": "^7.5.3"
35
38
  },
36
39
  "devDependencies": {
37
- "@bablr/boot": "0.2.4",
40
+ "@bablr/boot": "0.4.0",
38
41
  "@bablr/eslint-config-base": "github:bablr-lang/eslint-config-base#d834ccc52795d6c3b96ecc6c419960fceed221a6",
39
- "@bablr/macrome": "0.1.1",
42
+ "@bablr/macrome": "0.1.3",
40
43
  "@bablr/macrome-generator-bablr": "0.3.1",
41
44
  "enhanced-resolve": "^5.12.0",
42
45
  "eslint": "^7.32.0",