@bablr/bablr-vm 0.14.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/source.js CHANGED
@@ -168,6 +168,10 @@ export const SourceFacade = class BABLRSourceFacade {
168
168
  return actuals.get(this).done;
169
169
  }
170
170
 
171
+ get value() {
172
+ return actuals.get(this).value;
173
+ }
174
+
171
175
  get index() {
172
176
  return actuals.get(this).index;
173
177
  }
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) {
@@ -33,6 +34,10 @@ export const StateFacade = class BABLRStateFacade {
33
34
  return actuals.get(this).node;
34
35
  }
35
36
 
37
+ get parentNode() {
38
+ return actuals.get(this).parentNode;
39
+ }
40
+
36
41
  get source() {
37
42
  return facades.get(actuals.get(this).source);
38
43
  }
@@ -44,6 +49,18 @@ export const StateFacade = class BABLRStateFacade {
44
49
  get status() {
45
50
  return actuals.get(this).status;
46
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
+ }
47
64
  };
48
65
 
49
66
  export const State = class BABLRState extends WeakStackFrame {
@@ -85,6 +102,10 @@ export const State = class BABLRState extends WeakStackFrame {
85
102
  return this.agast.node;
86
103
  }
87
104
 
105
+ get parentNode() {
106
+ return this.agast.parentNode;
107
+ }
108
+
88
109
  get holding() {
89
110
  return this.agast.holding;
90
111
  }
@@ -101,10 +122,37 @@ export const State = class BABLRState extends WeakStackFrame {
101
122
  return !!this.parent;
102
123
  }
103
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
+
104
137
  guardedMatch(pattern) {
105
- let { span, spans, source } = this;
138
+ let { span, spans, source, node } = this;
106
139
  let { guard } = span;
107
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
+
108
156
  if (pattern?.intrinsicValue) {
109
157
  // if (pattern.type === 'OpenNodeTag') {
110
158
 
@@ -112,15 +160,11 @@ export const State = class BABLRState extends WeakStackFrame {
112
160
  // pattern = pattern.value;
113
161
  // }
114
162
 
115
- ({ guard } = span);
163
+ pattern = pattern.intrinsicValue || getCooked(pattern.children);
116
164
 
117
- if (span.type === 'Lexical' && pattern.attributes.balancer) {
118
- // also check that the open node starts a lexical span?
119
- span = spans.prev.value;
120
- ({ guard } = span);
165
+ if (pattern.type === 'String') {
166
+ pattern = reifyExpression(pattern);
121
167
  }
122
-
123
- pattern = pattern.intrinsicValue || getCooked(pattern.children);
124
168
  }
125
169
 
126
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, intrinsicValue ? ctx.nodeForTag(openTag) : s.node, '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,11 +177,13 @@ 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
 
195
- resolvedLanguages.set(s.node, resolvedLanguages.get(node));
184
+ if (node) {
185
+ resolvedLanguages.set(s.node, resolvedLanguages.get(node));
186
+ }
196
187
 
197
188
  returnValue = facades.get(s);
198
189
  break;
@@ -203,7 +194,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
203
194
 
204
195
  s.status = 'accepted';
205
196
 
206
- const agastState = yield sourceInstr;
197
+ const agastState = yield instr;
207
198
 
208
199
  s = s.parent;
209
200
 
@@ -226,25 +217,37 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
226
217
 
227
218
  s.status = 'rejected';
228
219
 
229
- yield sourceInstr;
220
+ yield instr;
230
221
 
231
222
  s = s.parent;
232
223
 
233
224
  if (s.path.depth && rejectedState.path.depth > s.path.depth) {
234
- const didShift = rejectedState.node.at(s.node.depth) === s.node;
225
+ // const didShift = rejectedState.node.at(sNodeDepth) === s.node;
226
+ const didShift =
227
+ s.nodeForPath(s.path) && !s.nodeForPath(rejectedState.path.at(s.path.depth));
235
228
  const lowPath = rejectedState.path.at(
236
- 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
+ ),
237
233
  );
238
- const lowNode = s.node;
234
+ const lowNode = s.node || s.parentNode;
239
235
 
240
236
  const { name, isArray } = lowPath.reference?.value || {};
241
237
 
242
- if (lowPath.depth === lowNode.depth + 1 && !lowNode.resolver.counters.has(name)) {
243
- if (!lowNode.openTag?.value.flags.trivia && !lowNode.openTag?.value.flags.escape) {
244
- 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)));
245
248
  }
246
249
 
247
- yield buildCall('advance', buildNull());
250
+ yield buildCall('advance', buildEmbeddedTag(buildNull()));
248
251
  }
249
252
  }
250
253
 
@@ -258,7 +261,7 @@ const __strategy = function* bablrStrategy(ctx, rootSource, agastState, strategy
258
261
 
259
262
  case 'write':
260
263
  case 'bindAttribute': {
261
- returnValue = yield sourceInstr;
264
+ returnValue = yield instr;
262
265
  break;
263
266
  }
264
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.14.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.1.6",
16
- "@bablr/agast-vm-helpers": "0.1.5",
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.16.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"