+1
-3
src/codegen.js
+1
-3
src/codegen.js
···
95
95
};
96
96
97
97
const astChild = (ast, depth, opts) =>
98
-
ast.type === 'expression'
99
-
? astExpression(ast, depth, opts)
100
-
: astGroup(ast, depth, opts);
98
+
ast.expression ? astExpression(ast, depth, opts) : astGroup(ast, depth, opts);
101
99
102
100
const astRepeating = (ast, depth, opts) => {
103
101
const label = `loop_${depth}`;
+1
-14
src/parser.js
+1
-14
src/parser.js
···
4
4
5
5
const sequenceStack = [];
6
6
const rootSequence = {
7
-
type: 'sequence',
8
7
sequence: [],
9
-
alternation: null,
10
8
};
11
9
12
10
let currentGroup = null;
···
15
13
16
14
while (stackIndex < quasis.length + expressions.length) {
17
15
if (stackIndex % 2 !== 0) {
18
-
const expression = expressions[stackIndex++ >> 1];
19
-
20
16
currentSequence.sequence.push({
21
-
type: 'expression',
22
-
expression,
23
-
quantifier: null,
17
+
expression: expressions[stackIndex++ >> 1],
24
18
});
25
19
}
26
20
···
32
26
continue;
33
27
} else if (char === '|' && currentSequence.sequence.length > 0) {
34
28
currentSequence = currentSequence.alternation = {
35
-
type: 'sequence',
36
29
sequence: [],
37
-
alternation: null,
38
30
};
39
31
40
32
continue;
···
44
36
if (currentSequence) continue;
45
37
} else if (char === '(') {
46
38
currentGroup = {
47
-
type: 'group',
48
39
sequence: {
49
-
type: 'sequence',
50
40
sequence: [],
51
-
alternation: null,
52
41
},
53
-
capture: null,
54
-
quantifier: null,
55
42
};
56
43
57
44
sequenceStack.push(currentSequence);
+6
-29
src/parser.test.js
+6
-29
src/parser.test.js
···
4
4
5
5
it('supports parsing expressions', () => {
6
6
expect(parseTag`${1}`).toEqual({
7
-
type: 'sequence',
8
7
sequence: [
9
8
{
10
-
type: 'expression',
11
9
expression: 1,
12
-
quantifier: null,
10
+
quantifier: undefined,
13
11
},
14
12
],
15
-
alternation: null,
13
+
alternation: undefined,
16
14
});
17
15
});
18
16
···
20
18
let ast;
21
19
22
20
ast = parseTag`${1}?`;
23
-
expect(ast).toHaveProperty('sequence.0.type', 'expression');
24
21
expect(ast).toHaveProperty('sequence.0.quantifier', '?');
25
22
26
23
ast = parseTag`${1}+`;
27
-
expect(ast).toHaveProperty('sequence.0.type', 'expression');
28
24
expect(ast).toHaveProperty('sequence.0.quantifier', '+');
29
25
30
26
ast = parseTag`${1}*`;
31
-
expect(ast).toHaveProperty('sequence.0.type', 'expression');
32
27
expect(ast).toHaveProperty('sequence.0.quantifier', '*');
33
28
});
34
29
···
37
32
38
33
ast = parseTag`${1} | ${2}`;
39
34
expect(ast).toHaveProperty('sequence.length', 1);
40
-
expect(ast).toHaveProperty('sequence.0.type', 'expression');
41
35
expect(ast).toHaveProperty('sequence.0.expression', 1);
42
-
expect(ast).toHaveProperty('alternation.type', 'sequence');
43
36
expect(ast).toHaveProperty('alternation.sequence.0.expression', 2);
44
37
45
38
ast = parseTag`${1}? | ${2}?`;
···
51
44
52
45
ast = parseTag`(${1} ${2})`;
53
46
expect(ast).toHaveProperty('sequence.length', 1);
54
-
expect(ast).toHaveProperty('sequence.0.type', 'group');
55
47
expect(ast).toHaveProperty('sequence.0.sequence.sequence.length', 2);
56
48
expect(ast).toHaveProperty('sequence.0.sequence.sequence.0.expression', 1);
57
49
expect(ast).toHaveProperty('sequence.0.sequence.sequence.1.expression', 2);
58
50
59
51
ast = parseTag`(${1} ${2}?)?`;
60
52
expect(ast).toHaveProperty('sequence.length', 1);
61
-
expect(ast).toHaveProperty('sequence.0.type', 'group');
62
53
expect(ast).toHaveProperty('sequence.0.quantifier', '?');
63
-
expect(ast).toHaveProperty('sequence.0.sequence.sequence.0.quantifier', null);
54
+
expect(ast).toHaveProperty(
55
+
'sequence.0.sequence.sequence.0.quantifier',
56
+
undefined
57
+
);
64
58
});
65
59
66
60
it('supports non-capturing groups', () => {
67
61
const ast = parseTag`(?: ${1})`;
68
62
expect(ast).toHaveProperty('sequence.length', 1);
69
-
expect(ast).toHaveProperty('sequence.0.type', 'group');
70
63
expect(ast).toHaveProperty('sequence.0.capture', ':');
71
64
expect(ast).toHaveProperty('sequence.0.sequence.sequence.length', 1);
72
65
});
···
74
67
it('supports positive lookahead groups', () => {
75
68
const ast = parseTag`(?= ${1})`;
76
69
expect(ast).toHaveProperty('sequence.length', 1);
77
-
expect(ast).toHaveProperty('sequence.0.type', 'group');
78
70
expect(ast).toHaveProperty('sequence.0.capture', '=');
79
71
expect(ast).toHaveProperty('sequence.0.sequence.sequence.length', 1);
80
72
});
···
82
74
it('supports negative lookahead groups', () => {
83
75
const ast = parseTag`(?! ${1})`;
84
76
expect(ast).toHaveProperty('sequence.length', 1);
85
-
expect(ast).toHaveProperty('sequence.0.type', 'group');
86
77
expect(ast).toHaveProperty('sequence.0.capture', '!');
87
78
expect(ast).toHaveProperty('sequence.0.sequence.sequence.length', 1);
88
79
});
···
90
81
it('supports groups with alternates', () => {
91
82
expect(parseTag`(${1} | ${2}) ${3}`).toMatchInlineSnapshot(`
92
83
Object {
93
-
"alternation": null,
94
84
"sequence": Array [
95
85
Object {
96
-
"capture": null,
97
-
"quantifier": null,
98
86
"sequence": Object {
99
87
"alternation": Object {
100
-
"alternation": null,
101
88
"sequence": Array [
102
89
Object {
103
90
"expression": 2,
104
-
"quantifier": null,
105
-
"type": "expression",
106
91
},
107
92
],
108
-
"type": "sequence",
109
93
},
110
94
"sequence": Array [
111
95
Object {
112
96
"expression": 1,
113
-
"quantifier": null,
114
-
"type": "expression",
115
97
},
116
98
],
117
-
"type": "sequence",
118
99
},
119
-
"type": "group",
120
100
},
121
101
Object {
122
102
"expression": 3,
123
-
"quantifier": null,
124
-
"type": "expression",
125
103
},
126
104
],
127
-
"type": "sequence",
128
105
}
129
106
`);
130
107
});