| 316 | // so that there is never a concat of a concat or an |
| 317 | // alternate of an alternate. |
| 318 | private Regexp collapse(Regexp[] subs, Regexp.Op op) { |
| 319 | if (subs.length == 1) { |
| 320 | return subs[0]; |
| 321 | } |
| 322 | // Concatenate subs iff op is same. |
| 323 | // Compute length in first pass. |
| 324 | int len = 0; |
| 325 | for (Regexp sub : subs) { |
| 326 | len += (sub.op == op) ? sub.subs.length : 1; |
| 327 | } |
| 328 | Regexp[] newsubs = new Regexp[len]; |
| 329 | int i = 0; |
| 330 | for (Regexp sub : subs) { |
| 331 | if (sub.op == op) { |
| 332 | System.arraycopy(sub.subs, 0, newsubs, i, sub.subs.length); |
| 333 | i += sub.subs.length; |
| 334 | reuse(sub); |
| 335 | } else { |
| 336 | newsubs[i++] = sub; |
| 337 | } |
| 338 | } |
| 339 | Regexp re = newRegexp(op); |
| 340 | re.subs = newsubs; |
| 341 | |
| 342 | if (op == Regexp.Op.ALTERNATE) { |
| 343 | re.subs = factor(re.subs, re.flags); |
| 344 | if (re.subs.length == 1) { |
| 345 | Regexp old = re; |
| 346 | re = re.subs[0]; |
| 347 | reuse(old); |
| 348 | } |
| 349 | } |
| 350 | return re; |
| 351 | } |
| 352 | |
| 353 | // factor factors common prefixes from the alternation list sub. It |
| 354 | // returns a replacement list that reuses the same storage and frees |