Mirror: The magical sticky regex-based parser generator 馃
1import { astRoot, _exec as execId } from './codegen'; 2import { parse as parseDSL } from './parser'; 3 4const isStickySupported = typeof /./g.sticky === 'boolean'; 5 6export const _pattern = (input) => { 7 if (typeof input === 'function') return input; 8 const source = typeof input !== 'string' ? input.source : input; 9 return isStickySupported 10 ? new RegExp(source, 'y') 11 : new RegExp(source + '|()', 'g'); 12}; 13 14export const _exec = (state, pattern) => { 15 let match; 16 17 if (typeof pattern === 'function') { 18 if (!pattern.length) pattern = pattern(); 19 return pattern(state); 20 } 21 22 pattern.lastIndex = state.index; 23 24 if (isStickySupported) { 25 if (pattern.test(state.input)) 26 match = state.input.slice(state.index, pattern.lastIndex); 27 } else { 28 match = pattern.exec(state.input)[0] || match; 29 } 30 31 state.index = pattern.lastIndex; 32 return match; 33}; 34 35export const parse = (pattern) => (input) => { 36 const state = { input, index: 0 }; 37 return pattern(state); 38}; 39 40export const match = (name, transform) => (quasis, ...expressions) => { 41 const ast = parseDSL( 42 quasis, 43 expressions.map((expression, i) => ({ 44 fn: typeof expression === 'function' && expression.length, 45 id: `_${i}`, 46 })) 47 ); 48 49 const makeMatcher = new Function( 50 execId + ',_n,_t,' + expressions.map((_expression, i) => `_${i}`).join(','), 51 'return ' + astRoot(ast, '_n', transform ? '_t' : null) 52 ); 53 54 return makeMatcher(_exec, name, transform, ...expressions.map(_pattern)); 55};