1// Copyright 2013 the V8 project authors. All rights reserved.
2// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are met:
7// 1.  Redistributions of source code must retain the above copyright
8//     notice, this list of conditions and the following disclaimer.
9// 2.  Redistributions in binary form must reproduce the above copyright
10//     notice, this list of conditions and the following disclaimer in the
11//     documentation and/or other materials provided with the distribution.
12//
13// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16// DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24description(
25'Test regular expression processing with alternatives that match consuming no characters'
26);
27
28var emptyStr = "";
29var s1 = "xxxx";
30var s2 = "aaaa";
31var s3 = "aax";
32var s4 = "abab";
33var s5 = "ab";
34var s6 = "xabx";
35var s7 = "g0";
36
37// Non-capturing empty first alternative greedy '*'
38var re1 = new RegExp(/(?:|a|z)*/);
39shouldBe('emptyStr.match(re1)', '[""]');
40shouldBe('s1.match(re1)', '[""]');
41shouldBe('s2.match(re1)', '["aaaa"]');
42shouldBe('s3.match(re1)', '["aa"]');
43
44// Non-capturing empty middle alternative greedy '*'
45var re2 = new RegExp(/(?:a||z)*/);
46shouldBe('emptyStr.match(re2)', '[""]');
47shouldBe('s1.match(re2)', '[""]');
48shouldBe('s2.match(re2)', '["aaaa"]');
49shouldBe('s3.match(re2)', '["aa"]');
50
51// Non-capturing empty last alternative greedy '*'
52var re3 = new RegExp(/(?:a|z|)*/);
53shouldBe('emptyStr.match(re3)', '[""]');
54shouldBe('s1.match(re3)', '[""]');
55shouldBe('s2.match(re3)', '["aaaa"]');
56shouldBe('s3.match(re3)', '["aa"]');
57
58// Capturing empty first alternative greedy '*'
59var re4 = new RegExp(/(|a|z)*/);
60shouldBe('emptyStr.match(re4)', '["", undefined]');
61shouldBe('s1.match(re4)', '["", undefined]');
62shouldBe('s2.match(re4)', '["aaaa", "a"]');
63shouldBe('s3.match(re4)', '["aa", "a"]');
64
65// Capturing empty middle alternative greedy '*'
66var re5 = new RegExp(/(a||z)*/);
67shouldBe('emptyStr.match(re5)', '["", undefined]');
68shouldBe('s1.match(re5)', '["", undefined]');
69shouldBe('s2.match(re5)', '["aaaa", "a"]');
70shouldBe('s3.match(re5)', '["aa", "a"]');
71
72// Capturing empty last alternative greedy '*'
73var re6 = new RegExp(/(a|z|)*/);
74shouldBe('emptyStr.match(re6)', '["", undefined]');
75shouldBe('s1.match(re6)', '["", undefined]');
76shouldBe('s2.match(re6)', '["aaaa", "a"]');
77shouldBe('s3.match(re6)', '["aa", "a"]');
78
79// Non-capturing empty first alternative fixed-count
80var re7 = new RegExp(/(?:|a|z){2,5}/);
81shouldBe('emptyStr.match(re7)', '[""]');
82shouldBe('s1.match(re7)', '[""]');
83shouldBe('s2.match(re7)', '["aaa"]');
84shouldBe('s3.match(re7)', '["aa"]');
85
86// Non-capturing empty middle alternative fixed-count
87var re8 = new RegExp(/(?:a||z){2,5}/);
88shouldBe('emptyStr.match(re8)', '[""]');
89shouldBe('s1.match(re8)', '[""]');
90shouldBe('s2.match(re8)', '["aaaa"]');
91shouldBe('s3.match(re8)', '["aa"]');
92
93// Non-capturing empty last alternative fixed-count
94var re9 = new RegExp(/(?:a|z|){2,5}/);
95shouldBe('emptyStr.match(re9)', '[""]');
96shouldBe('s1.match(re9)', '[""]');
97shouldBe('s2.match(re9)', '["aaaa"]');
98shouldBe('s3.match(re9)', '["aa"]');
99
100// Non-capturing empty first alternative non-greedy '*'
101var re10 = new RegExp(/(?:|a|z)*?/);
102shouldBe('emptyStr.match(re10)', '[""]');
103shouldBe('s1.match(re10)', '[""]');
104shouldBe('s2.match(re10)', '[""]');
105shouldBe('s3.match(re10)', '[""]');
106
107// Non-capturing empty middle alternative non-greedy '*'
108var re11 = new RegExp(/(?:a||z)*?/);
109shouldBe('emptyStr.match(re11)', '[""]');
110shouldBe('s1.match(re11)', '[""]');
111shouldBe('s2.match(re11)', '[""]');
112shouldBe('s3.match(re11)', '[""]');
113
114// Non-capturing empty last alternative non-greedy '*'
115var re12 = new RegExp(/(?:a|z|)*?/);
116shouldBe('emptyStr.match(re12)', '[""]');
117shouldBe('s1.match(re12)', '[""]');
118shouldBe('s2.match(re12)', '[""]');
119shouldBe('s3.match(re12)', '[""]');
120
121// Capturing empty first alternative non-greedy '*'
122var re13 = new RegExp(/(|a|z)*?/);
123shouldBe('emptyStr.match(re13)', '["", undefined]');
124shouldBe('s1.match(re13)', '["", undefined]');
125shouldBe('s2.match(re13)', '["", undefined]');
126shouldBe('s3.match(re13)', '["", undefined]');
127
128// Capturing empty middle alternative non-greedy '*'
129var re14 = new RegExp(/(a||z)*?/);
130shouldBe('emptyStr.match(re14)', '["", undefined]');
131shouldBe('s1.match(re14)', '["", undefined]');
132shouldBe('s2.match(re14)', '["", undefined]');
133shouldBe('s3.match(re14)', '["", undefined]');
134
135// Capturing empty last alternative non-greedy '*'
136var re15 = new RegExp(/(a|z|)*?/);
137shouldBe('emptyStr.match(re15)', '["", undefined]');
138shouldBe('s1.match(re15)', '["", undefined]');
139shouldBe('s2.match(re15)', '["", undefined]');
140shouldBe('s3.match(re15)', '["", undefined]');
141
142// Non-capturing empty first alternative greedy '?'
143var re16 = new RegExp(/(?:|a|z)?/);
144shouldBe('emptyStr.match(re16)', '[""]');
145shouldBe('s1.match(re16)', '[""]');
146shouldBe('s2.match(re16)', '["a"]');
147shouldBe('s3.match(re16)', '["a"]');
148
149// Non-capturing empty middle alternative greedy '?'
150var re17 = new RegExp(/(?:a||z)?/);
151shouldBe('emptyStr.match(re17)', '[""]');
152shouldBe('s1.match(re17)', '[""]');
153shouldBe('s2.match(re17)', '["a"]');
154shouldBe('s3.match(re17)', '["a"]');
155
156// Non-capturing empty last alternative greedy '?'
157var re18 = new RegExp(/(?:a|z|)?/);
158shouldBe('emptyStr.match(re18)', '[""]');
159shouldBe('s1.match(re18)', '[""]');
160shouldBe('s2.match(re18)', '["a"]');
161shouldBe('s3.match(re18)', '["a"]');
162
163// Capturing empty first alternative greedy '?'
164var re19 = new RegExp(/(|a|z)?/);
165shouldBe('emptyStr.match(re19)', '["", undefined]');
166shouldBe('s1.match(re19)', '["", undefined]');
167shouldBe('s2.match(re19)', '["a", "a"]');
168shouldBe('s3.match(re19)', '["a", "a"]');
169
170// Capturing empty middle alternative greedy '?'
171var re20 = new RegExp(/(a||z)?/);
172shouldBe('emptyStr.match(re20)', '["", undefined]');
173shouldBe('s1.match(re20)', '["", undefined]');
174shouldBe('s2.match(re20)', '["a", "a"]');
175shouldBe('s3.match(re20)', '["a", "a"]');
176
177// Capturing empty last alternative greedy '?'
178var re21 = new RegExp(/(a|z|)?/);
179shouldBe('emptyStr.match(re21)', '["", undefined]');
180shouldBe('s1.match(re21)', '["", undefined]');
181shouldBe('s2.match(re21)', '["a", "a"]');
182shouldBe('s3.match(re21)', '["a", "a"]');
183
184// Non-capturing empty first alternative non-greedy '?'
185var re22 = new RegExp(/(?:|a|z)??/);
186shouldBe('emptyStr.match(re22)', '[""]');
187shouldBe('s1.match(re22)', '[""]');
188shouldBe('s2.match(re22)', '[""]');
189shouldBe('s3.match(re22)', '[""]');
190
191// Non-capturing empty middle alternative non-greedy '?'
192var re23 = new RegExp(/(?:a||z)??/);
193shouldBe('emptyStr.match(re23)', '[""]');
194shouldBe('s1.match(re23)', '[""]');
195shouldBe('s2.match(re23)', '[""]');
196shouldBe('s3.match(re23)', '[""]');
197
198// Non-capturing empty last alternative non-greedy '?'
199var re24 = new RegExp(/(?:a|z|)??/);
200shouldBe('emptyStr.match(re24)', '[""]');
201shouldBe('s1.match(re24)', '[""]');
202shouldBe('s2.match(re24)', '[""]');
203shouldBe('s3.match(re24)', '[""]');
204
205// Capturing empty first alternative non-greedy '?'
206var re25 = new RegExp(/(|a|z)??/);
207shouldBe('emptyStr.match(re25)', '["", undefined]');
208shouldBe('s1.match(re25)', '["", undefined]');
209shouldBe('s2.match(re25)', '["", undefined]');
210shouldBe('s3.match(re25)', '["", undefined]');
211
212// Capturing empty middle alternative non-greedy '?'
213var re26 = new RegExp(/(a||z)??/);
214shouldBe('emptyStr.match(re26)', '["", undefined]');
215shouldBe('s1.match(re26)', '["", undefined]');
216shouldBe('s2.match(re26)', '["", undefined]');
217shouldBe('s3.match(re26)', '["", undefined]');
218
219// Capturing empty last alternative non-greedy '?'
220var re27 = new RegExp(/(a|z|)??/);
221shouldBe('emptyStr.match(re27)', '["", undefined]');
222shouldBe('s1.match(re27)', '["", undefined]');
223shouldBe('s2.match(re27)', '["", undefined]');
224shouldBe('s3.match(re27)', '["", undefined]');
225
226// Non-capturing empty first alternative greedy '*' non-terminal
227var re28 = new RegExp(/(?:|a|z)*x/);
228shouldBe('emptyStr.match(re28)', 'null');
229shouldBe('s1.match(re28)', '["x"]');
230shouldBe('s2.match(re28)', 'null');
231shouldBe('s3.match(re28)', '["aax"]');
232
233// Non-capturing empty middle alternative greedy '*' non-terminal
234var re29 = new RegExp(/(?:a||z)*x/);
235shouldBe('emptyStr.match(re29)', 'null');
236shouldBe('s1.match(re29)', '["x"]');
237shouldBe('s2.match(re29)', 'null');
238shouldBe('s3.match(re29)', '["aax"]');
239
240// Non-capturing empty last alternative greedy '*' non-terminal
241var re30 = new RegExp(/(?:a|z|)*x/);
242shouldBe('emptyStr.match(re30)', 'null');
243shouldBe('s1.match(re30)', '["x"]');
244shouldBe('s2.match(re30)', 'null');
245shouldBe('s3.match(re30)', '["aax"]');
246
247// Non-capturing two possibly empty alternatives greedy '*'
248var re31 = new RegExp(/(?:a*|b*)*/);
249shouldBe('emptyStr.match(re31)', '[""]');
250shouldBe('s1.match(re31)', '[""]');
251shouldBe('s3.match(re31)', '["aa"]');
252shouldBe('s4.match(re31)', '["abab"]');
253
254// Non-capturing two possibly empty non-greedy alternatives non-greedy '*'
255var re32 = new RegExp(/(?:a*?|b*?)*/);
256shouldBe('emptyStr.match(re32)', '[""]');
257shouldBe('s1.match(re32)', '[""]');
258shouldBe('s2.match(re32)', '["aaaa"]');
259shouldBe('s4.match(re32)', '["abab"]');
260shouldBe('s5.match(re32)', '["ab"]');
261shouldBe('s6.match(re32)', '[""]');
262
263// Three possibly empty alternatives with greedy +
264var re33 = new RegExp(/(?:(?:(?!))|g?|0*\*?)+/);
265shouldBe('emptyStr.match(re33)', '[""]');
266shouldBe('s1.match(re33)', '[""]');
267shouldBe('s7.match(re33)', '["g0"]');
268
269// first alternative zero length fixed count
270var re34 = new RegExp(/(?:|a)/);
271shouldBe('emptyStr.match(re34)', '[""]');
272shouldBe('s1.match(re34)', '[""]');
273shouldBe('s2.match(re34)', '[""]');
274shouldBe('s3.match(re34)', '[""]');
275