Mirror: The magical sticky regex-based parser generator 馃
at main 2.2 kB view raw
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 let capture; 16 17 for ( 18 let quasiIndex = 0, stackIndex = 0; 19 stackIndex < quasis.length + expressions.length; 20 stackIndex++ 21 ) { 22 if (stackIndex % 2 !== 0) { 23 const expression = expressions[stackIndex++ >> 1]; 24 currentSequence.push({ expression, capture }); 25 capture = undefined; 26 } 27 28 const quasi = quasis[stackIndex >> 1]; 29 for (quasiIndex = 0; quasiIndex < quasi.length; ) { 30 const char = quasi[quasiIndex++]; 31 if (char === ' ' || char === '\t' || char === '\r' || char === '\n') { 32 } else if (char === '|' && currentSequence.length) { 33 currentSequence = currentSequence.alternation = []; 34 } else if (char === ')' && currentSequence.length) { 35 currentGroup = null; 36 currentSequence = sequenceStack.pop(); 37 if (!currentSequence) syntaxError(char); 38 } else if (char === '(') { 39 sequenceStack.push(currentSequence); 40 currentSequence.push((currentGroup = { sequence: [], capture })); 41 currentSequence = currentGroup.sequence; 42 capture = undefined; 43 } else if (char === ':' || char === '=' || char === '!') { 44 capture = char; 45 const nextChar = quasi[quasiIndex]; 46 if (quasi[quasiIndex] && quasi[quasiIndex] !== '(') syntaxError(char); 47 } else if (char === '?' && !currentSequence.length && currentGroup) { 48 capture = quasi[quasiIndex++]; 49 if (capture === ':' || capture === '=' || capture === '!') { 50 currentGroup.capture = capture; 51 capture = undefined; 52 } else { 53 syntaxError(char); 54 } 55 } else if ( 56 (char === '?' || char === '+' || char === '*') && 57 (lastMatch = currentSequence[currentSequence.length - 1]) 58 ) { 59 lastMatch.quantifier = char; 60 } else { 61 syntaxError(char); 62 } 63 } 64 } 65 66 return rootSequence; 67};