Parses a possibly-negated character class expression like [^abx-z[:digit:]]. Sets *s to span the remainder of the string. Sets *out_re to the regexp for the class.
| 1905 | // Sets *s to span the remainder of the string. |
| 1906 | // Sets *out_re to the regexp for the class. |
| 1907 | bool Regexp::ParseState::ParseCharClass(StringPiece* s, |
| 1908 | Regexp** out_re, |
| 1909 | RegexpStatus* status) { |
| 1910 | StringPiece whole_class = *s; |
| 1911 | if (s->empty() || (*s)[0] != '[') { |
| 1912 | // Caller checked this. |
| 1913 | status->set_code(kRegexpInternalError); |
| 1914 | status->set_error_arg(StringPiece()); |
| 1915 | return false; |
| 1916 | } |
| 1917 | bool negated = false; |
| 1918 | Regexp* re = new Regexp(kRegexpCharClass, flags_ & ~FoldCase); |
| 1919 | re->ccb_ = new CharClassBuilder; |
| 1920 | s->remove_prefix(1); // '[' |
| 1921 | if (!s->empty() && (*s)[0] == '^') { |
| 1922 | s->remove_prefix(1); // '^' |
| 1923 | negated = true; |
| 1924 | if (!(flags_ & ClassNL) || (flags_ & NeverNL)) { |
| 1925 | // If NL can't match implicitly, then pretend |
| 1926 | // negated classes include a leading \n. |
| 1927 | re->ccb_->AddRange('\n', '\n'); |
| 1928 | } |
| 1929 | } |
| 1930 | bool first = true; // ] is okay as first char in class |
| 1931 | while (!s->empty() && ((*s)[0] != ']' || first)) { |
| 1932 | // - is only okay unescaped as first or last in class. |
| 1933 | // Except that Perl allows - anywhere. |
| 1934 | if ((*s)[0] == '-' && !first && !(flags_&PerlX) && |
| 1935 | (s->size() == 1 || (*s)[1] != ']')) { |
| 1936 | StringPiece t = *s; |
| 1937 | t.remove_prefix(1); // '-' |
| 1938 | Rune r; |
| 1939 | int n = StringPieceToRune(&r, &t, status); |
| 1940 | if (n < 0) { |
| 1941 | re->Decref(); |
| 1942 | return false; |
| 1943 | } |
| 1944 | status->set_code(kRegexpBadCharRange); |
| 1945 | status->set_error_arg(StringPiece(s->data(), 1+n)); |
| 1946 | re->Decref(); |
| 1947 | return false; |
| 1948 | } |
| 1949 | first = false; |
| 1950 | |
| 1951 | // Look for [:alnum:] etc. |
| 1952 | if (s->size() > 2 && (*s)[0] == '[' && (*s)[1] == ':') { |
| 1953 | switch (ParseCCName(s, flags_, re->ccb_, status)) { |
| 1954 | case kParseOk: |
| 1955 | continue; |
| 1956 | case kParseError: |
| 1957 | re->Decref(); |
| 1958 | return false; |
| 1959 | case kParseNothing: |
| 1960 | break; |
| 1961 | } |
| 1962 | } |
| 1963 | |
| 1964 | // Look for Unicode character group like \p{Han} |
no test coverage detected