Mirror: The magical sticky regex-based parser generator 馃
1const syntaxError = (char) => { 2 throw new SyntaxError('Unexpected token "' + char + '"'); 3}; 4 5export const parse = (quasis, expressions) => { 6 let quasiIndex = 0; 7 let stackIndex = 0; 8 9 const sequenceStack = []; 10 const rootSequence = []; 11 12 let currentGroup = null; 13 let lastMatch; 14 let currentSequence = rootSequence; 15 16 for ( 17 let quasiIndex = 0, stackIndex = 0; 18 stackIndex < quasis.length + expressions.length; 19 stackIndex++ 20 ) { 21 if (stackIndex % 2 !== 0) { 22 currentSequence.push({ 23 expression: expressions[stackIndex++ >> 1], 24 }); 25 } 26 27 const quasi = quasis[stackIndex >> 1]; 28 for (quasiIndex = 0; quasiIndex < quasi.length; ) { 29 const char = quasi[quasiIndex++]; 30 if (char === ' ' || char === '\t' || char === '\r' || char === '\n') { 31 } else if (char === '|' && currentSequence.length) { 32 currentSequence = currentSequence.alternation = []; 33 } else if (char === ')' && currentSequence.length) { 34 currentGroup = null; 35 currentSequence = sequenceStack.pop(); 36 if (!currentSequence) syntaxError(char); 37 } else if (char === '(') { 38 sequenceStack.push(currentSequence); 39 currentSequence.push((currentGroup = { sequence: [] })); 40 currentSequence = currentGroup.sequence; 41 } else if (char === '?' && !currentSequence.length && currentGroup) { 42 const nextChar = quasi[quasiIndex++]; 43 if (nextChar === ':' || nextChar === '=' || nextChar === '!') { 44 currentGroup.capture = nextChar; 45 } else { 46 syntaxError(char); 47 } 48 } else if ( 49 (char === '?' || char === '+' || char === '*') && 50 (lastMatch = currentSequence[currentSequence.length - 1]) 51 ) { 52 lastMatch.quantifier = char; 53 } else { 54 syntaxError(char); 55 } 56 } 57 } 58 59 return rootSequence; 60};