@bablr/bablr-vm 0.15.0 → 0.16.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/spans.js CHANGED
@@ -10,7 +10,7 @@ export function updateSpans(ctx, s, node, phase) {
10
10
 
11
11
  if (flags.intrinsic) {
12
12
  if (s.path && balanced) {
13
- s.spans = s.spans.push({
13
+ s.spans = s.spans.push({
14
14
  type: 'Lexical',
15
15
  name: balancedSpan || s.span.name,
16
16
  path: s.path,
@@ -37,7 +37,7 @@ export function updateSpans(ctx, s, node, phase) {
37
37
 
38
38
  if (!s.balanced.size) throw new Error();
39
39
 
40
- if (!balancedNode.openTag.value.attributes.balanced) {
40
+ if (!balancedNode.children[0].value.attributes.balanced) {
41
41
  throw new Error();
42
42
  }
43
43
 
@@ -47,7 +47,7 @@ export function updateSpans(ctx, s, node, phase) {
47
47
  }
48
48
 
49
49
  if (balanced) {
50
- s.balanced = s.balanced.push(ctx.nodeForTag(s.result));
50
+ s.balanced = s.balanced.push(s.nodeForTag(s.result));
51
51
  }
52
52
 
53
53
  if (innerSpan) {
@@ -63,8 +63,7 @@ export function updateSpans(ctx, s, node, phase) {
63
63
  }
64
64
 
65
65
  case 'close': {
66
- const { openTag, flags } = node;
67
- const { attributes } = openTag.value;
66
+ const { flags, attributes } = node;
68
67
  const { balancedSpan, span: innerSpan, closeSpan, balanced } = attributes || {};
69
68
 
70
69
  if (balanced && !flags.intrinsic) {
package/lib/state.js CHANGED
@@ -3,6 +3,7 @@ import { WeakStackFrame } from '@bablr/weak-stack';
3
3
  import { getCooked } from '@bablr/agast-helpers/stream';
4
4
  import { match, guardWithPattern } from './utils/pattern.js';
5
5
  import { facades, actuals } from './facades.js';
6
+ import { reifyExpression } from '@bablr/agast-vm-helpers';
6
7
 
7
8
  export const StateFacade = class BABLRStateFacade {
8
9
  constructor(state) {
@@ -48,6 +49,18 @@ export const StateFacade = class BABLRStateFacade {
48
49
  get status() {
49
50
  return actuals.get(this).status;
50
51
  }
52
+
53
+ nodeForPath(path) {
54
+ return actuals.get(this).nodeForPath(path);
55
+ }
56
+
57
+ pathForTag(tag) {
58
+ return actuals.get(this).pathForTag(tag);
59
+ }
60
+
61
+ nodeForTag(tag) {
62
+ return actuals.get(this).nodeForTag(tag);
63
+ }
51
64
  };
52
65
 
53
66
  export const State = class BABLRState extends WeakStackFrame {
@@ -109,10 +122,37 @@ export const State = class BABLRState extends WeakStackFrame {
109
122
  return !!this.parent;
110
123
  }
111
124
 
125
+ nodeForPath(path) {
126
+ return this.agast.nodeForPath(path);
127
+ }
128
+
129
+ pathForTag(tag) {
130
+ return this.agast.pathForTag(tag);
131
+ }
132
+
133
+ nodeForTag(tag) {
134
+ return this.agast.nodeForTag(tag);
135
+ }
136
+
112
137
  guardedMatch(pattern) {
113
- let { span, spans, source } = this;
138
+ let { span, spans, source, node } = this;
114
139
  let { guard } = span;
115
140
 
141
+ if (pattern.type === 'EmbeddedNode') {
142
+ pattern = reifyExpression(pattern.value);
143
+ }
144
+
145
+ if (
146
+ span.type === 'Lexical' &&
147
+ (node.flags.token
148
+ ? node.attributes.balancer || node.attributes.balanced
149
+ : pattern.attributes?.balancer)
150
+ ) {
151
+ // also check that the open node starts a lexical span?
152
+ span = spans.prev.value;
153
+ ({ guard } = span);
154
+ }
155
+
116
156
  if (pattern?.intrinsicValue) {
117
157
  // if (pattern.type === 'OpenNodeTag') {
118
158
 
@@ -120,15 +160,11 @@ export const State = class BABLRState extends WeakStackFrame {
120
160
  // pattern = pattern.value;
121
161
  // }
122
162
 
123
- ({ guard } = span);
163
+ pattern = pattern.intrinsicValue || getCooked(pattern.children);
124
164
 
125
- if (span.type === 'Lexical' && pattern.attributes.balancer) {
126
- // also check that the open node starts a lexical span?
127
- span = spans.prev.value;
128
- ({ guard } = span);
165
+ if (pattern.type === 'String') {
166
+ pattern = reifyExpression(pattern);
129
167
  }
130
-
131
- pattern = pattern.intrinsicValue || getCooked(pattern.children);
132
168
  }
133
169
 
134
170
  return match(pattern, guard ? guardWithPattern(guard, source) : source);
package/lib/strategy.js CHANGED
@@ -1,12 +1,20 @@
1
1
  import { Coroutine } from '@bablr/coroutine';
2
- import { buildCall, buildNull, buildReference, reifyExpression } from '@bablr/agast-vm-helpers';
2
+ import {
3
+ buildCall,
4
+ buildReference,
5
+ buildNull,
6
+ buildEmbeddedTag,
7
+ } from '@bablr/agast-helpers/builders';
3
8
  import { StreamGenerator } from '@bablr/agast-helpers/stream';
9
+ import { getOpenTag } from '@bablr/agast-helpers/tree';
4
10
  import { buildTokens } from './utils/token.js';
5
11
  import { formatType } from './utils/format.js';
6
12
  import { facades } from './facades.js';
7
13
  import { State } from './state.js';
8
14
  import { updateSpans } from './spans.js';
9
15
 
16
+ const { hasOwn } = Object;
17
+
10
18
  export const createBablrStrategy = (rootSource, strategy) => {
11
19
  return (ctx, agastState) => {
12
20
  return new StreamGenerator(__strategy(ctx, rootSource, agastState, strategy));
@@ -39,53 +47,32 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
39
47
 
40
48
  if (co.done) break;
41
49
 
42
- const sourceInstr = co.value;
43
- const instr = reifyExpression(sourceInstr);
50
+ const instr = co.value;
44
51
  let returnValue = undefined;
45
52
 
46
53
  const { verb } = instr;
47
54
 
48
55
  switch (verb) {
49
56
  case 'advance': {
50
- const {
51
- arguments: { 0: terminal = [] },
52
- } = instr;
57
+ const { arguments: { 0: embeddedTerminal } = [] } = instr;
58
+
59
+ const terminal = embeddedTerminal.value;
53
60
 
54
61
  switch (terminal?.type || 'Null') {
55
62
  case 'DoctypeTag': {
56
- const doctypeTag = yield sourceInstr;
63
+ const doctypeTag = yield instr;
57
64
 
58
65
  returnValue = doctypeTag;
59
66
  break;
60
67
  }
61
68
 
62
69
  case 'OpenNodeTag': {
63
- const { type, intrinsicValue } = terminal.value;
70
+ const { type } = terminal.value;
64
71
 
65
- const openTag = yield sourceInstr;
72
+ const openTag = yield instr;
66
73
 
67
74
  if (type) {
68
- let intrinsicResult = intrinsicValue && s.guardedMatch(terminal.value);
69
-
70
- if (intrinsicResult instanceof Promise) {
71
- intrinsicResult = yield intrinsicResult;
72
- }
73
-
74
- updateSpans(ctx, s, ctx.nodeForTag(openTag), 'open');
75
-
76
- if (intrinsicValue) {
77
- if (!intrinsicResult) {
78
- throw new Error('advance failed to match an intrinsic node');
79
- }
80
-
81
- const sourceStep = s.source.advance(intrinsicResult.length);
82
-
83
- if (sourceStep instanceof Promise) {
84
- yield sourceStep;
85
- }
86
-
87
- updateSpans(ctx, s, ctx.nodeForTag(openTag), 'close');
88
- }
75
+ updateSpans(ctx, s, s.node, 'open');
89
76
  }
90
77
 
91
78
  returnValue = openTag;
@@ -95,7 +82,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
95
82
  case 'CloseNodeTag': {
96
83
  const { node } = s;
97
84
 
98
- const endTag = yield sourceInstr;
85
+ const endTag = yield instr;
99
86
 
100
87
  if (s.path) {
101
88
  updateSpans(ctx, s, node, 'close');
@@ -129,7 +116,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
129
116
  sourceStep = yield sourceStep;
130
117
  }
131
118
 
132
- returnValue = yield sourceInstr;
119
+ returnValue = yield instr;
133
120
  } else {
134
121
  throw new Error('Failed to advance literal');
135
122
  }
@@ -148,7 +135,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
148
135
  }
149
136
  }
150
137
 
151
- returnValue = yield sourceInstr;
138
+ returnValue = yield instr;
152
139
  } else {
153
140
  throw new Error('Failed to advance gap');
154
141
  }
@@ -158,12 +145,12 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
158
145
  case 'Shift': {
159
146
  s.source.shift();
160
147
 
161
- returnValue = yield sourceInstr;
148
+ returnValue = yield instr;
162
149
  break;
163
150
  }
164
151
 
165
152
  default: {
166
- returnValue = yield sourceInstr;
153
+ returnValue = yield instr;
167
154
  break;
168
155
  }
169
156
  }
@@ -180,7 +167,9 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
180
167
  result = yield result;
181
168
  }
182
169
 
183
- returnValue = result && ctx.buildRange(buildTokens(result));
170
+ const tokens = result && ctx.buildRange(buildTokens(result));
171
+
172
+ returnValue = tokens || null;
184
173
  break;
185
174
  }
186
175
 
@@ -188,7 +177,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
188
177
  const baseState = s;
189
178
  let { source, agast, balanced, spans, node } = baseState;
190
179
 
191
- agast = yield sourceInstr;
180
+ agast = yield instr;
192
181
 
193
182
  s = s.push(source.branch(), agast, balanced, spans);
194
183
 
@@ -205,7 +194,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
205
194
 
206
195
  s.status = 'accepted';
207
196
 
208
- const agastState = yield sourceInstr;
197
+ const agastState = yield instr;
209
198
 
210
199
  s = s.parent;
211
200
 
@@ -228,27 +217,37 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
228
217
 
229
218
  s.status = 'rejected';
230
219
 
231
- yield sourceInstr;
220
+ yield instr;
232
221
 
233
222
  s = s.parent;
234
223
 
235
224
  if (s.path.depth && rejectedState.path.depth > s.path.depth) {
236
225
  // const didShift = rejectedState.node.at(sNodeDepth) === s.node;
237
226
  const didShift =
238
- ctx.nodeForPath(s.path) && !ctx.nodeForPath(rejectedState.path.at(s.path.depth));
227
+ s.nodeForPath(s.path) && !s.nodeForPath(rejectedState.path.at(s.path.depth));
239
228
  const lowPath = rejectedState.path.at(
240
- Math.min(s.path.depth + (didShift ? 0 : 1), rejectedState.path.depth),
229
+ Math.min(
230
+ s.path.depth + (didShift || s.result.type === 'Reference' ? 0 : 1),
231
+ rejectedState.path.depth,
232
+ ),
241
233
  );
242
234
  const lowNode = s.node || s.parentNode;
243
235
 
244
236
  const { name, isArray } = lowPath.reference?.value || {};
245
237
 
246
- if (!didShift && !lowNode.resolver.counters.has(name)) {
247
- if (!lowNode.openTag?.value.flags.trivia && !lowNode.openTag?.value.flags.escape) {
248
- yield buildCall('advance', buildReference(name, isArray));
238
+ if (
239
+ !didShift &&
240
+ !hasOwn(lowNode.properties, name) &&
241
+ !(s.result.type === 'Reference' && s.result.value.name === name)
242
+ ) {
243
+ if (
244
+ !getOpenTag(lowNode)?.value.flags.trivia &&
245
+ !getOpenTag(lowNode)?.value.flags.escape
246
+ ) {
247
+ yield buildCall('advance', buildEmbeddedTag(buildReference(name, isArray)));
249
248
  }
250
249
 
251
- yield buildCall('advance', buildNull());
250
+ yield buildCall('advance', buildEmbeddedTag(buildNull()));
252
251
  }
253
252
  }
254
253
 
@@ -262,7 +261,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
262
261
 
263
262
  case 'write':
264
263
  case 'bindAttribute': {
265
- returnValue = yield sourceInstr;
264
+ returnValue = yield instr;
266
265
  break;
267
266
  }
268
267
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bablr/bablr-vm",
3
3
  "description": "A VM for parsing using BABLR languages",
4
- "version": "0.15.0",
4
+ "version": "0.16.0",
5
5
  "author": "Conrad Buck<conartist6@gmail.com>",
6
6
  "type": "module",
7
7
  "files": [
@@ -12,11 +12,11 @@
12
12
  },
13
13
  "sideEffects": false,
14
14
  "dependencies": {
15
- "@bablr/agast-helpers": "0.2.0",
16
- "@bablr/agast-vm-helpers": "0.2.0",
15
+ "@bablr/agast-helpers": "0.3.1",
16
+ "@bablr/agast-vm-helpers": "0.3.1",
17
17
  "@bablr/coroutine": "0.1.0",
18
- "@bablr/helpers": "0.17.0",
19
- "@bablr/regex-vm": "0.5.1",
18
+ "@bablr/helpers": "0.18.0",
19
+ "@bablr/regex-vm": "0.6.0",
20
20
  "@bablr/weak-stack": "0.1.0",
21
21
  "@iter-tools/imm-stack": "1.1.0",
22
22
  "iter-tools-es": "^7.5.3"