//===-------------------------- regex.cpp ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "regex" #include "algorithm" #include "iterator" _LIBCPP_BEGIN_NAMESPACE_STD static const char* make_error_type_string(regex_constants::error_type ecode) { switch (ecode) { case regex_constants::error_collate: return "The expression contained an invalid collating element name."; case regex_constants::error_ctype: return "The expression contained an invalid character class name."; case regex_constants::error_escape: return "The expression contained an invalid escaped character, or a " "trailing escape."; case regex_constants::error_backref: return "The expression contained an invalid back reference."; case regex_constants::error_brack: return "The expression contained mismatched [ and ]."; case regex_constants::error_paren: return "The expression contained mismatched ( and )."; case regex_constants::error_brace: return "The expression contained mismatched { and }."; case regex_constants::error_badbrace: return "The expression contained an invalid range in a {} expression."; case regex_constants::error_range: return "The expression contained an invalid character range, " "such as [b-a] in most encodings."; case regex_constants::error_space: return "There was insufficient memory to convert the expression into " "a finite state machine."; case regex_constants::error_badrepeat: return "One of *?+{ was not preceded by a valid regular expression."; case regex_constants::error_complexity: return "The complexity of an attempted match against a regular " "expression exceeded a pre-set level."; case regex_constants::error_stack: return "There was insufficient memory to determine whether the regular " "expression could match the specified character sequence."; case regex_constants::__re_err_grammar: return "An invalid regex grammar has been requested."; case regex_constants::__re_err_empty: return "An empty regex is not allowed in the POSIX grammar."; default: break; } return "Unknown error type"; } regex_error::regex_error(regex_constants::error_type ecode) : runtime_error(make_error_type_string(ecode)), __code_(ecode) {} regex_error::~regex_error() throw() {} namespace { #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif struct collationnames { const char* elem_; char char_; }; #if defined(__clang__) #pragma clang diagnostic pop #endif const collationnames collatenames[] = { {"A", 0x41}, {"B", 0x42}, {"C", 0x43}, {"D", 0x44}, {"E", 0x45}, {"F", 0x46}, {"G", 0x47}, {"H", 0x48}, {"I", 0x49}, {"J", 0x4a}, {"K", 0x4b}, {"L", 0x4c}, {"M", 0x4d}, {"N", 0x4e}, {"NUL", 0x00}, {"O", 0x4f}, {"P", 0x50}, {"Q", 0x51}, {"R", 0x52}, {"S", 0x53}, {"T", 0x54}, {"U", 0x55}, {"V", 0x56}, {"W", 0x57}, {"X", 0x58}, {"Y", 0x59}, {"Z", 0x5a}, {"a", 0x61}, {"alert", 0x07}, {"ampersand", 0x26}, {"apostrophe", 0x27}, {"asterisk", 0x2a}, {"b", 0x62}, {"backslash", 0x5c}, {"backspace", 0x08}, {"c", 0x63}, {"carriage-return", 0x0d}, {"circumflex", 0x5e}, {"circumflex-accent", 0x5e}, {"colon", 0x3a}, {"comma", 0x2c}, {"commercial-at", 0x40}, {"d", 0x64}, {"dollar-sign", 0x24}, {"e", 0x65}, {"eight", 0x38}, {"equals-sign", 0x3d}, {"exclamation-mark", 0x21}, {"f", 0x66}, {"five", 0x35}, {"form-feed", 0x0c}, {"four", 0x34}, {"full-stop", 0x2e}, {"g", 0x67}, {"grave-accent", 0x60}, {"greater-than-sign", 0x3e}, {"h", 0x68}, {"hyphen", 0x2d}, {"hyphen-minus", 0x2d}, {"i", 0x69}, {"j", 0x6a}, {"k", 0x6b}, {"l", 0x6c}, {"left-brace", 0x7b}, {"left-curly-bracket", 0x7b}, {"left-parenthesis", 0x28}, {"left-square-bracket", 0x5b}, {"less-than-sign", 0x3c}, {"low-line", 0x5f}, {"m", 0x6d}, {"n", 0x6e}, {"newline", 0x0a}, {"nine", 0x39}, {"number-sign", 0x23}, {"o", 0x6f}, {"one", 0x31}, {"p", 0x70}, {"percent-sign", 0x25}, {"period", 0x2e}, {"plus-sign", 0x2b}, {"q", 0x71}, {"question-mark", 0x3f}, {"quotation-mark", 0x22}, {"r", 0x72}, {"reverse-solidus", 0x5c}, {"right-brace", 0x7d}, {"right-curly-bracket", 0x7d}, {"right-parenthesis", 0x29}, {"right-square-bracket", 0x5d}, {"s", 0x73}, {"semicolon", 0x3b}, {"seven", 0x37}, {"six", 0x36}, {"slash", 0x2f}, {"solidus", 0x2f}, {"space", 0x20}, {"t", 0x74}, {"tab", 0x09}, {"three", 0x33}, {"tilde", 0x7e}, {"two", 0x32}, {"u", 0x75}, {"underscore", 0x5f}, {"v", 0x76}, {"vertical-line", 0x7c}, {"vertical-tab", 0x0b}, {"w", 0x77}, {"x", 0x78}, {"y", 0x79}, {"z", 0x7a}, {"zero", 0x30} }; #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif struct classnames { const char* elem_; regex_traits<char>::char_class_type mask_; }; #if defined(__clang__) #pragma clang diagnostic pop #endif const classnames ClassNames[] = { {"alnum", ctype_base::alnum}, {"alpha", ctype_base::alpha}, {"blank", ctype_base::blank}, {"cntrl", ctype_base::cntrl}, {"d", ctype_base::digit}, {"digit", ctype_base::digit}, {"graph", ctype_base::graph}, {"lower", ctype_base::lower}, {"print", ctype_base::print}, {"punct", ctype_base::punct}, {"s", ctype_base::space}, {"space", ctype_base::space}, {"upper", ctype_base::upper}, {"w", regex_traits<char>::__regex_word}, {"xdigit", ctype_base::xdigit} }; struct use_strcmp { bool operator()(const collationnames& x, const char* y) {return strcmp(x.elem_, y) < 0;} bool operator()(const classnames& x, const char* y) {return strcmp(x.elem_, y) < 0;} }; } string __get_collation_name(const char* s) { const collationnames* i = _VSTD::lower_bound(begin(collatenames), end(collatenames), s, use_strcmp()); string r; if (i != end(collatenames) && strcmp(s, i->elem_) == 0) r = char(i->char_); return r; } regex_traits<char>::char_class_type __get_classname(const char* s, bool __icase) { const classnames* i = _VSTD::lower_bound(begin(ClassNames), end(ClassNames), s, use_strcmp()); regex_traits<char>::char_class_type r = 0; if (i != end(ClassNames) && strcmp(s, i->elem_) == 0) { r = i->mask_; if (r == regex_traits<char>::__regex_word) r |= ctype_base::alnum | ctype_base::upper | ctype_base::lower; else if (__icase) { if (r & (ctype_base::lower | ctype_base::upper)) r |= ctype_base::alpha; } } return r; } template <> void __match_any_but_newline<char>::__exec(__state& __s) const { if (__s.__current_ != __s.__last_) { switch (*__s.__current_) { case '\r': case '\n': __s.__do_ = __state::__reject; __s.__node_ = nullptr; break; default: __s.__do_ = __state::__accept_and_consume; ++__s.__current_; __s.__node_ = this->first(); break; } } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } template <> void __match_any_but_newline<wchar_t>::__exec(__state& __s) const { if (__s.__current_ != __s.__last_) { switch (*__s.__current_) { case '\r': case '\n': case 0x2028: case 0x2029: __s.__do_ = __state::__reject; __s.__node_ = nullptr; break; default: __s.__do_ = __state::__accept_and_consume; ++__s.__current_; __s.__node_ = this->first(); break; } } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } _LIBCPP_END_NAMESPACE_STD