Mirror: The magical sticky regex-based parser generator 馃
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};