tangled
alpha
login
or
join now
kitten.sh
/
reghex
0
fork
atom
Mirror: The magical sticky regex-based parser generator 🧙
0
fork
atom
overview
issues
pulls
pipelines
Update codegen to use a combined __private object of methods
kitten.sh
5 years ago
ca927f19
8b12428d
+129
-111
5 changed files
expand all
collapse all
unified
split
src
babel
__snapshots__
plugin.test.js.snap
sharedIds.js
transform.js
codegen.js
core.js
+76
-43
src/babel/__snapshots__/plugin.test.js.snap
···
5
5
6
6
var _reghex = require(\\"reghex\\");
7
7
8
8
-
var _node_expression = (0, _reghex._pattern)(1),
9
9
-
_node_expression2 = (0, _reghex._pattern)(2);
8
8
+
var _node_expression = _reghex.__private.pattern(1),
9
9
+
_node_expression2 = _reghex.__private.pattern(2);
10
10
11
11
const node = function (state) {
12
12
-
var y1 = state.y;
12
12
+
var y1 = state.y,
13
13
+
x1 = state.x;
13
14
var node = [];
14
15
var x;
15
16
16
16
-
if (x = (0, _reghex._exec)(state, _node_expression)) {
17
17
+
if (x = _reghex.__private.exec(state, _node_expression)) {
17
18
node.push(x);
18
19
} else {
19
20
state.y = y1;
21
21
+
state.x = x1;
20
22
return;
21
23
}
22
24
23
23
-
if (x = (0, _reghex._exec)(state, _node_expression2)) {
25
25
+
if (x = _reghex.__private.exec(state, _node_expression2)) {
24
26
node.push(x);
25
27
} else {
26
28
state.y = y1;
29
29
+
state.x = x1;
27
30
return;
28
31
}
29
32
···
38
41
`;
39
42
40
43
exports[`works with local recursion 1`] = `
41
41
-
"import { match as m, tag, _exec, _pattern } from 'reghex';
44
44
+
"import { match as m, tag, __private } from 'reghex';
42
45
43
43
-
var _inner_expression = _pattern(/inner/);
46
46
+
var _inner_expression = __private.pattern(/inner/);
44
47
45
48
const inner = function (state) {
46
46
-
var y1 = state.y;
49
49
+
var y1 = state.y,
50
50
+
x1 = state.x;
47
51
var node = [];
48
52
var x;
49
53
50
50
-
if (x = _exec(state, _inner_expression)) {
54
54
+
if (x = __private.exec(state, _inner_expression)) {
51
55
node.push(x);
52
56
} else {
53
57
state.y = y1;
58
58
+
state.x = x1;
54
59
return;
55
60
}
56
61
···
59
64
};
60
65
61
66
const node = function (state) {
62
62
-
var y1 = state.y;
67
67
+
var y1 = state.y,
68
68
+
x1 = state.x;
63
69
var node = [];
64
70
var x;
65
71
···
67
73
node.push(x);
68
74
} else {
69
75
state.y = y1;
76
76
+
state.x = x1;
70
77
return;
71
78
}
72
79
···
76
83
`;
77
84
78
85
exports[`works with non-capturing groups 1`] = `
79
79
-
"import { match, _exec, _pattern, tag as _tag } from 'reghex';
86
86
+
"import { match, __private } from 'reghex';
80
87
81
81
-
var _node_expression = _pattern(1),
82
82
-
_node_expression2 = _pattern(2),
83
83
-
_node_expression3 = _pattern(3);
88
88
+
var _node_expression = __private.pattern(1),
89
89
+
_node_expression2 = __private.pattern(2),
90
90
+
_node_expression3 = __private.pattern(3);
84
91
85
92
const node = function (state) {
86
86
-
var y1 = state.y;
93
93
+
var y1 = state.y,
94
94
+
x1 = state.x;
87
95
var node = [];
88
96
var x;
89
97
90
90
-
if (x = _exec(state, _node_expression)) {
98
98
+
if (x = __private.exec(state, _node_expression)) {
91
99
node.push(x);
92
100
} else {
93
101
state.y = y1;
102
102
+
state.x = x1;
94
103
return;
95
104
}
96
105
···
98
107
99
108
alt_3: {
100
109
block_3: {
101
101
-
var y3 = state.y;
110
110
+
var y3 = state.y,
111
111
+
x3 = state.x;
102
112
103
103
-
if (x = _exec(state, _node_expression2)) {
113
113
+
if (x = __private.exec(state, _node_expression2)) {
104
114
node.push(x);
105
115
} else {
106
116
state.y = y3;
117
117
+
state.x = x3;
107
118
node.length = ln2;
108
119
break block_3;
109
120
}
···
112
123
}
113
124
114
125
loop_3: for (var j3 = 0; 1; j3++) {
115
115
-
var y3 = state.y;
126
126
+
var y3 = state.y,
127
127
+
x3 = state.x;
116
128
117
117
-
if (x = _exec(state, _node_expression3)) {} else {
129
129
+
if (x = __private.exec(state, _node_expression3)) {} else {
118
130
if (j3) {
119
131
state.y = y3;
132
132
+
state.x = x3;
120
133
break loop_3;
121
134
} else {}
122
135
123
136
state.y = y1;
137
137
+
state.x = x1;
124
138
node.length = ln2;
125
139
return;
126
140
}
···
133
147
`;
134
148
135
149
exports[`works with self-referential thunks 1`] = `
136
136
-
"import { match, tag, _exec, _pattern } from 'reghex';
150
150
+
"import { match, tag, __private } from 'reghex';
137
151
138
152
const inner = function (state) {
139
139
-
var y1 = state.y;
153
153
+
var y1 = state.y,
154
154
+
x1 = state.x;
140
155
var node = [];
141
156
var x;
142
157
···
144
159
node.push(x);
145
160
} else {
146
161
state.y = y1;
162
162
+
state.x = x1;
147
163
return;
148
164
}
149
165
···
152
168
};
153
169
154
170
const node = function (state) {
155
155
-
var y1 = state.y;
171
171
+
var y1 = state.y,
172
172
+
x1 = state.x;
156
173
var node = [];
157
174
var x;
158
175
···
160
177
node.push(x);
161
178
} else {
162
179
state.y = y1;
180
180
+
state.x = x1;
163
181
return;
164
182
}
165
183
···
169
187
`;
170
188
171
189
exports[`works with standard features 1`] = `
172
172
-
"import { match, _exec, _pattern, tag as _tag } from \\"reghex\\";
190
190
+
"import { match, __private } from \\"reghex\\";
173
191
174
174
-
var _node_expression = _pattern(1),
175
175
-
_node_expression2 = _pattern(2),
176
176
-
_node_expression3 = _pattern(3),
177
177
-
_node_expression4 = _pattern(4),
178
178
-
_node_expression5 = _pattern(5);
192
192
+
var _node_expression = __private.pattern(1),
193
193
+
_node_expression2 = __private.pattern(2),
194
194
+
_node_expression3 = __private.pattern(3),
195
195
+
_node_expression4 = __private.pattern(4),
196
196
+
_node_expression5 = __private.pattern(5);
179
197
180
198
const node = function (state) {
181
181
-
var y1 = state.y;
199
199
+
var y1 = state.y,
200
200
+
x1 = state.x;
182
201
var node = [];
183
202
var x;
184
203
185
204
alt_2: {
186
205
block_2: {
187
187
-
var y2 = state.y;
206
206
+
var y2 = state.y,
207
207
+
x2 = state.x;
188
208
189
209
loop_2: for (var j2 = 0; 1; j2++) {
190
190
-
var y2 = state.y;
210
210
+
var y2 = state.y,
211
211
+
x2 = state.x;
191
212
192
192
-
if (x = _exec(state, _node_expression)) {
213
213
+
if (x = __private.exec(state, _node_expression)) {
193
214
node.push(x);
194
215
} else {
195
216
if (j2) {
196
217
state.y = y2;
218
218
+
state.x = x2;
197
219
break loop_2;
198
220
} else {}
199
221
200
222
state.y = y2;
223
223
+
state.x = x2;
201
224
break block_2;
202
225
}
203
226
}
···
206
229
}
207
230
208
231
loop_2: for (var j2 = 0; 1; j2++) {
209
209
-
var y2 = state.y;
232
232
+
var y2 = state.y,
233
233
+
x2 = state.x;
210
234
211
211
-
if (x = _exec(state, _node_expression2)) {
235
235
+
if (x = __private.exec(state, _node_expression2)) {
212
236
node.push(x);
213
237
} else {
214
238
if (j2) {
215
239
state.y = y2;
240
240
+
state.x = x2;
216
241
break loop_2;
217
242
} else {}
218
243
219
244
state.y = y1;
245
245
+
state.x = x1;
220
246
return;
221
247
}
222
248
}
223
249
224
250
loop_2: for (;;) {
225
225
-
var y2 = state.y;
251
251
+
var y2 = state.y,
252
252
+
x2 = state.x;
226
253
var ln2 = node.length;
227
254
228
228
-
if (x = _exec(state, _node_expression3)) {
255
255
+
if (x = __private.exec(state, _node_expression3)) {
229
256
node.push(x);
230
257
} else {
231
258
state.y = y2;
259
259
+
state.x = x2;
232
260
node.length = ln2;
233
261
break loop_2;
234
262
}
235
263
236
236
-
var y4 = state.y;
264
264
+
var y4 = state.y,
265
265
+
x4 = state.x;
237
266
238
238
-
if (x = _exec(state, _node_expression4)) {
267
267
+
if (x = __private.exec(state, _node_expression4)) {
239
268
node.push(x);
240
269
} else {
241
270
state.y = y4;
271
271
+
state.x = x4;
242
272
}
243
273
244
244
-
if (x = _exec(state, _node_expression5)) {
274
274
+
if (x = __private.exec(state, _node_expression5)) {
245
275
node.push(x);
246
276
} else {
247
277
state.y = y2;
278
278
+
state.x = x2;
248
279
node.length = ln2;
249
280
break loop_2;
250
281
}
···
257
288
`;
258
289
259
290
exports[`works with transform functions 1`] = `
260
260
-
"import { match, _exec, _pattern, tag as _tag } from 'reghex';
291
291
+
"import { match, __private } from 'reghex';
261
292
262
293
var _inner_transform = x => x;
263
294
264
295
const first = function (state) {
265
265
-
var y1 = state.y;
296
296
+
var y1 = state.y,
297
297
+
x1 = state.x;
266
298
var node = [];
267
299
var x;
268
300
node.tag = 'inner';
···
272
304
const transform = x => x;
273
305
274
306
const second = function (state) {
275
275
-
var y1 = state.y;
307
307
+
var y1 = state.y,
308
308
+
x1 = state.x;
276
309
var node = [];
277
310
var x;
278
311
node.tag = 'node';
-20
src/babel/sharedIds.js
···
1
1
-
export class SharedIds {
2
2
-
constructor(t) {
3
3
-
this.t = t;
4
4
-
this.execId = t.identifier('_exec');
5
5
-
this.patternId = t.identifier('_pattern');
6
6
-
this.tagId = t.identifier('tag');
7
7
-
}
8
8
-
9
9
-
get exec() {
10
10
-
return this.t.identifier(this.execId.name);
11
11
-
}
12
12
-
13
13
-
get pattern() {
14
14
-
return this.t.identifier(this.patternId.name);
15
15
-
}
16
16
-
17
17
-
get tag() {
18
18
-
return this.t.identifier(this.tagId.name);
19
19
-
}
20
20
-
}
+12
-18
src/babel/transform.js
···
1
1
+
import { astRoot, _private } from '../codegen';
1
2
import { parse } from '../parser';
2
2
-
import { astRoot } from '../codegen';
3
3
-
import { SharedIds } from './sharedIds';
4
3
5
4
export function makeHelpers({ types: t, template }) {
6
5
const regexPatternsRe = /^[()\[\]|.+?*]|[^\\][()\[\]|.+?*$^]|\\[wdsWDS]/;
7
6
const importSourceRe = /reghex$|^reghex\/macro/;
8
7
const importName = 'reghex';
9
9
-
const ids = new SharedIds(t);
10
8
11
9
let _hasUpdatedImport = false;
10
10
+
let _matchId = t.identifier('match');
11
11
+
let _privateId = t.identifier(_private);
12
12
+
13
13
+
const privateMethod = (name) =>
14
14
+
t.memberExpression(t.identifier(_privateId.name), t.identifier(name));
12
15
13
16
return {
14
17
/** Adds the reghex import declaration to the Program scope */
···
21
24
path.node.source = t.stringLiteral(importName);
22
25
}
23
26
24
24
-
path.node.specifiers.push(
25
25
-
t.importSpecifier(
26
26
-
(ids.execId = path.scope.generateUidIdentifier('exec')),
27
27
-
t.identifier('_exec')
28
28
-
),
29
29
-
t.importSpecifier(
30
30
-
(ids.patternId = path.scope.generateUidIdentifier('pattern')),
31
31
-
t.identifier('_pattern')
32
32
-
)
33
33
-
);
27
27
+
path.node.specifiers.push(t.importSpecifier(_privateId, _privateId));
34
28
35
29
const tagImport = path.node.specifiers.find((node) => {
36
36
-
return t.isImportSpecifier(node) && node.imported.name === 'tag';
30
30
+
return t.isImportSpecifier(node) && node.imported.name === 'match';
37
31
});
38
32
39
33
if (!tagImport) {
40
34
path.node.specifiers.push(
41
35
t.importSpecifier(
42
42
-
(ids.tagId = path.scope.generateUidIdentifier('tag')),
43
43
-
t.identifier('tag')
36
36
+
(_matchId = path.scope.generateUidIdentifier('match')),
37
37
+
t.identifier('match')
44
38
)
45
39
);
46
40
} else {
47
47
-
ids.tagId = tagImport.imported;
41
41
+
_matchId = tagImport.imported;
48
42
}
49
43
},
50
44
···
140
134
variableDeclarators.push(
141
135
t.variableDeclarator(
142
136
id,
143
143
-
t.callExpression(ids.pattern, [expression])
137
137
+
t.callExpression(privateMethod('pattern'), [expression])
144
138
)
145
139
);
146
140
+3
-2
src/codegen.js
···
1
1
-
export const _exec = '_exec';
1
1
+
export const _private = '__private';
2
2
+
2
3
const _state = 'state';
3
4
const _node = 'node';
4
5
const _match = 'x';
···
32
33
'';
33
34
const expression = ast.expression.fn
34
35
? `${ast.expression.id}(${_state})`
35
35
-
: `${_exec}(${_state}, ${ast.expression.id})`;
36
36
+
: `${_private}.exec(${_state}, ${ast.expression.id})`;
36
37
37
38
return js`
38
39
if (${_match} = ${expression}) {
+38
-28
src/core.js
···
1
1
-
import { astRoot, _exec as execId } from './codegen';
1
1
+
import { astRoot, _private as privateId } from './codegen';
2
2
import { parse as parseDSL } from './parser';
3
3
4
4
const isStickySupported = typeof /./g.sticky === 'boolean';
5
5
6
6
-
export const _pattern = (input) => {
7
7
-
if (typeof input === 'function') return input;
8
8
-
const source = typeof input !== 'string' ? input.source : input;
9
9
-
return isStickySupported
10
10
-
? new RegExp(source, 'y')
11
11
-
: new RegExp(source + '|()', 'g');
12
12
-
};
6
6
+
export const __private = {
7
7
+
pattern(input) {
8
8
+
if (typeof input === 'function') return input;
9
9
+
const source = typeof input !== 'string' ? input.source : input;
10
10
+
return isStickySupported
11
11
+
? new RegExp(source, 'y')
12
12
+
: new RegExp(source + '|()', 'g');
13
13
+
},
13
14
14
14
-
export const _exec = (state, pattern) => {
15
15
-
let match;
16
16
-
17
17
-
if (typeof pattern === 'function') {
18
18
-
if (!pattern.length) pattern = pattern();
19
19
-
return pattern(state);
20
20
-
}
15
15
+
exec(state, pattern) {
16
16
+
let match;
21
17
22
22
-
const input = state.quasis[state.x];
23
23
-
if (input && (pattern.lastIndex = state.y) < input.length) {
24
24
-
if (isStickySupported) {
25
25
-
if (pattern.test(input)) match = input.slice(state.y, pattern.lastIndex);
26
26
-
} else {
27
27
-
match = pattern.exec(input)[0] || match;
18
18
+
if (typeof pattern === 'function') {
19
19
+
if (!pattern.length) pattern = pattern();
20
20
+
return pattern(state);
28
21
}
29
22
30
30
-
state.y = pattern.lastIndex;
31
31
-
}
23
23
+
const input = state.quasis[state.x];
24
24
+
if (input && (pattern.lastIndex = state.y) < input.length) {
25
25
+
if (isStickySupported) {
26
26
+
if (pattern.test(input))
27
27
+
match = input.slice(state.y, pattern.lastIndex);
28
28
+
} else {
29
29
+
match = pattern.exec(input)[0] || match;
30
30
+
}
32
31
33
33
-
return match;
32
32
+
state.y = pattern.lastIndex;
33
33
+
}
34
34
+
35
35
+
return match;
36
36
+
},
34
37
};
35
38
36
39
export const interpolation = (predicate) => (state) => {
···
48
51
return match;
49
52
};
50
53
51
51
-
export const parse = (pattern) => (quasis, ...expressions) => {
54
54
+
export const parse = (matcher) => (quasis, ...expressions) => {
52
55
if (typeof quasis === 'string') quasis = [quasis];
53
56
const state = { quasis, expressions, x: 0, y: 0 };
54
54
-
return pattern(state);
57
57
+
return matcher(state);
55
58
};
56
59
57
60
export const match = (name, transform) => (quasis, ...expressions) => {
···
64
67
);
65
68
66
69
const makeMatcher = new Function(
67
67
-
execId + ',_n,_t,' + expressions.map((_expression, i) => `_${i}`).join(','),
70
70
+
privateId +
71
71
+
',_n,_t,' +
72
72
+
expressions.map((_expression, i) => `_${i}`).join(','),
68
73
'return ' + astRoot(ast, '_n', transform ? '_t' : null)
69
74
);
70
75
71
71
-
return makeMatcher(_exec, name, transform, ...expressions.map(_pattern));
76
76
+
return makeMatcher(
77
77
+
__private,
78
78
+
name,
79
79
+
transform,
80
80
+
...expressions.map(__private.pattern)
81
81
+
);
72
82
};