1 |
|
2 |
|
3 |
|
4 |
|
5 | function escape(value) {
|
6 | return new RegExp(value.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'), 'm');
|
7 | }
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | function source(re) {
|
14 | if (!re) return null;
|
15 | if (typeof re === "string") return re;
|
16 |
|
17 | return re.source;
|
18 | }
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | function lookahead(re) {
|
25 | return concat('(?=', re, ')');
|
26 | }
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 | function anyNumberOfTimes(re) {
|
33 | return concat('(?:', re, ')*');
|
34 | }
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | function optional(re) {
|
41 | return concat('(?:', re, ')?');
|
42 | }
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 | function concat(...args) {
|
49 | const joined = args.map((x) => source(x)).join("");
|
50 | return joined;
|
51 | }
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 | function stripOptionsFromArgs(args) {
|
58 | const opts = args[args.length - 1];
|
59 |
|
60 | if (typeof opts === 'object' && opts.constructor === Object) {
|
61 | args.splice(args.length - 1, 1);
|
62 | return opts;
|
63 | } else {
|
64 | return {};
|
65 | }
|
66 | }
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 | function either(...args) {
|
76 |
|
77 | const opts = stripOptionsFromArgs(args);
|
78 | const joined = '('
|
79 | + (opts.capture ? "" : "?:")
|
80 | + args.map((x) => source(x)).join("|") + ")";
|
81 | return joined;
|
82 | }
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | function countMatchGroups(re) {
|
89 | return (new RegExp(re.toString() + '|')).exec('').length - 1;
|
90 | }
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 | function startsWith(re, lexeme) {
|
98 | const match = re && re.exec(lexeme);
|
99 | return match && match.index === 0;
|
100 | }
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 | const BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 | function _rewriteBackreferences(regexps, { joinWith }) {
|
123 | let numCaptures = 0;
|
124 |
|
125 | return regexps.map((regex) => {
|
126 | numCaptures += 1;
|
127 | const offset = numCaptures;
|
128 | let re = source(regex);
|
129 | let out = '';
|
130 |
|
131 | while (re.length > 0) {
|
132 | const match = BACKREF_RE.exec(re);
|
133 | if (!match) {
|
134 | out += re;
|
135 | break;
|
136 | }
|
137 | out += re.substring(0, match.index);
|
138 | re = re.substring(match.index + match[0].length);
|
139 | if (match[0][0] === '\\' && match[1]) {
|
140 |
|
141 | out += '\\' + String(Number(match[1]) + offset);
|
142 | } else {
|
143 | out += match[0];
|
144 | if (match[0] === '(') {
|
145 | numCaptures++;
|
146 | }
|
147 | }
|
148 | }
|
149 | return out;
|
150 | }).map(re => `(${re})`).join(joinWith);
|
151 | }
|
152 |
|
153 | export { _rewriteBackreferences, anyNumberOfTimes, concat, countMatchGroups, either, escape, lookahead, optional, source, startsWith };
|