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};