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