@bablr/helpers 0.22.1 → 0.24.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/decorators.js CHANGED
@@ -1,4 +1,3 @@
1
- import { printType } from '@bablr/agast-helpers/print';
2
1
  import * as sym from './symbols.js';
3
2
 
4
3
  export const AllowEmpty = (desc, context) => {
@@ -27,8 +26,6 @@ export const Literal = (desc, context) => {
27
26
 
28
27
  export const CoveredBy = (type) => {
29
28
  return (desc, context) => {
30
- if (!/^[a-zA-Z]+$/.test(printType(type))) throw new Error();
31
-
32
29
  context.addInitializer(function () {
33
30
  let covers = this.covers;
34
31
 
package/lib/enhancers.js CHANGED
@@ -1,7 +1,4 @@
1
- import {
2
- enhanceStrategyBuilderWithDebugLogging as logStrategy,
3
- enhanceStrategyBuilderWithEmittedLogging as logEmitted,
4
- } from '@bablr/strategy_enhancer-debug-log';
1
+ import { enhanceStrategyBuilderWithDebugLogging as logStrategy } from '@bablr/strategy_enhancer-debug-log';
5
2
  import { enhanceProductionWithDebugLogging as createProductionLogger } from '@bablr/language_enhancer-debug-log';
6
3
  import { mapProductions } from './grammar.js';
7
4
 
@@ -40,8 +37,8 @@ export const compose = (functions) => {
40
37
 
41
38
  export const debugEnhancers = {
42
39
  // bablr: (strategy) => logStrategy(strategy, '<<< '),
43
- createBablrStrategy: (strategy) => (matcher, props) =>
44
- logStrategy(strategy(matcher, props), ' >>> '),
40
+ createBablrStrategy: (strategy) => (language, matcher, props) =>
41
+ logStrategy(strategy(language, matcher, props), ' >>> '),
45
42
  bablrProduction: createProductionLogger('>>> '),
46
43
  };
47
44
 
package/lib/grammar.js CHANGED
@@ -2,7 +2,6 @@ import every from 'iter-tools-es/methods/every';
2
2
  import isString from 'iter-tools-es/methods/is-string';
3
3
  import { getOwnPropertySymbols, getPrototypeOf, objectEntries, objectValues } from './object.js';
4
4
  import { OpenNodeTag, CloseNodeTag, NullTag } from './symbols.js';
5
- import { buildExpression } from './builders.js';
6
5
  import { buildEmbeddedObject } from '@bablr/agast-vm-helpers/builders';
7
6
 
8
7
  export * from './decorators.js';
@@ -17,6 +16,21 @@ export const notNull = (facade) => {
17
16
  return facade && (facade.type !== null || facade.openTag.type !== NullTag);
18
17
  };
19
18
 
19
+ export const mapOwnProductions = (fn, Grammar) => {
20
+ let { prototype } = Grammar;
21
+
22
+ class MappedGrammar extends Grammar {}
23
+
24
+ const mapped = MappedGrammar.prototype;
25
+
26
+ for (const key of [...getOwnPropertyNames(prototype), ...getOwnPropertySymbols(prototype)]) {
27
+ if (!hasOwn(mapped, key)) {
28
+ mapped[key] = fn(prototype[key], key);
29
+ }
30
+ }
31
+ return MappedGrammar;
32
+ };
33
+
20
34
  export const mapProductions = (fn, Grammar) => {
21
35
  let { prototype } = Grammar;
22
36
 
@@ -81,30 +95,6 @@ export const resolveLanguage = (context, language, path) => {
81
95
  return l;
82
96
  };
83
97
 
84
- export const unresolveLanguage = (context, baseLanguage, absoluteLanguage) => {
85
- if (absoluteLanguage == null || absoluteLanguage === baseLanguage.canonicalURL) {
86
- return null;
87
- }
88
-
89
- for (const { 0: key, 1: value } of objectEntries(baseLanguage.dependencies)) {
90
- if (value.canonicalURL === absoluteLanguage) {
91
- return [key];
92
- }
93
- }
94
-
95
- // TODO wow I am lazy I literally just hardcoded this to depth two yep
96
- // I really want to do a BFS with handling for dep cycles
97
- for (const lang of objectValues(baseLanguage.dependencies)) {
98
- for (const { 0: key, 1: value } of objectEntries(lang.dependencies)) {
99
- if (value.canonicalURL === absoluteLanguage) {
100
- return [key];
101
- }
102
- }
103
- }
104
-
105
- throw new Error('Cannot currently unresolve more deeply nested deps');
106
- };
107
-
108
98
  export const explodeSubtypes = (aliases, exploded, types) => {
109
99
  for (const type of types) {
110
100
  const explodedTypes = aliases.get(type);
@@ -206,14 +196,6 @@ export function* zipLanguages(tags, rootLanguage) {
206
196
  }
207
197
  }
208
198
 
209
- const safeShallowEmbed = (value) => {
210
- if (typeof value !== 'object') {
211
- return buildExpression(value);
212
- } else {
213
- return value;
214
- }
215
- };
216
-
217
199
  const __buildCall = (verb, ...args) => {
218
200
  while (args.length && args[args.length - 1] === undefined) {
219
201
  args.pop();
@@ -238,8 +220,8 @@ export const guard = (matcher, value, options) => {
238
220
  return __buildCall('guard', matcher, value, options);
239
221
  };
240
222
 
241
- export const holdForMatch = (matcher, value, options) => {
242
- return __buildCall('holdForMatch', matcher, value, options);
223
+ export const shiftMatch = (matcher, value, options) => {
224
+ return __buildCall('shiftMatch', matcher, value, options);
243
225
  };
244
226
 
245
227
  export const fail = () => {
package/lib/index.js CHANGED
@@ -6,7 +6,6 @@ export * as object from './object.js';
6
6
  export * as productions from './productions.js';
7
7
  export * as shorthand from './shorthand.js';
8
8
  export * as source from './source.js';
9
- export * as stream from './stream.js';
10
9
  export * as symbols from './symbols.js';
11
10
  export * as tree from './tree.js';
12
11
  export * as trivia from './trivia.js';
package/lib/object.js CHANGED
@@ -1,20 +1,22 @@
1
1
  import map from 'iter-tools-es/methods/map';
2
+ export {
3
+ isObject,
4
+ isArray,
5
+ isPlainObject,
6
+ isFunction,
7
+ isSymbol,
8
+ isString,
9
+ isType,
10
+ isRegex,
11
+ isPattern,
12
+ } from '@bablr/agast-helpers/object';
2
13
 
3
14
  export const { hasOwn, getOwnPropertySymbols, getPrototypeOf, fromEntries } = Object;
4
15
 
5
- export const isObject = (obj) => obj !== null && typeof obj === 'object';
6
- export const { isArray } = Array;
7
- export const isFunction = (obj) => typeof obj === 'function';
8
- export const isSymbol = (obj) => typeof obj === 'symbol';
9
- export const isString = (obj) => typeof obj === 'string';
10
- export const isRegex = (obj) => obj instanceof RegExp;
11
- export const isPattern = (obj) => isString(obj) || isRegex(obj);
12
- export const isType = (obj) => isSymbol(obj) || isString(obj);
13
- export const isPlainObject = (val) => val && getPrototypeOf(val) === Object.prototype;
14
-
15
16
  export const objectKeys = (obj) => {
16
17
  return {
17
18
  *[Symbol.iterator]() {
19
+ if (obj == null) return;
18
20
  for (let key in obj) if (hasOwn(obj, key)) yield key;
19
21
  yield* getOwnPropertySymbols(obj);
20
22
  },
@@ -24,6 +26,7 @@ export const objectKeys = (obj) => {
24
26
  export const objectValues = (obj) => {
25
27
  return {
26
28
  *[Symbol.iterator]() {
29
+ if (obj == null) return;
27
30
  for (let key in obj) if (hasOwn(obj, key)) yield obj[key];
28
31
  yield* map((sym) => obj[sym], getOwnPropertySymbols(obj));
29
32
  },
@@ -33,6 +36,7 @@ export const objectValues = (obj) => {
33
36
  export const objectEntries = (obj) => {
34
37
  return {
35
38
  *[Symbol.iterator]() {
39
+ if (obj == null) return;
36
40
  for (let key in obj) if (hasOwn(obj, key)) yield [key, obj[key]];
37
41
  yield* map((sym) => [sym, obj[sym]], getOwnPropertySymbols(obj));
38
42
  },
@@ -1,13 +1,13 @@
1
1
  /* @macrome
2
2
  * @generatedby @bablr/macrome-generator-bablr
3
- * @generatedfrom ./productions.macro.js#1fc6c6c7f7c9fc7c43a69d9729301c75581c11ea
3
+ * @generatedfrom ./productions.macro.js#a661312b1d84c6cc48eac8794f36c3b607a57892
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
7
  import { spam as m } from '@bablr/boot';
8
- import { getCooked } from '@bablr/agast-helpers/tree';
8
+ import { get, getCooked } from '@bablr/agast-helpers/tree';
9
9
  import { eat, eatMatch } from './grammar.js';
10
- import { EmbeddedMatcher } from './symbols.js';
10
+ import { Matcher } from './symbols.js';
11
11
  import { getEmbeddedMatcher } from '@bablr/agast-vm-helpers/deembed';
12
12
  import { buildPropertyMatcher } from './builders.js';
13
13
  import { buildEmbeddedMatcher } from '@bablr/agast-vm-helpers/builders';
@@ -20,10 +20,10 @@ export function* List({
20
20
  allowHoles = false,
21
21
  allowTrailingSeparator = true
22
22
  } = props;
23
- if (!['#', '@'].includes(getCooked(getEmbeddedMatcher(separator).properties.refMatcher?.node.properties.name.node.properties.content.node))) {
24
- yield eat(buildEmbeddedMatcher(buildPropertyMatcher(getEmbeddedMatcher(separator).properties.refMatcher?.node, m.ArrayNodeMatcher`[]`)));
23
+ if (getCooked(get(['refMatcher', 'name', 'content'], getEmbeddedMatcher(separator)))) {
24
+ yield eat(buildEmbeddedMatcher(buildPropertyMatcher(get('refMatcher', getEmbeddedMatcher(separator)), null, m.ArrayNodeMatcher`[]`)));
25
25
  }
26
- yield eat(buildEmbeddedMatcher(buildPropertyMatcher(getEmbeddedMatcher(Array.isArray(element) ? element[0] : element).properties.refMatcher?.node, m.ArrayNodeMatcher`[]`)));
26
+ yield eat(buildEmbeddedMatcher(buildPropertyMatcher(get('refMatcher', getEmbeddedMatcher(Array.isArray(element) ? element[0] : element)), null, m.ArrayNodeMatcher`[]`)));
27
27
  let sep,
28
28
  it,
29
29
  anySep = false;
@@ -46,7 +46,7 @@ export function* Any({
46
46
  for (const alternative of alternatives) {
47
47
  if (Array.isArray(alternative)) {
48
48
  if (yield eatMatch(...alternative)) break;
49
- } else if (alternative.type === EmbeddedMatcher) {
49
+ } else if (alternative.type === Matcher) {
50
50
  if (yield eatMatch(alternative)) break;
51
51
  } else {
52
52
  throw new Error();
@@ -74,10 +74,12 @@ export function* Optional({
74
74
  yield eatMatch(matcher);
75
75
  }
76
76
  export function* Literal({
77
- intrinsicValue
77
+ ctx,
78
+ literalValue
78
79
  }) {
79
- if (!intrinsicValue) throw new Error('Intrinsic productions must have value');
80
- yield eat(intrinsicValue);
80
+ if (!literalValue) throw new Error('Intrinsic productions must have value');
81
+ yield eat(ctx.sourceTextFor(literalValue.value));
81
82
  }
82
83
  export const Keyword = Literal;
83
- export const Punctuator = Literal;
84
+ export const Punctuator = Literal;
85
+ export const Space = Literal;
@@ -1,7 +1,7 @@
1
1
  import { spam as m } from '@bablr/boot';
2
- import { getCooked } from '@bablr/agast-helpers/tree';
2
+ import { get, getCooked } from '@bablr/agast-helpers/tree';
3
3
  import { eat, eatMatch } from './grammar.js';
4
- import { EmbeddedMatcher } from './symbols.js';
4
+ import { Matcher } from './symbols.js';
5
5
  import { getEmbeddedMatcher } from '@bablr/agast-vm-helpers/deembed';
6
6
  import { buildPropertyMatcher } from './builders.js';
7
7
  import { buildEmbeddedMatcher } from '@bablr/agast-vm-helpers/builders';
@@ -9,18 +9,12 @@ import { buildEmbeddedMatcher } from '@bablr/agast-vm-helpers/builders';
9
9
  export function* List({ props }) {
10
10
  const { element, separator, allowHoles = false, allowTrailingSeparator = true } = props;
11
11
 
12
- if (
13
- !['#', '@'].includes(
14
- getCooked(
15
- getEmbeddedMatcher(separator).properties.refMatcher?.node.properties.name.node.properties
16
- .content.node,
17
- ),
18
- )
19
- ) {
12
+ if (getCooked(get(['refMatcher', 'name', 'content'], getEmbeddedMatcher(separator)))) {
20
13
  yield eat(
21
14
  buildEmbeddedMatcher(
22
15
  buildPropertyMatcher(
23
- getEmbeddedMatcher(separator).properties.refMatcher?.node,
16
+ get('refMatcher', getEmbeddedMatcher(separator)),
17
+ null,
24
18
  m.ArrayNodeMatcher`[]`,
25
19
  ),
26
20
  ),
@@ -30,8 +24,8 @@ export function* List({ props }) {
30
24
  yield eat(
31
25
  buildEmbeddedMatcher(
32
26
  buildPropertyMatcher(
33
- getEmbeddedMatcher(Array.isArray(element) ? element[0] : element).properties.refMatcher
34
- ?.node,
27
+ get('refMatcher', getEmbeddedMatcher(Array.isArray(element) ? element[0] : element)),
28
+ null,
35
29
  m.ArrayNodeMatcher`[]`,
36
30
  ),
37
31
  ),
@@ -56,7 +50,7 @@ export function* Any({ props: { value: alternatives } }) {
56
50
  for (const alternative of alternatives) {
57
51
  if (Array.isArray(alternative)) {
58
52
  if (yield eatMatch(...alternative)) break;
59
- } else if (alternative.type === EmbeddedMatcher) {
53
+ } else if (alternative.type === Matcher) {
60
54
  if (yield eatMatch(alternative)) break;
61
55
  } else {
62
56
  throw new Error();
@@ -78,11 +72,13 @@ export function* Optional({ props: { value: matcher } }) {
78
72
  yield eatMatch(matcher);
79
73
  }
80
74
 
81
- export function* Literal({ intrinsicValue }) {
82
- if (!intrinsicValue) throw new Error('Intrinsic productions must have value');
75
+ export function* Literal({ ctx, literalValue }) {
76
+ if (!literalValue) throw new Error('Intrinsic productions must have value');
83
77
 
84
- yield eat(intrinsicValue);
78
+ yield eat(ctx.sourceTextFor(literalValue.value));
85
79
  }
86
80
  export const Keyword = Literal;
87
81
 
88
82
  export const Punctuator = Literal;
83
+
84
+ export const Space = Literal;
package/lib/source.js CHANGED
@@ -142,7 +142,7 @@ function* __sourceFromTokenStream(tags) {
142
142
  step = iter.next();
143
143
 
144
144
  if (step instanceof Promise) {
145
- yield step;
145
+ step = yield step;
146
146
  }
147
147
 
148
148
  if (step.done) break;
package/lib/tree.js CHANGED
@@ -1,8 +1,6 @@
1
1
  import { streamFromTree } from '@bablr/agast-helpers/tree';
2
-
3
- import { printPrettyCSTML as printPrettyCSTMLFromStream } from './stream.js';
2
+ import { printPrettyCSTML as printPrettyCSTMLFromStream } from '@bablr/agast-helpers/stream';
4
3
 
5
4
  export const printPrettyCSTML = (rootNode, options = {}) => {
6
- // i need a context-aware streamFromTree here to build a stream with linked Tags...?
7
5
  return printPrettyCSTMLFromStream(streamFromTree(rootNode), options);
8
6
  };
package/lib/trivia.js CHANGED
@@ -1,16 +1,139 @@
1
+ /* global WeakSet */
1
2
  import { spam as m } from '@bablr/boot';
2
3
  import { Coroutine } from '@bablr/coroutine';
3
- import { eat, eatMatch, mapProductions, o, resolveLanguage } from './grammar.js';
4
- import { EmbeddedMatcher, EmbeddedRegex, EmbeddedNode } from './symbols.js';
4
+ import { eat, eatMatch, mapOwnProductions, mapProductions, o } from './grammar.js';
5
+ import {
6
+ Matcher,
7
+ Regex,
8
+ Node,
9
+ OpenNodeTag,
10
+ CloseNodeTag,
11
+ ReferenceTag,
12
+ Property,
13
+ } from './symbols.js';
5
14
  import { buildIdentifier, buildString } from './builders.js';
6
15
  import { buildCall, buildEmbeddedInstruction } from '@bablr/agast-vm-helpers/builders';
7
16
  import { getEmbeddedInstruction } from '@bablr/agast-vm-helpers/deembed';
8
17
  import { reifyExpression } from '@bablr/agast-vm-helpers';
18
+ import { get, getCooked } from '@bablr/agast-helpers/tree';
19
+ import { buildPathSegment } from '@bablr/agast-helpers/path';
20
+
21
+ const lookbehind = (context, s) => {
22
+ let token = s.resultPath;
23
+ while (token && [OpenNodeTag, CloseNodeTag, ReferenceTag].includes(token.type)) {
24
+ const prevToken = context.getPreviousTagPath(token);
25
+ if (!prevToken) break;
26
+ token = prevToken;
27
+ }
28
+ return token;
29
+ };
30
+
31
+ const matchedResults = new WeakSet();
32
+
33
+ export const basicTriviaEnhancer = ({ triviaIsAllowed, triviaMatcher }, grammar) => {
34
+ let Wrapper_ = 'Wrapper';
35
+ let Literal_ = 'Literal';
36
+
37
+ while (grammar.prototype[Wrapper_]) Wrapper_ += '_';
38
+ while (grammar.prototype[Literal_]) Literal_ += '_';
39
+
40
+ const resultGrammar = mapOwnProductions((production) => {
41
+ return function* (props) {
42
+ const co = new Coroutine(production(props));
43
+ const { s, ctx, flags, isCover, isCovered } = props;
44
+
45
+ co.advance();
46
+
47
+ try {
48
+ while (!co.done) {
49
+ const instr = co.value;
50
+ const { verb, arguments: args = [] } = instr;
51
+ let returnValue = undefined;
52
+
53
+ switch (verb) {
54
+ case 'eat':
55
+ case 'eatMatch':
56
+ case 'match':
57
+ case 'guard': {
58
+ const { 0: matcher } = args;
59
+
60
+ if (
61
+ matcher &&
62
+ !isCovered &&
63
+ matcher.type === Matcher &&
64
+ getCooked(get(['refMatcher', 'type', 'value'], matcher.value)) !== '#'
65
+ ) {
66
+ const previous = lookbehind(ctx, s);
67
+ if (triviaIsAllowed(s) && (!previous || !matchedResults.has(previous))) {
68
+ matchedResults.add(previous);
69
+ yield eatMatch(triviaMatcher);
70
+ matchedResults.add(s.resultPath);
71
+ }
72
+ }
73
+
74
+ returnValue = returnValue || (yield instr);
75
+ break;
76
+ }
77
+
78
+ default:
79
+ returnValue = yield instr;
80
+ break;
81
+ }
82
+
83
+ co.advance(returnValue);
84
+ }
85
+
86
+ if (co.value) {
87
+ let realMatcher = reifyExpression(get('nodeMatcher', co.value.arguments[0].value));
88
+ let { flags: matcherFlags } = realMatcher;
89
+
90
+ let isNode = matcherFlags && !matcherFlags.fragment;
91
+
92
+ if (
93
+ !flags.token &&
94
+ isNode &&
95
+ !isCover &&
96
+ (!s.depths.path || (co.value && ['shift', 'shiftMatch'].includes(co.value.verb)))
97
+ ) {
98
+ if (triviaIsAllowed(s)) {
99
+ yield eatMatch(triviaMatcher);
100
+ }
101
+ }
102
+
103
+ return co.value;
104
+ } else {
105
+ if (!s.depths.path && !flags.token && !isCovered) {
106
+ if (triviaIsAllowed(s)) {
107
+ yield eatMatch(triviaMatcher);
108
+ }
109
+ }
110
+ }
111
+ } catch (e) {
112
+ co.throw(e);
113
+ throw e;
114
+ }
115
+ };
116
+ }, grammar);
117
+
118
+ return class extends resultGrammar {
119
+ *[Wrapper_]({ value: wrapped }) {
120
+ for (const instr of wrapped) {
121
+ yield getEmbeddedInstruction(instr);
122
+ }
123
+ }
124
+
125
+ *[Literal_]({ value: matcher }) {
126
+ yield eat(matcher);
127
+ }
128
+ };
129
+ };
9
130
 
10
131
  export const triviaEnhancer = (
11
132
  { triviaIsAllowed, triviaIsRequired = () => false, triviaMatcher },
12
133
  grammar,
13
134
  ) => {
135
+ if (!triviaMatcher) throw new Error();
136
+
14
137
  let Wrapper_ = 'Wrapper';
15
138
  let Literal_ = 'Literal';
16
139
 
@@ -18,9 +141,9 @@ export const triviaEnhancer = (
18
141
  while (grammar.prototype[Literal_]) Literal_ += '_';
19
142
 
20
143
  const resultGrammar = mapProductions((production) => {
21
- return function* (props) {
22
- const co = new Coroutine(production(props));
23
- const { ctx, s, isCovered, isCover, flags } = props;
144
+ return function* (args) {
145
+ const co = new Coroutine(production(args));
146
+ const { ctx, s, isCovered, isCover, isCoverBoundary, flags, mergedReference } = args;
24
147
 
25
148
  co.advance();
26
149
 
@@ -38,9 +161,9 @@ export const triviaEnhancer = (
38
161
  const { 0: matcher, 1: props, 2: options } = args;
39
162
 
40
163
  if (
41
- matcher.type === EmbeddedMatcher &&
164
+ matcher.type === Matcher &&
42
165
  ['ArrayNodeMatcher', 'NullNodeMatcher'].includes(
43
- matcher.value.properties.nodeMatcher.node.type.description,
166
+ get('nodeMatcher', matcher.value).type.description,
44
167
  )
45
168
  ) {
46
169
  returnValue = yield instr;
@@ -48,64 +171,90 @@ export const triviaEnhancer = (
48
171
  }
49
172
 
50
173
  if (
51
- matcher.type === EmbeddedRegex ||
174
+ matcher.type === Regex ||
52
175
  typeof matcher === 'string' ||
53
- (matcher.type === EmbeddedNode && matcher.value.flags.token)
176
+ (matcher.type === Node && matcher.value.flags.token)
54
177
  ) {
55
178
  if (triviaIsAllowed(s) && !flags.token) {
56
179
  let isString = typeof matcher === 'string';
57
- let wrappedMatcher = m`value: <*Literal ${
180
+ let wrappedMatcher = m`#: <*Literal ${
58
181
  isString ? buildString(matcher) : matcher.value
59
182
  } />`;
60
183
 
61
- let tmi = buildEmbeddedInstruction(
62
- triviaIsRequired() ? eat(triviaMatcher) : eatMatch(triviaMatcher),
63
- );
184
+ let tmi = buildEmbeddedInstruction(eatMatch(triviaMatcher));
64
185
 
65
- let result = yield buildCall(verb, m`<_${buildIdentifier(Wrapper_)} />`, [
186
+ let result = yield buildCall(verb, m`<__${buildIdentifier(Wrapper_)} />`, [
66
187
  tmi,
67
188
  buildEmbeddedInstruction(eat(wrappedMatcher, props, options)),
68
189
  ]);
69
190
 
70
- returnValue = result?.get('value');
191
+ let prop = null;
192
+
193
+ if (result) {
194
+ for (let child of result.tagsInner) {
195
+ if (child.type === Property) prop = child.value;
196
+ }
197
+ }
198
+
199
+ returnValue = prop?.node;
71
200
  } else {
72
201
  returnValue = yield instr;
73
202
  }
74
203
  break;
75
204
  }
76
205
 
77
- let { name } = reifyExpression(matcher.value.properties.refMatcher?.node) || {};
78
- let realMatcher = reifyExpression(matcher.value.properties.nodeMatcher?.node);
206
+ let { type: refType } = reifyExpression(get('refMatcher', matcher.value)) || {};
207
+ let realMatcher = reifyExpression(get('nodeMatcher', matcher.value));
79
208
  let { flags: matcherFlags } = realMatcher;
80
209
 
81
210
  let isNode = matcherFlags && !matcherFlags.fragment;
82
211
  let isCoverBoundary = matcherFlags && (matcherFlags.cover || (isNode && !isCovered));
83
212
  if (
84
213
  matcher &&
85
- (matcher.type !== EmbeddedMatcher || name !== '#') &&
214
+ (matcher.type !== Matcher || refType !== '#') &&
86
215
  !s.holding &&
87
216
  !flags.token &&
88
217
  isCoverBoundary
89
218
  ) {
90
219
  if (triviaIsAllowed(s)) {
220
+ let { nodeMatcher } = reifyExpression(matcher.value);
221
+
91
222
  let tmi = buildEmbeddedInstruction(
92
- triviaIsRequired() ? eat(triviaMatcher) : eatMatch(triviaMatcher),
223
+ triviaIsRequired(s, nodeMatcher) ? eat(triviaMatcher) : eatMatch(triviaMatcher),
93
224
  );
94
225
 
95
226
  let result = yield buildCall(
96
227
  verb,
97
- m`<_${buildIdentifier(Wrapper_)} />`,
228
+ m`<__${buildIdentifier(Wrapper_)} />`,
98
229
  [tmi, buildEmbeddedInstruction(eat(matcher, props, options))],
99
230
  o({ bind: options?.value.bind ?? false }),
100
231
  );
101
232
  let trivialResult = result;
102
233
 
103
234
  if (result && !result.isNull) {
104
- if (matcher.value.properties.refMatcher) {
105
- let path = ctx
106
- .sourceTextFor(matcher.value.properties.refMatcher.node)
107
- .slice(0, -1);
108
- result = result.get(path);
235
+ if (isNode || isCoverBoundary) {
236
+ let refMatcher = get('refMatcher', matcher.value);
237
+
238
+ let name, isArray;
239
+
240
+ if (!refMatcher) {
241
+ ({ name, isArray } = mergedReference);
242
+ } else {
243
+ let name_ = get('name', refMatcher);
244
+ let openIndexToken = get('openIndexToken', refMatcher);
245
+ name = name_ && ctx.sourceTextFor(name_);
246
+ isArray = !!openIndexToken;
247
+ }
248
+
249
+ if (name) {
250
+ let pathSpec = name;
251
+
252
+ if (isArray) {
253
+ pathSpec = buildPathSegment(name, -1);
254
+ }
255
+
256
+ result = result.get([pathSpec]);
257
+ }
109
258
  }
110
259
 
111
260
  result = result && result.merge(trivialResult);
@@ -128,14 +277,13 @@ export const triviaEnhancer = (
128
277
  co.advance(returnValue);
129
278
  }
130
279
 
131
- if (!s.depths.path && !flags.token && !(isCovered || isCover)) {
280
+ if (!flags.token && !(isCovered || isCover)) {
132
281
  if (triviaIsAllowed(s)) {
133
282
  yield eatMatch(triviaMatcher);
134
283
  }
135
284
  } else if (co.value) {
136
- let realMatcher = reifyExpression(
137
- co.value.arguments[0].value.properties.nodeMatcher.node,
138
- );
285
+ let matcher = co.value.arguments[0];
286
+ let realMatcher = reifyExpression(get('nodeMatcher', matcher.value));
139
287
  let { flags: matcherFlags } = realMatcher;
140
288
 
141
289
  let isNode = matcherFlags && !matcherFlags.fragment;
@@ -145,16 +293,48 @@ export const triviaEnhancer = (
145
293
  isNode &&
146
294
  !isCover &&
147
295
  co.value &&
148
- ['holdFor', 'holdForMatch'].includes(co.value.verb)
296
+ ['shift', 'shiftMatch'].includes(co.value.verb)
149
297
  ) {
150
298
  if (triviaIsAllowed(s)) {
151
299
  let tmi = buildEmbeddedInstruction(
152
300
  triviaIsRequired() ? eat(triviaMatcher) : eatMatch(triviaMatcher),
153
301
  );
154
- return buildCall(co.value.verb, m`<_${buildIdentifier(Wrapper_)} />`, [
302
+ let result = yield buildCall(co.value.verb, m`<__${buildIdentifier(Wrapper_)} />`, [
155
303
  tmi,
156
304
  buildEmbeddedInstruction(eat(co.value.arguments[0], co.value.arguments[1])),
157
305
  ]);
306
+
307
+ let trivialResult = result;
308
+
309
+ if (result && !result.isNull) {
310
+ if (isNode || isCoverBoundary) {
311
+ let refMatcher = get('refMatcher', matcher.value);
312
+
313
+ let name, isArray;
314
+
315
+ if (!refMatcher) {
316
+ ({ name, isArray } = mergedReference);
317
+ } else {
318
+ let name = get('name', refMatcher);
319
+ let openIndexToken = get('openIndexToken', refMatcher);
320
+ name = name && ctx.sourceTextFor(name);
321
+ isArray = !!openIndexToken;
322
+ }
323
+
324
+ if (name) {
325
+ let pathSpec = name;
326
+
327
+ if (isArray) {
328
+ pathSpec = buildPathSegment(name, -1);
329
+ }
330
+
331
+ result = result.get([pathSpec]);
332
+ }
333
+ }
334
+
335
+ result = result && result.merge(trivialResult);
336
+ }
337
+ return result;
158
338
  }
159
339
  }
160
340
  }
@@ -194,8 +374,8 @@ export const triviaEnhancer = (
194
374
  }
195
375
  }
196
376
 
197
- *[Literal_]({ intrinsicValue }) {
198
- yield eat(intrinsicValue);
377
+ *[Literal_]({ literalValue }) {
378
+ yield eat(literalValue);
199
379
  }
200
380
  };
201
381
  };