Mirror: The magical sticky regex-based parser generator 🧙
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #11 from kitten/feat/string-matchers

Add support for string matchers

authored by

Phil Pluckthun and committed by
GitHub
72c3cfff 0082078a

+61 -9
+17
src/babel/__snapshots__/plugin.test.js.snap
··· 3 3 exports[`deduplicates hoisted expressions 1`] = ` 4 4 "import { match, __private } from \\"reghex\\"; 5 5 const re = /1/; 6 + const str = '1'; 6 7 7 8 var _re_expression = __private.pattern(re); 8 9 ··· 13 14 var x; 14 15 15 16 if (x = __private.exec(state, _re_expression)) { 17 + node.push(x); 18 + } else { 19 + state.y = y1; 20 + state.x = x1; 21 + return; 22 + } 23 + 24 + if (x = __private.exec(state, str)) { 16 25 node.push(x); 17 26 } else { 18 27 state.y = y1; ··· 31 40 var x; 32 41 33 42 if (x = __private.exec(state, _re_expression)) { 43 + node.push(x); 44 + } else { 45 + state.y = y1; 46 + state.x = x1; 47 + return; 48 + } 49 + 50 + if (x = __private.exec(state, \\"2\\")) { 34 51 node.push(x); 35 52 } else { 36 53 state.y = y1;
+4 -1
src/babel/plugin.test.js
··· 34 34 ).toMatchSnapshot(); 35 35 }); 36 36 37 - it('deduplicates hoisted expressions', () => { 37 + it.only('deduplicates hoisted expressions', () => { 38 38 const code = ` 39 39 import { match } from 'reghex/macro'; 40 40 41 41 const re = /1/; 42 + const str = '1'; 42 43 43 44 const a = match('a')\` 44 45 \${re} 46 + \${str} 45 47 \`; 46 48 47 49 const b = match('b')\` 48 50 \${re} 51 + \${'2'} 49 52 \`; 50 53 `; 51 54
+5
src/babel/transform.js
··· 116 116 t.isIdentifier(expression.body.body[0].argument) 117 117 ) { 118 118 expression = expression.body.body[0].argument; 119 + } else if (t.isStringLiteral(expression)) { 120 + return expression; 119 121 } 120 122 121 123 const isBindingExpression = ··· 126 128 if (t.isVariableDeclarator(binding.path.node)) { 127 129 const matchPath = binding.path.get('init'); 128 130 if (this.isMatch(matchPath)) { 131 + return expression; 132 + } else if (t.isStringLiteral(matchPath)) { 129 133 return expression; 130 134 } else if (_hoistedExpressions.has(expression.name)) { 131 135 return t.identifier(_hoistedExpressions.get(expression.name)); ··· 149 153 if (t.isIdentifier(expression)) { 150 154 _hoistedExpressions.set(expression.name, id.name); 151 155 } 156 + 152 157 return id; 153 158 } 154 159 );
+21 -8
src/core.js
··· 5 5 6 6 export const __private = { 7 7 pattern(input) { 8 - if (typeof input === 'function') return input; 8 + if (typeof input === 'function' || typeof input === 'string') { 9 + return input; 10 + } 11 + 9 12 const source = typeof input !== 'string' ? input.source : input; 10 13 return isStickySupported 11 14 ? new RegExp(source, 'y') ··· 21 24 } 22 25 23 26 const input = state.quasis[state.x]; 24 - if (input && (pattern.lastIndex = state.y) < input.length) { 25 - if (isStickySupported) { 26 - if (pattern.test(input)) 27 - match = input.slice(state.y, pattern.lastIndex); 27 + if (input && state.y < input.length) { 28 + if (typeof pattern === 'string') { 29 + const end = state.y + pattern.length; 30 + const sub = input.slice(state.y, end); 31 + if (sub === pattern) { 32 + state.y = end; 33 + match = sub; 34 + } 28 35 } else { 29 - match = pattern.exec(input)[0] || match; 30 - } 36 + pattern.lastIndex = state.y; 37 + if (isStickySupported) { 38 + if (pattern.test(input)) 39 + match = input.slice(state.y, pattern.lastIndex); 40 + } else { 41 + match = pattern.exec(input)[0] || match; 42 + } 31 43 32 - state.y = pattern.lastIndex; 44 + state.y = pattern.lastIndex; 45 + } 33 46 } 34 47 35 48 return match;
+14
src/core.test.js
··· 573 573 expect(parse(node)`1${1}3`).toBe(undefined); 574 574 }); 575 575 }); 576 + 577 + describe('string matching', () => { 578 + const node = match('node')` 579 + ${'1'} 580 + ${'2'} 581 + `; 582 + 583 + it('matches strings', () => { 584 + const expected = ['1', '2']; 585 + expected.tag = 'node'; 586 + expect(parse(node)('12')).toEqual(expected); 587 + expect(parse(node)('13')).toBe(undefined); 588 + }); 589 + });