Parses the regular expression given by s, returning the corresponding Regexp tree. The caller must Decref the return value when done with it. Returns NULL on error.
| 2198 | // The caller must Decref the return value when done with it. |
| 2199 | // Returns NULL on error. |
| 2200 | Regexp* Regexp::Parse(const StringPiece& s, ParseFlags global_flags, |
| 2201 | RegexpStatus* status) { |
| 2202 | // Make status non-NULL (easier on everyone else). |
| 2203 | RegexpStatus xstatus; |
| 2204 | if (status == NULL) |
| 2205 | status = &xstatus; |
| 2206 | |
| 2207 | ParseState ps(global_flags, s, status); |
| 2208 | StringPiece t = s; |
| 2209 | |
| 2210 | // Convert regexp to UTF-8 (easier on the rest of the parser). |
| 2211 | if (global_flags & Latin1) { |
| 2212 | std::string* tmp = new std::string; |
| 2213 | ConvertLatin1ToUTF8(t, tmp); |
| 2214 | status->set_tmp(tmp); |
| 2215 | t = *tmp; |
| 2216 | } |
| 2217 | |
| 2218 | if (global_flags & Literal) { |
| 2219 | // Special parse loop for literal string. |
| 2220 | while (!t.empty()) { |
| 2221 | Rune r; |
| 2222 | if (StringPieceToRune(&r, &t, status) < 0) |
| 2223 | return NULL; |
| 2224 | if (!ps.PushLiteral(r)) |
| 2225 | return NULL; |
| 2226 | } |
| 2227 | return ps.DoFinish(); |
| 2228 | } |
| 2229 | |
| 2230 | StringPiece lastunary = StringPiece(); |
| 2231 | while (!t.empty()) { |
| 2232 | StringPiece isunary = StringPiece(); |
| 2233 | switch (t[0]) { |
| 2234 | default: { |
| 2235 | Rune r; |
| 2236 | if (StringPieceToRune(&r, &t, status) < 0) |
| 2237 | return NULL; |
| 2238 | if (!ps.PushLiteral(r)) |
| 2239 | return NULL; |
| 2240 | break; |
| 2241 | } |
| 2242 | |
| 2243 | case '(': |
| 2244 | // "(?" introduces Perl escape. |
| 2245 | if ((ps.flags() & PerlX) && (t.size() >= 2 && t[1] == '?')) { |
| 2246 | // Flag changes and non-capturing groups. |
| 2247 | if (!ps.ParsePerlFlags(&t)) |
| 2248 | return NULL; |
| 2249 | break; |
| 2250 | } |
| 2251 | if (ps.flags() & NeverCapture) { |
| 2252 | if (!ps.DoLeftParenNoCapture()) |
| 2253 | return NULL; |
| 2254 | } else { |
| 2255 | if (!ps.DoLeftParen(StringPiece())) |
| 2256 | return NULL; |
| 2257 | } |