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 24 description( 25 'Test regular expression processing with alternatives that match consuming no characters' 26 ); 27 28 var emptyStr = ""; 29 var s1 = "xxxx"; 30 var s2 = "aaaa"; 31 var s3 = "aax"; 32 var s4 = "abab"; 33 var s5 = "ab"; 34 var s6 = "xabx"; 35 var s7 = "g0"; 36 37 // Non-capturing empty first alternative greedy '*' 38 var re1 = new RegExp(/(?:|a|z)*/); 39 shouldBe('emptyStr.match(re1)', '[""]'); 40 shouldBe('s1.match(re1)', '[""]'); 41 shouldBe('s2.match(re1)', '["aaaa"]'); 42 shouldBe('s3.match(re1)', '["aa"]'); 43 44 // Non-capturing empty middle alternative greedy '*' 45 var re2 = new RegExp(/(?:a||z)*/); 46 shouldBe('emptyStr.match(re2)', '[""]'); 47 shouldBe('s1.match(re2)', '[""]'); 48 shouldBe('s2.match(re2)', '["aaaa"]'); 49 shouldBe('s3.match(re2)', '["aa"]'); 50 51 // Non-capturing empty last alternative greedy '*' 52 var re3 = new RegExp(/(?:a|z|)*/); 53 shouldBe('emptyStr.match(re3)', '[""]'); 54 shouldBe('s1.match(re3)', '[""]'); 55 shouldBe('s2.match(re3)', '["aaaa"]'); 56 shouldBe('s3.match(re3)', '["aa"]'); 57 58 // Capturing empty first alternative greedy '*' 59 var re4 = new RegExp(/(|a|z)*/); 60 shouldBe('emptyStr.match(re4)', '["", undefined]'); 61 shouldBe('s1.match(re4)', '["", undefined]'); 62 shouldBe('s2.match(re4)', '["aaaa", "a"]'); 63 shouldBe('s3.match(re4)', '["aa", "a"]'); 64 65 // Capturing empty middle alternative greedy '*' 66 var re5 = new RegExp(/(a||z)*/); 67 shouldBe('emptyStr.match(re5)', '["", undefined]'); 68 shouldBe('s1.match(re5)', '["", undefined]'); 69 shouldBe('s2.match(re5)', '["aaaa", "a"]'); 70 shouldBe('s3.match(re5)', '["aa", "a"]'); 71 72 // Capturing empty last alternative greedy '*' 73 var re6 = new RegExp(/(a|z|)*/); 74 shouldBe('emptyStr.match(re6)', '["", undefined]'); 75 shouldBe('s1.match(re6)', '["", undefined]'); 76 shouldBe('s2.match(re6)', '["aaaa", "a"]'); 77 shouldBe('s3.match(re6)', '["aa", "a"]'); 78 79 // Non-capturing empty first alternative fixed-count 80 var re7 = new RegExp(/(?:|a|z){2,5}/); 81 shouldBe('emptyStr.match(re7)', '[""]'); 82 shouldBe('s1.match(re7)', '[""]'); 83 shouldBe('s2.match(re7)', '["aaa"]'); 84 shouldBe('s3.match(re7)', '["aa"]'); 85 86 // Non-capturing empty middle alternative fixed-count 87 var re8 = new RegExp(/(?:a||z){2,5}/); 88 shouldBe('emptyStr.match(re8)', '[""]'); 89 shouldBe('s1.match(re8)', '[""]'); 90 shouldBe('s2.match(re8)', '["aaaa"]'); 91 shouldBe('s3.match(re8)', '["aa"]'); 92 93 // Non-capturing empty last alternative fixed-count 94 var re9 = new RegExp(/(?:a|z|){2,5}/); 95 shouldBe('emptyStr.match(re9)', '[""]'); 96 shouldBe('s1.match(re9)', '[""]'); 97 shouldBe('s2.match(re9)', '["aaaa"]'); 98 shouldBe('s3.match(re9)', '["aa"]'); 99 100 // Non-capturing empty first alternative non-greedy '*' 101 var re10 = new RegExp(/(?:|a|z)*?/); 102 shouldBe('emptyStr.match(re10)', '[""]'); 103 shouldBe('s1.match(re10)', '[""]'); 104 shouldBe('s2.match(re10)', '[""]'); 105 shouldBe('s3.match(re10)', '[""]'); 106 107 // Non-capturing empty middle alternative non-greedy '*' 108 var re11 = new RegExp(/(?:a||z)*?/); 109 shouldBe('emptyStr.match(re11)', '[""]'); 110 shouldBe('s1.match(re11)', '[""]'); 111 shouldBe('s2.match(re11)', '[""]'); 112 shouldBe('s3.match(re11)', '[""]'); 113 114 // Non-capturing empty last alternative non-greedy '*' 115 var re12 = new RegExp(/(?:a|z|)*?/); 116 shouldBe('emptyStr.match(re12)', '[""]'); 117 shouldBe('s1.match(re12)', '[""]'); 118 shouldBe('s2.match(re12)', '[""]'); 119 shouldBe('s3.match(re12)', '[""]'); 120 121 // Capturing empty first alternative non-greedy '*' 122 var re13 = new RegExp(/(|a|z)*?/); 123 shouldBe('emptyStr.match(re13)', '["", undefined]'); 124 shouldBe('s1.match(re13)', '["", undefined]'); 125 shouldBe('s2.match(re13)', '["", undefined]'); 126 shouldBe('s3.match(re13)', '["", undefined]'); 127 128 // Capturing empty middle alternative non-greedy '*' 129 var re14 = new RegExp(/(a||z)*?/); 130 shouldBe('emptyStr.match(re14)', '["", undefined]'); 131 shouldBe('s1.match(re14)', '["", undefined]'); 132 shouldBe('s2.match(re14)', '["", undefined]'); 133 shouldBe('s3.match(re14)', '["", undefined]'); 134 135 // Capturing empty last alternative non-greedy '*' 136 var re15 = new RegExp(/(a|z|)*?/); 137 shouldBe('emptyStr.match(re15)', '["", undefined]'); 138 shouldBe('s1.match(re15)', '["", undefined]'); 139 shouldBe('s2.match(re15)', '["", undefined]'); 140 shouldBe('s3.match(re15)', '["", undefined]'); 141 142 // Non-capturing empty first alternative greedy '?' 143 var re16 = new RegExp(/(?:|a|z)?/); 144 shouldBe('emptyStr.match(re16)', '[""]'); 145 shouldBe('s1.match(re16)', '[""]'); 146 shouldBe('s2.match(re16)', '["a"]'); 147 shouldBe('s3.match(re16)', '["a"]'); 148 149 // Non-capturing empty middle alternative greedy '?' 150 var re17 = new RegExp(/(?:a||z)?/); 151 shouldBe('emptyStr.match(re17)', '[""]'); 152 shouldBe('s1.match(re17)', '[""]'); 153 shouldBe('s2.match(re17)', '["a"]'); 154 shouldBe('s3.match(re17)', '["a"]'); 155 156 // Non-capturing empty last alternative greedy '?' 157 var re18 = new RegExp(/(?:a|z|)?/); 158 shouldBe('emptyStr.match(re18)', '[""]'); 159 shouldBe('s1.match(re18)', '[""]'); 160 shouldBe('s2.match(re18)', '["a"]'); 161 shouldBe('s3.match(re18)', '["a"]'); 162 163 // Capturing empty first alternative greedy '?' 164 var re19 = new RegExp(/(|a|z)?/); 165 shouldBe('emptyStr.match(re19)', '["", undefined]'); 166 shouldBe('s1.match(re19)', '["", undefined]'); 167 shouldBe('s2.match(re19)', '["a", "a"]'); 168 shouldBe('s3.match(re19)', '["a", "a"]'); 169 170 // Capturing empty middle alternative greedy '?' 171 var re20 = new RegExp(/(a||z)?/); 172 shouldBe('emptyStr.match(re20)', '["", undefined]'); 173 shouldBe('s1.match(re20)', '["", undefined]'); 174 shouldBe('s2.match(re20)', '["a", "a"]'); 175 shouldBe('s3.match(re20)', '["a", "a"]'); 176 177 // Capturing empty last alternative greedy '?' 178 var re21 = new RegExp(/(a|z|)?/); 179 shouldBe('emptyStr.match(re21)', '["", undefined]'); 180 shouldBe('s1.match(re21)', '["", undefined]'); 181 shouldBe('s2.match(re21)', '["a", "a"]'); 182 shouldBe('s3.match(re21)', '["a", "a"]'); 183 184 // Non-capturing empty first alternative non-greedy '?' 185 var re22 = new RegExp(/(?:|a|z)??/); 186 shouldBe('emptyStr.match(re22)', '[""]'); 187 shouldBe('s1.match(re22)', '[""]'); 188 shouldBe('s2.match(re22)', '[""]'); 189 shouldBe('s3.match(re22)', '[""]'); 190 191 // Non-capturing empty middle alternative non-greedy '?' 192 var re23 = new RegExp(/(?:a||z)??/); 193 shouldBe('emptyStr.match(re23)', '[""]'); 194 shouldBe('s1.match(re23)', '[""]'); 195 shouldBe('s2.match(re23)', '[""]'); 196 shouldBe('s3.match(re23)', '[""]'); 197 198 // Non-capturing empty last alternative non-greedy '?' 199 var re24 = new RegExp(/(?:a|z|)??/); 200 shouldBe('emptyStr.match(re24)', '[""]'); 201 shouldBe('s1.match(re24)', '[""]'); 202 shouldBe('s2.match(re24)', '[""]'); 203 shouldBe('s3.match(re24)', '[""]'); 204 205 // Capturing empty first alternative non-greedy '?' 206 var re25 = new RegExp(/(|a|z)??/); 207 shouldBe('emptyStr.match(re25)', '["", undefined]'); 208 shouldBe('s1.match(re25)', '["", undefined]'); 209 shouldBe('s2.match(re25)', '["", undefined]'); 210 shouldBe('s3.match(re25)', '["", undefined]'); 211 212 // Capturing empty middle alternative non-greedy '?' 213 var re26 = new RegExp(/(a||z)??/); 214 shouldBe('emptyStr.match(re26)', '["", undefined]'); 215 shouldBe('s1.match(re26)', '["", undefined]'); 216 shouldBe('s2.match(re26)', '["", undefined]'); 217 shouldBe('s3.match(re26)', '["", undefined]'); 218 219 // Capturing empty last alternative non-greedy '?' 220 var re27 = new RegExp(/(a|z|)??/); 221 shouldBe('emptyStr.match(re27)', '["", undefined]'); 222 shouldBe('s1.match(re27)', '["", undefined]'); 223 shouldBe('s2.match(re27)', '["", undefined]'); 224 shouldBe('s3.match(re27)', '["", undefined]'); 225 226 // Non-capturing empty first alternative greedy '*' non-terminal 227 var re28 = new RegExp(/(?:|a|z)*x/); 228 shouldBe('emptyStr.match(re28)', 'null'); 229 shouldBe('s1.match(re28)', '["x"]'); 230 shouldBe('s2.match(re28)', 'null'); 231 shouldBe('s3.match(re28)', '["aax"]'); 232 233 // Non-capturing empty middle alternative greedy '*' non-terminal 234 var re29 = new RegExp(/(?:a||z)*x/); 235 shouldBe('emptyStr.match(re29)', 'null'); 236 shouldBe('s1.match(re29)', '["x"]'); 237 shouldBe('s2.match(re29)', 'null'); 238 shouldBe('s3.match(re29)', '["aax"]'); 239 240 // Non-capturing empty last alternative greedy '*' non-terminal 241 var re30 = new RegExp(/(?:a|z|)*x/); 242 shouldBe('emptyStr.match(re30)', 'null'); 243 shouldBe('s1.match(re30)', '["x"]'); 244 shouldBe('s2.match(re30)', 'null'); 245 shouldBe('s3.match(re30)', '["aax"]'); 246 247 // Non-capturing two possibly empty alternatives greedy '*' 248 var re31 = new RegExp(/(?:a*|b*)*/); 249 shouldBe('emptyStr.match(re31)', '[""]'); 250 shouldBe('s1.match(re31)', '[""]'); 251 shouldBe('s3.match(re31)', '["aa"]'); 252 shouldBe('s4.match(re31)', '["abab"]'); 253 254 // Non-capturing two possibly empty non-greedy alternatives non-greedy '*' 255 var re32 = new RegExp(/(?:a*?|b*?)*/); 256 shouldBe('emptyStr.match(re32)', '[""]'); 257 shouldBe('s1.match(re32)', '[""]'); 258 shouldBe('s2.match(re32)', '["aaaa"]'); 259 shouldBe('s4.match(re32)', '["abab"]'); 260 shouldBe('s5.match(re32)', '["ab"]'); 261 shouldBe('s6.match(re32)', '[""]'); 262 263 // Three possibly empty alternatives with greedy + 264 var re33 = new RegExp(/(?:(?:(?!))|g?|0*\*?)+/); 265 shouldBe('emptyStr.match(re33)', '[""]'); 266 shouldBe('s1.match(re33)', '[""]'); 267 shouldBe('s7.match(re33)', '["g0"]'); 268 269 // first alternative zero length fixed count 270 var re34 = new RegExp(/(?:|a)/); 271 shouldBe('emptyStr.match(re34)', '[""]'); 272 shouldBe('s1.match(re34)', '[""]'); 273 shouldBe('s2.match(re34)', '[""]'); 274 shouldBe('s3.match(re34)', '[""]'); 275