1export const parse = (quasis, expressions) => {
2 let quasiIndex = 0;
3 let stackIndex = 0;
4
5 const sequenceStack = [];
6 const rootSequence = {
7 sequence: [],
8 };
9
10 let currentGroup = null;
11 let lastMatch;
12 let currentSequence = rootSequence;
13
14 while (stackIndex < quasis.length + expressions.length) {
15 if (stackIndex % 2 !== 0) {
16 currentSequence.sequence.push({
17 expression: expressions[stackIndex++ >> 1],
18 });
19 }
20
21 const quasi = quasis[stackIndex >> 1];
22 while (quasiIndex < quasi.length) {
23 const char = quasi[quasiIndex++];
24
25 if (char === ' ' || char === '\t' || char === '\r' || char === '\n') {
26 continue;
27 } else if (char === '|' && currentSequence.sequence.length > 0) {
28 currentSequence = currentSequence.alternation = {
29 sequence: [],
30 };
31
32 continue;
33 } else if (char === ')' && currentSequence.sequence.length > 0) {
34 currentGroup = null;
35 currentSequence = sequenceStack.pop();
36 if (currentSequence) continue;
37 } else if (char === '(') {
38 currentGroup = {
39 sequence: {
40 sequence: [],
41 },
42 };
43
44 sequenceStack.push(currentSequence);
45 currentSequence.sequence.push(currentGroup);
46 currentSequence = currentGroup.sequence;
47 continue;
48 } else if (
49 char === '?' &&
50 currentSequence.sequence.length === 0 &&
51 currentGroup
52 ) {
53 const nextChar = quasi[quasiIndex++];
54 if (nextChar === ':') {
55 currentGroup.capture = nextChar;
56 continue;
57 } else if (nextChar === '=') {
58 currentGroup.capture = nextChar;
59 continue;
60 } else if (nextChar === '!') {
61 currentGroup.capture = nextChar;
62 continue;
63 }
64 } else if (
65 (char === '?' || char === '+' || char === '*') &&
66 (lastMatch =
67 currentSequence.sequence[currentSequence.sequence.length - 1])
68 ) {
69 lastMatch.quantifier = char;
70 continue;
71 }
72
73 throw new SyntaxError('Unexpected token "' + char + '"');
74 }
75
76 stackIndex++;
77 quasiIndex = 0;
78 }
79
80 return rootSequence;
81};