2 Regualar expressions package test suite.
4 module std.regex.internal.tests;
8 import std.conv, std.exception, std.meta, std.range,
9 std.typecons, std.regex;
11 import std.regex.internal.parser : Escapables; // characters that need escaping
13 alias Sequence(int B, int E) = staticIota!(B, E);
18 regex(`(?:([0-9A-F]+)\.\.([0-9A-F]+)|([0-9A-F]+))\s*;\s*(.*)\s*#`);
19 regex("abc|edf|ighrg");
20 auto r1 = regex("abc");
21 auto r2 = regex("(gylba)");
22 assert(match("abcdef", r1).hit == "abc");
23 assert(!match("wida",r2));
24 assert(bmatch("abcdef", r1).hit == "abc");
25 assert(!bmatch("wida", r2));
26 assert(match("abc", "abc".dup));
27 assert(bmatch("abc", "abc".dup));
34 /* The test vectors in this file are altered from Henry Spencer's regexp
35 test code. His copyright notice is:
37 Copyright (c) 1986 by University of Toronto.
38 Written by Henry Spencer. Not derived from licensed software.
40 Permission is granted to anyone to use this software for any
41 purpose on any computer system, and to redistribute it freely,
42 subject to the following restrictions:
44 1. The author is not responsible for the consequences of use of
45 this software, no matter how awful, even if they arise
48 2. The origin of this software must not be misrepresented, either
49 by explicit claim or by omission.
51 3. Altered versions must be plainly marked as such, and must not
52 be misrepresented as being the original software.
69 static immutable TestVectors[] tv = [
70 TestVectors( "a\\b", "a", "y", "$&", "a" ),
71 TestVectors( "(a)b\\1", "abaab","y", "$&", "aba" ),
72 TestVectors( "()b\\1", "aaab", "y", "$&", "b" ),
73 TestVectors( "abc", "abc", "y", "$&", "abc" ),
74 TestVectors( "abc", "xbc", "n", "-", "-" ),
75 TestVectors( "abc", "axc", "n", "-", "-" ),
76 TestVectors( "abc", "abx", "n", "-", "-" ),
77 TestVectors( "abc", "xabcy","y", "$&", "abc" ),
78 TestVectors( "abc", "ababc","y", "$&", "abc" ),
79 TestVectors( "ab*c", "abc", "y", "$&", "abc" ),
80 TestVectors( "ab*bc", "abc", "y", "$&", "abc" ),
81 TestVectors( "ab*bc", "abbc", "y", "$&", "abbc" ),
82 TestVectors( "ab*bc", "abbbbc","y", "$&", "abbbbc" ),
83 TestVectors( "ab+bc", "abbc", "y", "$&", "abbc" ),
84 TestVectors( "ab+bc", "abc", "n", "-", "-" ),
85 TestVectors( "ab+bc", "abq", "n", "-", "-" ),
86 TestVectors( "ab+bc", "abbbbc","y", "$&", "abbbbc" ),
87 TestVectors( "ab?bc", "abbc", "y", "$&", "abbc" ),
88 TestVectors( "ab?bc", "abc", "y", "$&", "abc" ),
89 TestVectors( "ab?bc", "abbbbc","n", "-", "-" ),
90 TestVectors( "ab?c", "abc", "y", "$&", "abc" ),
91 TestVectors( "^abc$", "abc", "y", "$&", "abc" ),
92 TestVectors( "^abc$", "abcc", "n", "-", "-" ),
93 TestVectors( "^abc", "abcc", "y", "$&", "abc" ),
94 TestVectors( "^abc$", "aabc", "n", "-", "-" ),
95 TestVectors( "abc$", "aabc", "y", "$&", "abc" ),
96 TestVectors( "^", "abc", "y", "$&", "" ),
97 TestVectors( "$", "abc", "y", "$&", "" ),
98 TestVectors( "a.c", "abc", "y", "$&", "abc" ),
99 TestVectors( "a.c", "axc", "y", "$&", "axc" ),
100 TestVectors( "a.*c", "axyzc","y", "$&", "axyzc" ),
101 TestVectors( "a.*c", "axyzd","n", "-", "-" ),
102 TestVectors( "a[bc]d", "abc", "n", "-", "-" ),
103 TestVectors( "a[bc]d", "abd", "y", "$&", "abd" ),
104 TestVectors( "a[b-d]e", "abd", "n", "-", "-" ),
105 TestVectors( "a[b-d]e", "ace", "y", "$&", "ace" ),
106 TestVectors( "a[b-d]", "aac", "y", "$&", "ac" ),
107 TestVectors( "a[-b]", "a-", "y", "$&", "a-" ),
108 TestVectors( "a[b-]", "a-", "y", "$&", "a-" ),
109 TestVectors( "a[b-a]", "-", "c", "-", "-" ),
110 TestVectors( "a[]b", "-", "c", "-", "-" ),
111 TestVectors( "a[", "-", "c", "-", "-" ),
112 TestVectors( "a]", "a]", "y", "$&", "a]" ),
113 TestVectors( "a[\\]]b", "a]b", "y", "$&", "a]b" ),
114 TestVectors( "a[^bc]d", "aed", "y", "$&", "aed" ),
115 TestVectors( "a[^bc]d", "abd", "n", "-", "-" ),
116 TestVectors( "a[^-b]c", "adc", "y", "$&", "adc" ),
117 TestVectors( "a[^-b]c", "a-c", "n", "-", "-" ),
118 TestVectors( "a[^\\]b]c", "adc", "y", "$&", "adc" ),
119 TestVectors( "ab|cd", "abc", "y", "$&", "ab" ),
120 TestVectors( "ab|cd", "abcd", "y", "$&", "ab" ),
121 TestVectors( "()ef", "def", "y", "$&-$1", "ef-" ),
122 TestVectors( "()*", "-", "y", "-", "-" ),
123 TestVectors( "*a", "-", "c", "-", "-" ),
124 TestVectors( "^*", "-", "y", "-", "-" ),
125 TestVectors( "$*", "-", "y", "-", "-" ),
126 TestVectors( "(*)b", "-", "c", "-", "-" ),
127 TestVectors( "$b", "b", "n", "-", "-" ),
128 TestVectors( "a\\", "-", "c", "-", "-" ),
129 TestVectors( "a\\(b", "a(b", "y", "$&-$1", "a(b-" ),
130 TestVectors( "a\\(*b", "ab", "y", "$&", "ab" ),
131 TestVectors( "a\\(*b", "a((b", "y", "$&", "a((b" ),
132 TestVectors( "a\\\\b", "a\\b", "y", "$&", "a\\b" ),
133 TestVectors( "abc)", "-", "c", "-", "-" ),
134 TestVectors( "(abc", "-", "c", "-", "-" ),
135 TestVectors( "((a))", "abc", "y", "$&-$1-$2", "a-a-a" ),
136 TestVectors( "(a)b(c)", "abc", "y", "$&-$1-$2", "abc-a-c" ),
137 TestVectors( "a+b+c", "aabbabc","y", "$&", "abc" ),
138 TestVectors( "a**", "-", "c", "-", "-" ),
139 TestVectors( "a*?a", "aa", "y", "$&", "a" ),
140 TestVectors( "(a*)*", "aaa", "y", "-", "-" ),
141 TestVectors( "(a*)+", "aaa", "y", "-", "-" ),
142 TestVectors( "(a|)*", "-", "y", "-", "-" ),
143 TestVectors( "(a*|b)*", "aabb", "y", "-", "-" ),
144 TestVectors( "(a|b)*", "ab", "y", "$&-$1", "ab-b" ),
145 TestVectors( "(a+|b)*", "ab", "y", "$&-$1", "ab-b" ),
146 TestVectors( "(a+|b)+", "ab", "y", "$&-$1", "ab-b" ),
147 TestVectors( "(a+|b)?", "ab", "y", "$&-$1", "a-a" ),
148 TestVectors( "[^ab]*", "cde", "y", "$&", "cde" ),
149 TestVectors( "(^)*", "-", "y", "-", "-" ),
150 TestVectors( "(ab|)*", "-", "y", "-", "-" ),
151 TestVectors( ")(", "-", "c", "-", "-" ),
152 TestVectors( "", "abc", "y", "$&", "" ),
153 TestVectors( "abc", "", "n", "-", "-" ),
154 TestVectors( "a*", "", "y", "$&", "" ),
155 TestVectors( "([abc])*d", "abbbcd", "y", "$&-$1", "abbbcd-c" ),
156 TestVectors( "([abc])*bcd", "abcd", "y", "$&-$1", "abcd-a" ),
157 TestVectors( "a|b|c|d|e", "e", "y", "$&", "e" ),
158 TestVectors( "(a|b|c|d|e)f", "ef", "y", "$&-$1", "ef-e" ),
159 TestVectors( "((a*|b))*", "aabb", "y", "-", "-" ),
160 TestVectors( "abcd*efg", "abcdefg", "y", "$&", "abcdefg" ),
161 TestVectors( "ab*", "xabyabbbz", "y", "$&", "ab" ),
162 TestVectors( "ab*", "xayabbbz", "y", "$&", "a" ),
163 TestVectors( "(ab|cd)e", "abcde", "y", "$&-$1", "cde-cd" ),
164 TestVectors( "[abhgefdc]ij", "hij", "y", "$&", "hij" ),
165 TestVectors( "^(ab|cd)e", "abcde", "n", "x$1y", "xy" ),
166 TestVectors( "(abc|)ef", "abcdef", "y", "$&-$1", "ef-" ),
167 TestVectors( "(a|b)c*d", "abcd", "y", "$&-$1", "bcd-b" ),
168 TestVectors( "(ab|ab*)bc", "abc", "y", "$&-$1", "abc-a" ),
169 TestVectors( "a([bc]*)c*", "abc", "y", "$&-$1", "abc-bc" ),
170 TestVectors( "a([bc]*)(c*d)", "abcd", "y", "$&-$1-$2", "abcd-bc-d" ),
171 TestVectors( "a([bc]+)(c*d)", "abcd", "y", "$&-$1-$2", "abcd-bc-d" ),
172 TestVectors( "a([bc]*)(c+d)", "abcd", "y", "$&-$1-$2", "abcd-b-cd" ),
173 TestVectors( "a[bcd]*dcdcde", "adcdcde", "y", "$&", "adcdcde" ),
174 TestVectors( "a[bcd]+dcdcde", "adcdcde", "n", "-", "-" ),
175 TestVectors( "(ab|a)b*c", "abc", "y", "$&-$1", "abc-ab" ),
176 TestVectors( "((a)(b)c)(d)", "abcd", "y", "$1-$2-$3-$4", "abc-a-b-d" ),
177 TestVectors( "[a-zA-Z_][a-zA-Z0-9_]*", "alpha", "y", "$&", "alpha" ),
178 TestVectors( "^a(bc+|b[eh])g|.h$", "abh", "y", "$&-$1", "bh-" ),
179 TestVectors( "(bc+d$|ef*g.|h?i(j|k))", "effgz", "y", "$&-$1-$2", "effgz-effgz-" ),
180 TestVectors( "(bc+d$|ef*g.|h?i(j|k))", "ij", "y", "$&-$1-$2", "ij-ij-j" ),
181 TestVectors( "(bc+d$|ef*g.|h?i(j|k))", "effg", "n", "-", "-" ),
182 TestVectors( "(bc+d$|ef*g.|h?i(j|k))", "bcdd", "n", "-", "-" ),
183 TestVectors( "(bc+d$|ef*g.|h?i(j|k))", "reffgz", "y", "$&-$1-$2", "effgz-effgz-" ),
184 TestVectors( "(((((((((a)))))))))", "a", "y", "$&", "a" ),
185 TestVectors( "multiple words of text", "uh-uh", "n", "-", "-" ),
186 TestVectors( "multiple words", "multiple words, yeah", "y", "$&", "multiple words" ),
187 TestVectors( "(.*)c(.*)", "abcde", "y", "$&-$1-$2", "abcde-ab-de" ),
188 TestVectors( "\\((.*), (.*)\\)", "(a, b)", "y", "($2, $1)", "(b, a)" ),
189 TestVectors( "abcd", "abcd", "y", "$&-&-$$$&", "abcd-&-$abcd" ),
190 TestVectors( "a(bc)d", "abcd", "y", "$1-$$1-$$$1", "bc-$1-$bc" ),
191 TestVectors( "[k]", "ab", "n", "-", "-" ),
192 TestVectors( "[ -~]*", "abc", "y", "$&", "abc" ),
193 TestVectors( "[ -~ -~]*", "abc", "y", "$&", "abc" ),
194 TestVectors( "[ -~ -~ -~]*", "abc", "y", "$&", "abc" ),
195 TestVectors( "[ -~ -~ -~ -~]*", "abc", "y", "$&", "abc" ),
196 TestVectors( "[ -~ -~ -~ -~ -~]*", "abc", "y", "$&", "abc" ),
197 TestVectors( "[ -~ -~ -~ -~ -~ -~]*", "abc", "y", "$&", "abc" ),
198 TestVectors( "[ -~ -~ -~ -~ -~ -~ -~]*", "abc", "y", "$&", "abc" ),
199 TestVectors( "a{2}", "candy", "n", "", "" ),
200 TestVectors( "a{2}", "caandy", "y", "$&", "aa" ),
201 TestVectors( "a{2}", "caaandy", "y", "$&", "aa" ),
202 TestVectors( "a{2,}", "candy", "n", "", "" ),
203 TestVectors( "a{2,}", "caandy", "y", "$&", "aa" ),
204 TestVectors( "a{2,}", "caaaaaandy", "y", "$&", "aaaaaa" ),
205 TestVectors( "a{1,3}", "cndy", "n", "", "" ),
206 TestVectors( "a{1,3}", "candy", "y", "$&", "a" ),
207 TestVectors( "a{1,3}", "caandy", "y", "$&", "aa" ),
208 TestVectors( "a{1,3}", "caaaaaandy", "y", "$&", "aaa" ),
209 TestVectors( "e?le?", "angel", "y", "$&", "el" ),
210 TestVectors( "e?le?", "angle", "y", "$&", "le" ),
211 TestVectors( "\\bn\\w", "noonday", "y", "$&", "no" ),
212 TestVectors( "\\wy\\b", "possibly yesterday", "y", "$&", "ly" ),
213 TestVectors( "\\w\\Bn", "noonday", "y", "$&", "on" ),
214 TestVectors( "y\\B\\w", "possibly yesterday", "y", "$&", "ye" ),
215 TestVectors( "\\cJ", "abc\ndef", "y", "$&", "\n" ),
216 TestVectors( "\\d", "B2 is", "y", "$&", "2" ),
217 TestVectors( "\\D", "B2 is", "y", "$&", "B" ),
218 TestVectors( "\\s\\w*", "foo bar", "y", "$&", " bar" ),
219 TestVectors( "\\S\\w*", "foo bar", "y", "$&", "foo" ),
220 TestVectors( "abc", "ababc", "y", "$&", "abc" ),
221 TestVectors( "apple(,)\\sorange\\1", "apple, orange, cherry, peach", "y", "$&", "apple, orange," ),
222 TestVectors( "(\\w+)\\s(\\w+)", "John Smith", "y", "$2, $1", "Smith, John" ),
223 TestVectors( "\\n\\f\\r\\t\\v", "abc\n\f\r\t\vdef", "y", "$&", "\n\f\r\t\v" ),
224 TestVectors( ".*c", "abcde", "y", "$&", "abc" ),
225 TestVectors( "^\\w+((;|=)\\w+)+$", "some=host=tld", "y", "$&-$1-$2", "some=host=tld-=tld-=" ),
226 TestVectors( "^\\w+((\\.|-)\\w+)+$", "some.host.tld", "y", "$&-$1-$2", "some.host.tld-.tld-." ),
227 TestVectors( "q(a|b)*q", "xxqababqyy", "y", "$&-$1", "qababq-b" ),
228 TestVectors( "^(a)(b){0,1}(c*)", "abcc", "y", "$1 $2 $3", "a b cc" ),
229 TestVectors( "^(a)((b){0,1})(c*)", "abcc", "y", "$1 $2 $3", "a b b" ),
230 TestVectors( "^(a)(b)?(c*)", "abcc", "y", "$1 $2 $3", "a b cc" ),
231 TestVectors( "^(a)((b)?)(c*)", "abcc", "y", "$1 $2 $3", "a b b" ),
232 TestVectors( "^(a)(b){0,1}(c*)", "acc", "y", "$1 $2 $3", "a cc" ),
233 TestVectors( "^(a)((b){0,1})(c*)", "acc", "y", "$1 $2 $3", "a " ),
234 TestVectors( "^(a)(b)?(c*)", "acc", "y", "$1 $2 $3", "a cc" ),
235 TestVectors( "^(a)((b)?)(c*)", "acc", "y", "$1 $2 $3", "a " ),
236 TestVectors( "(?:ab){3}", "_abababc","y", "$&-$1", "ababab-" ),
237 TestVectors( "(?:a(?:x)?)+", "aaxaxx", "y", "$&-$1-$2", "aaxax--" ),
238 TestVectors( `\W\w\W`, "aa b!ca", "y", "$&", " b!"),
240 TestVectors( "(?:a{2,4}b{1,3}){1,2}", "aaabaaaabbb", "y", "$&", "aaabaaaabbb" ),
241 TestVectors( "(?:a{2,4}b{1,3}){1,2}?", "aaabaaaabbb", "y", "$&", "aaab" ),
243 TestVectors( "(abc)|(edf)|(xyz)", "xyz", "y", "$1-$2-$3","--xyz"),
244 TestVectors( "(?P<q>\\d+)/(?P<d>\\d+)", "2/3", "y", "${d}/${q}", "3/2"),
246 TestVectors( "[a-z--d-f]", " dfa", "y", "$&", "a"),
247 TestVectors( "[abc[pq--acq]]{2}", "bqpaca", "y", "$&", "pa"),
248 TestVectors( "[a-z9&&abc0-9]{3}", "z90a0abc", "y", "$&", "abc"),
249 TestVectors( "[0-9a-f~~0-5a-z]{2}", "g0a58x", "y", "$&", "8x"),
250 TestVectors( "[abc[pq]xyz[rs]]{4}", "cqxr", "y", "$&", "cqxr"),
251 TestVectors( "[abcdf--[ab&&[bcd]][acd]]", "abcdefgh", "y", "$&", "f"),
252 TestVectors( "[a-c||d-f]+", "abcdef", "y", "$&", "abcdef"),
253 TestVectors( "[a-f--a-c]+", "abcdef", "y", "$&", "def"),
254 TestVectors( "[a-c&&b-f]+", "abcdef", "y", "$&", "bc"),
255 TestVectors( "[a-c~~b-f]+", "abcdef", "y", "$&", "a"),
256 //unicode blocks & properties:
257 TestVectors( `\P{Inlatin1suppl ement}`, "\u00c2!", "y", "$&", "!"),
258 TestVectors( `\p{InLatin-1 Supplement}\p{in-mathematical-operators}\P{Inlatin1suppl ement}`,
259 "\u00c2\u2200\u00c3\u2203.", "y", "$&", "\u00c3\u2203."),
260 TestVectors( `[-+*/\p{in-mathematical-operators}]{2}`, "a+\u2212", "y", "$&", "+\u2212"),
261 TestVectors( `\p{Ll}+`, "XabcD", "y", "$&", "abc"),
262 TestVectors( `\p{Lu}+`, "абвГДЕ", "y", "$&", "ГДЕ"),
263 TestVectors( `^\p{Currency Symbol}\p{Sc}`, "$₤", "y", "$&", "$₤"),
264 TestVectors( `\p{Common}\p{Thai}`, "!ฆ", "y", "$&", "!ฆ"),
265 TestVectors( `[\d\s]*\D`, "12 \t3\U00001680\u0F20_2", "y", "$&", "12 \t3\U00001680\u0F20_"),
266 TestVectors( `[c-wф]фф`, "ффф", "y", "$&", "ффф"),
268 TestVectors( `^abcdEf$`, "AbCdEF", "y", "$&", "AbCdEF", "i"),
269 TestVectors( `Русский язык`, "рУсскИй ЯзЫк", "y", "$&", "рУсскИй ЯзЫк", "i"),
270 TestVectors( `ⒶⒷⓒ` , "ⓐⓑⒸ", "y", "$&", "ⓐⓑⒸ", "i"),
271 TestVectors( "\U00010400{2}", "\U00010428\U00010400 ", "y", "$&", "\U00010428\U00010400", "i"),
272 TestVectors( `[adzУ-Я]{4}`, "DzюЯ", "y", "$&", "DzюЯ", "i"),
273 TestVectors( `\p{L}\p{Lu}{10}`, "абвгдеЖЗИКЛ", "y", "$&", "абвгдеЖЗИКЛ", "i"),
274 TestVectors( `(?:Dåb){3}`, "DåbDÅBdÅb", "y", "$&", "DåbDÅBdÅb", "i"),
276 TestVectors( `\u0041\u005a\U00000065\u0001`, "AZe\u0001", "y", "$&", "AZe\u0001"),
277 TestVectors( `\u`, "", "c", "-", "-"),
278 TestVectors( `\U`, "", "c", "-", "-"),
279 TestVectors( `\u003`, "", "c", "-", "-"),
280 TestVectors( `[\x00-\x7f]{4}`, "\x00\x09ab", "y", "$&", "\x00\x09ab"),
281 TestVectors( `[\cJ\cK\cA-\cD]{3}\cQ`, "\x01\x0B\x0A\x11", "y", "$&", "\x01\x0B\x0A\x11"),
282 TestVectors( `\r\n\v\t\f\\`, "\r\n\v\t\f\\", "y", "$&", "\r\n\v\t\f\\"),
283 TestVectors( `[\u0003\u0001]{2}`, "\u0001\u0003", "y", "$&", "\u0001\u0003"),
284 TestVectors( `^[\u0020-\u0080\u0001\n-\r]{8}`, "abc\u0001\v\f\r\n", "y", "$&", "abc\u0001\v\f\r\n"),
285 TestVectors( `\w+\S\w+`, "ab7!44c", "y", "$&", "ab7!44c"),
286 TestVectors( `\b\w+\b`, " abde4 ", "y", "$&", "abde4"),
287 TestVectors( `\b\w+\b`, " abde4", "y", "$&", "abde4"),
288 TestVectors( `\b\w+\b`, "abde4 ", "y", "$&", "abde4"),
289 TestVectors( `\pL\pS`, "a\u02DA", "y", "$&", "a\u02DA"),
290 TestVectors( `\pX`, "", "c", "-", "-"),
291 // ^, $, \b, \B, multiline :
292 TestVectors( `\r.*?$`, "abc\r\nxy", "y", "$&", "\r\nxy", "sm"),
293 TestVectors( `^a$^b$`, "a\r\nb\n", "n", "$&", "-", "m"),
294 TestVectors( `^a$\r\n^b$`,"a\r\nb\n", "y", "$&", "a\r\nb", "m"),
295 TestVectors( `^$`, "\r\n", "y", "$&", "", "m"),
296 TestVectors( `^a$\nx$`, "a\nx\u2028","y", "$&", "a\nx", "m"),
297 TestVectors( `^a$\nx$`, "a\nx\u2029","y", "$&", "a\nx", "m"),
298 TestVectors( `^a$\nx$`, "a\nx\u0085","y", "$&", "a\nx","m"),
299 TestVectors( `^x$`, "\u2028x", "y", "$&", "x", "m"),
300 TestVectors( `^x$`, "\u2029x", "y", "$&", "x", "m"),
301 TestVectors( `^x$`, "\u0085x", "y", "$&", "x", "m"),
302 TestVectors( `\b^.`, "ab", "y", "$&", "a"),
303 TestVectors( `\B^.`, "ab", "n", "-", "-"),
304 TestVectors( `^ab\Bc\B`, "\r\nabcd", "y", "$&", "abc", "m"),
305 TestVectors( `^.*$`, "12345678", "y", "$&", "12345678"),
307 // luckily obtained regression on incremental matching in backtracker
308 TestVectors( `^(?:(?:([0-9A-F]+)\.\.([0-9A-F]+)|([0-9A-F]+))\s*;\s*([^ ]*)\s*#|# (?:\w|_)+=((?:\w|_)+))`,
309 "0020 ; White_Space # ", "y", "$1-$2-$3", "--0020"),
311 TestVectors( "(foo.)(?=(bar))", "foobar foodbar", "y", "$&-$1-$2", "food-food-bar" ),
312 TestVectors( `\b(\d+)[a-z](?=\1)`, "123a123", "y", "$&-$1", "123a-123" ),
313 TestVectors( `\$(?!\d{3})\w+`, "$123 $abc", "y", "$&", "$abc"),
314 TestVectors( `(abc)(?=(ed(f))\3)`, "abcedff", "y", "-", "-"),
315 TestVectors( `\b[A-Za-z0-9.]+(?=(@(?!gmail)))`, "a@gmail,x@com", "y", "$&-$1", "x-@"),
316 TestVectors( `x()(abc)(?=(d)(e)(f)\2)`, "xabcdefabc", "y", "$&", "xabc"),
317 TestVectors( `x()(abc)(?=(d)(e)(f)()\3\4\5)`, "xabcdefdef", "y", "$&", "xabc"),
319 TestVectors( `(?<=(ab))\d`, "12ba3ab4", "y", "$&-$1", "4-ab", "i"),
320 TestVectors( `\w(?<!\d)\w`, "123ab24", "y", "$&", "ab"),
321 TestVectors( `(?<=Dåb)x\w`, "DåbDÅBxdÅb", "y", "$&", "xd", "i"),
322 TestVectors( `(?<=(ab*c))x`, "abbbbcxac", "y", "$&-$1", "x-abbbbc"),
323 TestVectors( `(?<=(ab*?c))x`, "abbbbcxac", "y", "$&-$1", "x-abbbbc"),
324 TestVectors( `(?<=(a.*?c))x`, "ababbcxac", "y", "$&-$1", "x-abbc"),
325 TestVectors( `(?<=(a{2,4}b{1,3}))x`, "yyaaaabx", "y", "$&-$1", "x-aaaab"),
326 TestVectors( `(?<=((?:a{2,4}b{1,3}){1,2}))x`, "aabbbaaaabx", "y", "$&-$1", "x-aabbbaaaab"),
327 TestVectors( `(?<=((?:a{2,4}b{1,3}){1,2}?))x`, "aabbbaaaabx", "y", "$&-$1", "x-aaaab"),
328 TestVectors( `(?<=(abc|def|aef))x`, "abcx", "y", "$&-$1", "x-abc"),
329 TestVectors( `(?<=(abc|def|aef))x`, "aefx", "y", "$&-$1", "x-aef"),
330 TestVectors( `(?<=(abc|dabc))(x)`, "dabcx", "y", "$&-$1-$2", "x-abc-x"),
331 TestVectors( `(?<=(|abc))x`, "dabcx", "y", "$&-$1", "x-"),
332 TestVectors( `(?<=((ab|da)*))x`, "abdaabx", "y", "$&-$2-$1", "x-ab-abdaab"),
333 TestVectors( `a(?<=(ba(?<=(aba)(?<=aaba))))`, "aabaa", "y", "$&-$1-$2", "a-ba-aba"),
334 TestVectors( `.(?<!b).`, "bax", "y", "$&", "ax"),
335 TestVectors( `(?<=b(?<!ab)).`, "abbx", "y", "$&", "x"),
336 TestVectors( `(?<=\.|[!?]+)X`, "Hey?!X", "y", "$&", "X"),
337 TestVectors( `(?<=\.|[!?]+)a{3}`, ".Nope.aaaX", "y", "$&", "aaa"),
339 TestVectors( `a(?<=a(?=b))b`, "ab", "y", "$&", "ab"),
340 TestVectors( `a(?<=a(?!b))c`, "ac", "y", "$&", "ac"),
341 TestVectors( `a(?i)bc`, "aBc", "y", "$&", "aBc"),
342 TestVectors( `a(?i)bc`, "Abc", "n", "$&", "-"),
343 TestVectors( `(?i)a(?-i)bc`, "aBcAbc", "y", "$&", "Abc"),
344 TestVectors( `(?s).(?-s).`, "\n\n\na", "y", "$&", "\na"),
345 TestVectors( `(?m)^a(?-m)$`, "\na", "y", "$&", "a")
347 string produceExpected(M,String)(auto ref M m, String fmt)
349 auto app = appender!(String)();
350 replaceFmt(fmt, m.captures, app, true);
353 void run_tests(alias matchFn)()
356 foreach (Char; AliasSeq!( char, wchar, dchar))
357 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
358 alias String = immutable(Char)[];
359 String produceExpected(M,Range)(auto ref M m, Range fmt)
361 auto app = appender!(String)();
362 replaceFmt(fmt, m.captures, app, true);
368 uint c = tvd.result[0];
369 debug(std_regex_test) writeln(" Test #", a, " pattern: ", tvd.pattern, " with Char = ", Char.stringof);
373 r = regex(to!(String)(tvd.pattern), tvd.flags);
375 catch (RegexException e)
378 debug(std_regex_test) writeln(e.msg);
381 assert((c == 'c') ? !i : i, "failed to compile pattern "~tvd.pattern);
385 auto m = matchFn(to!(String)(tvd.input), r);
389 text(matchFn.stringof ~": failed to match pattern #", a ,": ", tvd.pattern)
393 auto result = produceExpected(m, to!(String)(tvd.format));
394 assert(result == to!String(tvd.replace),
395 text(matchFn.stringof ~": mismatch pattern #", a, ": ", tvd.pattern," expected: ",
396 tvd.replace, " vs ", result));
401 debug(std_regex_test) writeln("!!! FReD bulk test done "~matchFn.stringof~" !!!");
407 import std.algorithm.comparison : equal;
408 version (std_regex_ct1)
410 pragma(msg, "Testing 1st part of ctRegex");
411 alias Tests = Sequence!(0, 155);
413 else version (std_regex_ct2)
415 pragma(msg, "Testing 2nd part of ctRegex");
416 alias Tests = Sequence!(155, 174);
418 //FIXME: #174-178 contains CTFE parser bug
419 else version (std_regex_ct3)
421 pragma(msg, "Testing 3rd part of ctRegex");
422 alias Tests = Sequence!(178, 220);
424 else version (std_regex_ct4)
426 pragma(msg, "Testing 4th part of ctRegex");
427 alias Tests = Sequence!(220, tv.length);
430 alias Tests = AliasSeq!(Sequence!(0, 30), Sequence!(235, tv.length-5));
431 foreach (a, v; Tests)
432 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
434 static if (tvd.result == "c")
436 static assert(!__traits(compiles, (){
437 enum r = regex(tvd.pattern, tvd.flags);
438 }), "errornously compiles regex pattern: " ~ tvd.pattern);
442 //BUG: tv[v] is fine but tvd is not known at compile time?!
443 auto r = ctRegex!(tv[v].pattern, tv[v].flags);
444 auto nr = regex(tvd.pattern, tvd.flags);
445 assert(equal(r.ir, nr.ir),
446 text("!C-T regex! failed to compile pattern #", a ,": ", tvd.pattern));
447 auto m = match(tvd.input, r);
448 auto c = tvd.result[0];
449 bool ok = (c == 'y') ^ m.empty;
450 assert(ok, text("ctRegex: failed to match pattern #",
451 a ,": ", tvd.pattern));
455 auto result = produceExpected(m, tvd.format);
456 if (result != tvd.replace)
457 writeln("ctRegex mismatch pattern #", a, ": ", tvd.pattern," expected: ",
458 tvd.replace, " vs ", result);
462 debug(std_regex_test) writeln("!!! FReD C-T test done !!!");
466 run_tests!bmatch(); //backtracker
467 run_tests!match(); //thompson VM
472 auto cr = ctRegex!("abc");
473 assert(bmatch("abc",cr).hit == "abc");
474 auto cr2 = ctRegex!("ab*c");
475 assert(bmatch("abbbbc",cr2).hit == "abbbbc");
479 auto cr3 = ctRegex!("^abc$");
480 assert(bmatch("abc",cr3).hit == "abc");
481 auto cr4 = ctRegex!(`\b(a\B[a-z]b)\b`);
482 assert(array(match("azb",cr4).captures) == ["azb", "azb"]);
487 auto cr5 = ctRegex!("(?:a{2,4}b{1,3}){1,2}");
488 assert(bmatch("aaabaaaabbb", cr5).hit == "aaabaaaabbb");
489 auto cr6 = ctRegex!("(?:a{2,4}b{1,3}){1,2}?"w);
490 assert(bmatch("aaabaaaabbb"w, cr6).hit == "aaab"w);
495 auto cr7 = ctRegex!(`\r.*?$`,"sm");
496 assert(bmatch("abc\r\nxy", cr7).hit == "\r\nxy");
497 auto greed = ctRegex!("<packet.*?/packet>");
498 assert(bmatch("<packet>text</packet><packet>text</packet>", greed).hit
499 == "<packet>text</packet>");
504 import std.algorithm.comparison : equal;
505 auto cr8 = ctRegex!("^(a)(b)?(c*)");
506 auto m8 = bmatch("abcc",cr8);
508 assert(m8.captures[1] == "a");
509 assert(m8.captures[2] == "b");
510 assert(m8.captures[3] == "cc");
511 auto cr9 = ctRegex!("q(a|b)*q");
512 auto m9 = match("xxqababqyy",cr9);
514 assert(equal(bmatch("xxqababqyy",cr9).captures, ["qababq", "b"]));
519 import std.algorithm.comparison : equal;
520 auto rtr = regex("a|b|c");
521 enum ctr = regex("a|b|c");
522 assert(equal(rtr.ir,ctr.ir));
523 //CTFE parser BUG is triggered by group
524 //in the middle of alternation (at least not first and not last)
525 enum testCT = regex(`abc|(edf)|xyz`);
526 auto testRT = regex(`abc|(edf)|xyz`);
527 assert(equal(testCT.ir,testRT.ir));
532 import std.algorithm.comparison : equal;
533 import std.algorithm.iteration : map;
534 enum cx = ctRegex!"(A|B|C)";
535 auto mx = match("B",cx);
537 assert(equal(mx.captures, [ "B", "B"]));
538 enum cx2 = ctRegex!"(A|B)*";
539 assert(match("BAAA",cx2));
541 enum cx3 = ctRegex!("a{3,4}","i");
542 auto mx3 = match("AaA",cx3);
544 assert(mx3.captures[0] == "AaA");
545 enum cx4 = ctRegex!(`^a{3,4}?[a-zA-Z0-9~]{1,2}`,"i");
546 auto mx4 = match("aaaabc", cx4);
548 assert(mx4.captures[0] == "aaaab");
549 auto cr8 = ctRegex!("(a)(b)?(c*)");
550 auto m8 = bmatch("abcc",cr8);
552 assert(m8.captures[1] == "a");
553 assert(m8.captures[2] == "b");
554 assert(m8.captures[3] == "cc");
555 auto cr9 = ctRegex!(".*$", "gm");
556 auto m9 = match("First\rSecond", cr9);
558 assert(equal(map!"a.hit"(m9), ["First", "", "Second"]));
563 import std.algorithm.comparison : equal;
564 import std.algorithm.iteration : map;
566 void test_body(alias matchFn)()
568 string s = "a quick brown fox jumps over a lazy dog";
569 auto r1 = regex("\\b[a-z]+\\b","g");
571 foreach (m; matchFn(s, r1))
573 assert(equal(test, [ "a", "quick", "brown", "fox", "jumps", "over", "a", "lazy", "dog"]));
574 auto free_reg = regex(`
586 auto m = match(`abc "quoted string with \" inside"z`,free_reg);
588 string mails = " hey@you.com no@spam.net ";
589 auto rm = regex(`@(?<=\S+@)\S+`,"g");
590 assert(equal(map!"a[0]"(matchFn(mails, rm)), ["@you.com", "@spam.net"]));
591 auto m2 = matchFn("First line\nSecond line",regex(".*$","gm"));
592 assert(equal(map!"a[0]"(m2), ["First line", "", "Second line"]));
593 auto m2a = matchFn("First line\nSecond line",regex(".+$","gm"));
594 assert(equal(map!"a[0]"(m2a), ["First line", "Second line"]));
595 auto m2b = matchFn("First line\nSecond line",regex(".+?$","gm"));
596 assert(equal(map!"a[0]"(m2b), ["First line", "Second line"]));
597 debug(std_regex_test) writeln("!!! FReD FLAGS test done "~matchFn.stringof~" !!!");
603 //tests for accumulated std.regex issues and other regressions
606 import std.algorithm.comparison : equal;
607 import std.algorithm.iteration : map;
608 void test_body(alias matchFn)()
611 //matching goes out of control if ... in (...){x} has .*/.+
612 auto c = matchFn("axxxzayyyyyzd",regex("(a.*z){2}d")).captures;
613 assert(c[0] == "axxxzayyyyyzd");
614 assert(c[1] == "ayyyyyz");
615 auto c2 = matchFn("axxxayyyyyd",regex("(a.*){2}d")).captures;
616 assert(c2[0] == "axxxayyyyyd");
617 assert(c2[1] == "ayyyyy");
619 //greedy vs non-greedy
620 auto nogreed = regex("<packet.*?/packet>");
621 assert(matchFn("<packet>text</packet><packet>text</packet>", nogreed).hit
622 == "<packet>text</packet>");
623 auto greed = regex("<packet.*/packet>");
624 assert(matchFn("<packet>text</packet><packet>text</packet>", greed).hit
625 == "<packet>text</packet><packet>text</packet>");
627 //empty successful match still advances the input
628 string[] pres, posts, hits;
629 foreach (m; matchFn("abcabc", regex("","g")))
654 assert(pres == array(retro(heads)));
655 assert(posts == tails);
658 auto re = regex("c.*|d");
659 auto m = matchFn("mm", re);
661 debug(std_regex_test) writeln("!!! FReD REGRESSION test done "~matchFn.stringof~" !!!");
662 auto rprealloc = regex(`((.){5}.{1,10}){5}`);
663 auto arr = array(repeat('0',100));
664 auto m2 = matchFn(arr, rprealloc);
666 assert(collectException(
667 regex(r"^(import|file|binary|config)\s+([^\(]+)\(?([^\)]*)\)?\s*$")
669 foreach (ch; [Escapables])
671 assert(match(to!string(ch),regex(`[\`~ch~`]`)));
672 assert(!match(to!string(ch),regex(`[^\`~ch~`]`)));
673 assert(match(to!string(ch),regex(`[\`~ch~`-\`~ch~`]`)));
676 string strcmd = "./myApp.rb -os OSX -path \"/GIT/Ruby Apps/sec\" -conf 'notimer'";
677 auto reStrCmd = regex (`(".*")|('.*')`, "g");
678 assert(equal(map!"a[0]"(matchFn(strcmd, reStrCmd)),
679 [`"/GIT/Ruby Apps/sec"`, `'notimer'`]));
688 void test(alias matchFn)()
690 import std.uni : toUpper;
692 foreach (i, v; AliasSeq!(string, wstring, dstring))
695 if (is(Cap == Captures!(Cap.String)))
697 return toUpper(m.hit);
700 assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r")), to!String("c"))
701 == to!String("ack rapacity"));
702 assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r"), "g"), to!String("c"))
703 == to!String("ack capacity"));
704 assert(std.regex.replace!(matchFn)(to!String("noon"), regex(to!String("^n")), to!String("[$&]"))
705 == to!String("[n]oon"));
706 assert(std.regex.replace!(matchFn)(
707 to!String("test1 test2"), regex(to!String(`\w+`),"g"), to!String("$`:$'")
708 ) == to!String(": test2 test1 :"));
709 auto s = std.regex.replace!(baz!(Captures!(String)))(to!String("Strap a rocket engine on a chicken."),
710 regex(to!String("[ar]"), "g"));
711 assert(s == "StRAp A Rocket engine on A chicken.");
713 debug(std_regex_test) writeln("!!! Replace test done "~matchFn.stringof~" !!!");
719 // tests for splitter
722 import std.algorithm.comparison : equal;
723 auto s1 = ", abc, de, fg, hi, ";
724 auto sp1 = splitter(s1, regex(", *"));
725 auto w1 = ["", "abc", "de", "fg", "hi", ""];
726 assert(equal(sp1, w1));
728 auto s2 = ", abc, de, fg, hi";
729 auto sp2 = splitter(s2, regex(", *"));
730 auto w2 = ["", "abc", "de", "fg", "hi"];
735 assert(w2[cnt++] == e);
737 assert(equal(sp2, w2));
742 char[] s1 = ", abc, de, fg, hi, ".dup;
743 auto sp2 = splitter(s1, regex(", *"));
748 import std.algorithm.comparison : equal;
749 auto s1 = ", abc, de, fg, hi, ";
750 auto w1 = ["", "abc", "de", "fg", "hi", ""];
751 assert(equal(split(s1, regex(", *")), w1[]));
756 string pattern = `[a\--b]`;
757 assert(match("-", pattern));
758 assert(match("b", pattern));
759 string pattern2 = `[&-z]`;
760 assert(match("b", pattern2));
764 assert(match("", regex("^")));
768 assert(!match("a"d, "aa"d));
774 auto r = regex("[]abc]*");
775 assert("]ab".matchFirst(r).hit == "]ab");
776 assertThrown(regex("[]"));
777 auto r2 = regex("[]abc--ab]*");
778 assert("]ac".matchFirst(r2).hit == "]");
783 assert("1234".replace(regex("^"), "$$") == "$1234");
784 assert("hello?".replace(regex(r"\?", "g"), r"\?") == r"hello\?");
785 assert("hello?".replace(regex(r"\?", "g"), r"\\?") != r"hello\?");
789 import std.algorithm.comparison : equal;
790 foreach (S; AliasSeq!(string, wstring, dstring))
791 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
792 enum re = ctRegex!(to!S(r"\."));
793 auto str = to!S("a.b");
794 assert(equal(std.regex.splitter(str, re), [to!S("a"), to!S("b")]));
795 assert(split(str, re) == [to!S("a"), to!S("b")]);
801 NAME = XPAW01_STA:STATION
804 auto uniFileOld = data;
806 r"^NAME = (?P<comp>[a-zA-Z0-9_]+):*(?P<blk>[a-zA-Z0-9_]*)","gm");
807 auto uniCapturesNew = match(uniFileOld, r);
808 for (int i = 0; i < 20; i++)
809 foreach (matchNew; uniCapturesNew) {}
810 //a second issue with same symptoms
811 auto r2 = regex(`([а-яА-Я\-_]+\s*)+(?<=[\s\.,\^])`);
812 match("аллея Театральная", r2);
815 {// bugzilla 8637 purity of enforce
816 auto m = match("hello world", regex("world"));
823 static italic = regex( r"\*
828 string input = "this * is* interesting, *very* interesting";
829 assert(replace(input, italic, "<i>$1</i>") ==
830 "this * is* interesting, <i>very</i> interesting");
836 enum peakRegexStr = r"\>(wgEncode.*Tfbs.*\.(?:narrow)|(?:broad)Peak.gz)</a>";
837 enum peakRegex = ctRegex!(peakRegexStr);
838 //note that the regex pattern itself is probably bogus
839 assert(match(r"\>wgEncode-blah-Tfbs.narrow</a>", peakRegex));
845 import std.algorithm.comparison : equal;
846 auto rx_1 = regex(r"^(\w)*(\d)");
847 auto m = match("1234", rx_1);
848 assert(equal(m.front, ["1234", "3", "4"]));
849 auto rx_2 = regex(r"^([0-9])*(\d)");
850 auto m2 = match("1234", rx_2);
851 assert(equal(m2.front, ["1234", "3", "4"]));
857 string tomatch = "a!b@c";
858 static r = regex(r"^(?P<nick>.*?)!(?P<ident>.*?)@(?P<host>.*?)$");
859 auto nm = match(tomatch, r);
861 auto c = nm.captures;
863 assert(c["nick"] == "a");
870 char[] input = ['a', 'b', 'c'];
871 string format = "($1)";
872 // used to give a compile error:
873 auto re = regex(`(a)`, "g");
874 auto r = replace(input, re, format);
875 assert(r == "(a)bc");
881 auto re = ctRegex!"(?:a+)";
882 assert(match("aaaa", re).hit == "aaaa");
888 auto cr = ctRegex!("[abcd--c]*");
889 auto m = "abc".match(cr);
891 assert(m.hit == "ab");
897 @system static string foo(const(char)[] s)
901 @safe static string bar(const(char)[] s)
906 replace!((a) => foo(a.hit))("blah", regex(`a`));
909 replace!((a) => bar(a.hit))("blah", regex(`a`));
916 enum reg = ctRegex!(r",", "g");
917 auto str = "This,List";
918 str = str.replace(reg, "-");
919 assert(str == "This-List");
925 assert(collectException(regex("a{1,0}")));
931 import std.algorithm.comparison : equal;
932 assert(regex(`(?P<var1>\w+)`).namedCaptures.equal(["var1"]));
933 assert(collectException(regex(`(?P<1>\w+)`)));
934 assert(regex(`(?P<v1>\w+)`).namedCaptures.equal(["v1"]));
935 assert(regex(`(?P<__>\w+)`).namedCaptures.equal(["__"]));
936 assert(regex(`(?P<я>\w+)`).namedCaptures.equal(["я"]));
942 auto RE = ctRegex!(r"(?<!x[a-z]+)\s([a-z]+)");
943 string s = "one two";
944 auto m = match(s, RE);
950 auto r = ctRegex!`.*?(?!a)`;
951 assert("aaab".matchFirst(r).hit == "aaa");
952 auto r2 = ctRegex!`.*(?!a)`;
953 assert("aaab".matchFirst(r2).hit == "aaab");
959 assert("abcdefghijklmnopqrstuvwxyz"
960 .matchFirst("[a-z&&[^aeiuo]]").hit == "b");
966 auto re = ctRegex!(`^((?=(xx+?)\2+$)((?=\2+$)(?=(x+)(\4+$))\5){2})*x?$`);
967 assert("xxxxxxxx".match(re).empty);
968 assert(!"xxxx".match(re).empty);
974 auto r = regex(`(?P<a>abc)`);
975 assert(collectException("abc".matchFirst(r)["b"]));
981 assert(bmatch("e@", "^([a-z]|)*$").empty);
982 assert(bmatch("e@", ctRegex!`^([a-z]|)*$`).empty);
988 assertThrown(regex("[[a-z]([a-z]|(([[a-z])))"));
994 assertThrown(regex(`^x(\1)`));
995 assertThrown(regex(`^(x(\1))`));
996 assertThrown(regex(`^((x)(?=\1))`));
1002 auto p = ctRegex!("a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?" ~
1003 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
1009 auto ctPat2 = regex(r"^[CDF]$", "i");
1010 foreach (v; ["C", "c", "D", "d", "F", "f"])
1011 assert(matchAll(v, ctPat2).front.hit == v);
1017 import std.array : appender;
1018 import std.regex : replaceFirst, replaceFirstInto, regex;
1019 import std.stdio : writeln;
1021 auto example = "Hello, world!";
1022 auto pattern = regex("^Hello, (bug)"); // won't find this one
1023 auto result = replaceFirst(example, pattern, "$1 Sponge Bob");
1024 assert(result == "Hello, world!"); // Ok.
1026 auto sink = appender!string;
1027 replaceFirstInto(sink, example, pattern, "$1 Sponge Bob");
1028 assert(sink.data == "Hello, world!");
1029 replaceAllInto(sink, example, pattern, "$1 Sponge Bob");
1030 assert(sink.data == "Hello, world!Hello, world!");
1036 auto rx = regex("[c d]", "x");
1037 assert("a b".matchFirst(rx));
1043 regex(`(<a (?:(?:\w+=\"[^"]*\")?\s*)*href="\.\.?)"`);
1048 auto r = regex("(?# comment)abc(?# comment2)");
1049 assert("abc".matchFirst(r));
1050 assertThrown(regex("(?#..."));
1056 enum titlePattern = `<title>(.+)</title>`;
1057 static titleRegex = ctRegex!titlePattern;
1058 string input = "<title>" ~ "<".repeat(100_000).join;
1059 assert(input.matchFirst(titleRegex).empty);
1065 auto r = regex(" [a] ", "x");
1066 assert("a".matchFirst(r));
1072 import std.algorithm.comparison : equal;
1073 auto ctr = ctRegex!"(a)|(b)|(c)|(d)";
1074 auto r = regex("(a)|(b)|(c)|(d)", "g");
1075 auto s = "--a--b--c--d--";
1077 ["a", "a", "", "", ""],
1078 ["b", "", "b", "", ""],
1079 ["c", "", "", "c", ""],
1080 ["d", "", "", "", "d"]
1082 assert(equal!equal(s.matchAll(ctr), outcomes));
1083 assert(equal!equal(s.bmatch(r), outcomes));
1089 import std.algorithm.searching : canFind;
1090 void willThrow(T, size_t line = __LINE__)(T arg, string msg)
1092 auto e = collectException(regex(arg));
1093 assert(e.msg.canFind(msg), to!string(line) ~ ": " ~ e.msg);
1095 willThrow([r".", r"[\(\{[\]\}\)]"], "no matching ']' found while parsing character class");
1096 willThrow([r"[\", r"123"], "no matching ']' found while parsing character class");
1097 willThrow([r"[a-", r"123"], "no matching ']' found while parsing character class");
1098 willThrow([r"[a-\", r"123"], "invalid escape sequence");
1099 willThrow([r"\", r"123"], "invalid escape sequence");
1105 import std.algorithm.searching;
1106 auto e = collectException!RegexException(regex(q"<[^]>"));
1107 assert(e.msg.canFind("no operand for '^'"));
1114 string[] regexps = ["abc", "\"|x"];
1115 auto regexp = regex(regexps);
1116 auto c = matchFirst(str, regexp);
1118 assert(c.whichPattern == 2);