Factors common prefixes from alternation. For example, ABC|ABD|AEF|BCX|BCY simplifies to A(B(C|D)|EF)|BC(X|Y) and thence to A(B[CD]|EF)|BC[XY] Rewrites sub to contain simplified list to alternate and returns the new length of sub. Adjusts reference counts accordingly (incoming sub[i] decremented, outgoing sub[i] incremented).
| 931 | // the new length of sub. Adjusts reference counts accordingly |
| 932 | // (incoming sub[i] decremented, outgoing sub[i] incremented). |
| 933 | int Regexp::FactorAlternation(Regexp** sub, int nsub, ParseFlags flags) { |
| 934 | std::vector<Frame> stk; |
| 935 | stk.emplace_back(sub, nsub); |
| 936 | |
| 937 | for (;;) { |
| 938 | auto& sub = stk.back().sub; |
| 939 | auto& nsub = stk.back().nsub; |
| 940 | auto& round = stk.back().round; |
| 941 | auto& splices = stk.back().splices; |
| 942 | auto& spliceidx = stk.back().spliceidx; |
| 943 | |
| 944 | if (splices.empty()) { |
| 945 | // Advance to the next round of factoring. Note that this covers |
| 946 | // the initialised state: when splices is empty and round is 0. |
| 947 | round++; |
| 948 | } else if (spliceidx < static_cast<int>(splices.size())) { |
| 949 | // We have at least one more Splice to factor. Recurse logically. |
| 950 | stk.emplace_back(splices[spliceidx].sub, splices[spliceidx].nsub); |
| 951 | continue; |
| 952 | } else { |
| 953 | // We have no more Splices to factor. Apply them. |
| 954 | auto iter = splices.begin(); |
| 955 | int out = 0; |
| 956 | for (int i = 0; i < nsub; ) { |
| 957 | // Copy until we reach where the next Splice begins. |
| 958 | while (sub + i < iter->sub) |
| 959 | sub[out++] = sub[i++]; |
| 960 | switch (round) { |
| 961 | case 1: |
| 962 | case 2: { |
| 963 | // Assemble the Splice prefix and the suffixes. |
| 964 | Regexp* re[2]; |
| 965 | re[0] = iter->prefix; |
| 966 | re[1] = Regexp::AlternateNoFactor(iter->sub, iter->nsuffix, flags); |
| 967 | sub[out++] = Regexp::Concat(re, 2, flags); |
| 968 | i += iter->nsub; |
| 969 | break; |
| 970 | } |
| 971 | case 3: |
| 972 | // Just use the Splice prefix. |
| 973 | sub[out++] = iter->prefix; |
| 974 | i += iter->nsub; |
| 975 | break; |
| 976 | default: |
| 977 | LOG(DFATAL) << "unknown round: " << round; |
| 978 | break; |
| 979 | } |
| 980 | // If we are done, copy until the end of sub. |
| 981 | if (++iter == splices.end()) { |
| 982 | while (i < nsub) |
| 983 | sub[out++] = sub[i++]; |
| 984 | } |
| 985 | } |
| 986 | splices.clear(); |
| 987 | nsub = out; |
| 988 | // Advance to the next round of factoring. |
| 989 | round++; |
| 990 | } |