| 1143 | } |
| 1144 | |
| 1145 | void FactorAlternationImpl::Round3(Regexp** sub, int nsub, |
| 1146 | Regexp::ParseFlags flags, |
| 1147 | std::vector<Splice>* splices) { |
| 1148 | // Round 3: Merge runs of literals and/or character classes. |
| 1149 | int start = 0; |
| 1150 | Regexp* first = NULL; |
| 1151 | for (int i = 0; i <= nsub; i++) { |
| 1152 | // Invariant: sub[start:i] consists of regexps that all |
| 1153 | // are either literals (i.e. runes) or character classes. |
| 1154 | Regexp* first_i = NULL; |
| 1155 | if (i < nsub) { |
| 1156 | first_i = sub[i]; |
| 1157 | if (first != NULL && |
| 1158 | (first->op() == kRegexpLiteral || |
| 1159 | first->op() == kRegexpCharClass) && |
| 1160 | (first_i->op() == kRegexpLiteral || |
| 1161 | first_i->op() == kRegexpCharClass)) |
| 1162 | continue; |
| 1163 | } |
| 1164 | |
| 1165 | // Found end of a run of Literal/CharClass: |
| 1166 | // sub[start:i] all are either one or the other, |
| 1167 | // but sub[i] is not. |
| 1168 | if (i == start) { |
| 1169 | // Nothing to do - first iteration. |
| 1170 | } else if (i == start+1) { |
| 1171 | // Just one: don't bother factoring. |
| 1172 | } else { |
| 1173 | CharClassBuilder ccb; |
| 1174 | for (int j = start; j < i; j++) { |
| 1175 | Regexp* re = sub[j]; |
| 1176 | if (re->op() == kRegexpCharClass) { |
| 1177 | CharClass* cc = re->cc(); |
| 1178 | for (CharClass::iterator it = cc->begin(); it != cc->end(); ++it) |
| 1179 | ccb.AddRange(it->lo, it->hi); |
| 1180 | } else if (re->op() == kRegexpLiteral) { |
| 1181 | ccb.AddRangeFlags(re->rune(), re->rune(), re->parse_flags()); |
| 1182 | } else { |
| 1183 | LOG(DFATAL) << "RE2: unexpected op: " << re->op() << " " |
| 1184 | << re->ToString(); |
| 1185 | } |
| 1186 | re->Decref(); |
| 1187 | } |
| 1188 | Regexp* re = Regexp::NewCharClass(ccb.GetCharClass(), flags); |
| 1189 | splices->emplace_back(re, sub + start, i - start); |
| 1190 | } |
| 1191 | |
| 1192 | // Prepare for next iteration (if there is one). |
| 1193 | if (i < nsub) { |
| 1194 | start = i; |
| 1195 | first = first_i; |
| 1196 | } |
| 1197 | } |
| 1198 | } |
| 1199 | |
| 1200 | // Collapse the regexps on top of the stack, down to the |
| 1201 | // first marker, into a new op node (op == kRegexpAlternate |
nothing calls this directly
no test coverage detected