forked from OctoLinker/OctoLinker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
regexBuilder.js
62 lines (50 loc) · 1.74 KB
/
regexBuilder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import zip from 'pop-zip/zip';
import XRegExp from 'xregexp/src/xregexp';
import build from 'xregexp/src/addons/build';
build(XRegExp);
function interpolate(substitution) {
return substitution instanceof RegExp
? substitution
: XRegExp.escape(substitution);
}
// This function makes it easy to build regular expressions that look more like formal grammars.
// See here for more info:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals
// http://xregexp.com/api/#build
export default function (flags = 'xngm') {
return (literals, ...substitutions) => {
// the 'x' flag doesn't seem to work if we pass it outside the pattern
// so put it inside as well
let buildPattern = flags.includes('x') ? '(?x)' : '';
const subpatterns = [];
// make `substitutions` the same length as `literals`
// so we can iterate over them together
const pairs = zip(literals.raw, substitutions.concat(''));
pairs.forEach(([literal, substitution], index) => {
subpatterns[index] = interpolate(substitution);
buildPattern += `${literal}{{${index}}}`;
});
return XRegExp.build(buildPattern, subpatterns, flags);
};
}
/* Usage Example:
import regexBuilder from './regexBuilder';
const sub = /inner/;
const xregexp = regexBuilder();
const outer = xregexp`
# comments start with #
before
# whitespace is insignificant, match it with \s
\s
# a reference to the 'sub' regex
${sub}
\s
# groups are not captured by default
(after | after2)
\s
# this group is captured
(?<name> after2 )
$
`;
outer.exec('before inner after after2'); // ['before inner after after2', 'after2']
*/