diff options
-rw-r--r-- | libcxx/include/regex | 178 | ||||
-rw-r--r-- | libcxx/test/re/re.alg/re.alg.search/ecma.pass.cpp | 62 |
2 files changed, 163 insertions, 77 deletions
diff --git a/libcxx/include/regex b/libcxx/include/regex index 4d132a129fb..14a0e4bcc0d 100644 --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -2416,57 +2416,7 @@ __exit: } } -// __lookahead - -template <class _CharT, class _Traits> -class __lookahead - : public __owns_one_state<_CharT> -{ - typedef __owns_one_state<_CharT> base; - - _Traits __traits_; - bool __invert_; - - __lookahead(const __lookahead&); - __lookahead& operator=(const __lookahead&); -public: - typedef _STD::__state<_CharT> __state; - - __lookahead(const _Traits& __traits, bool __invert, __node<_CharT>* __s) - : base(__s), __traits_(__traits), __invert_(__invert) {} - - virtual void __exec(__state&) const; - - virtual string speak() const - { - ostringstream os; - if (__invert_) - os << "lookahead"; - else - os << "not lookahead"; - return os.str(); - } -}; - -template <class _CharT, class _Traits> -void -__lookahead<_CharT, _Traits>::__exec(__state& __s) const -{ -// match_results<const _CharT*> __m; -// __m.__init(1 + mark_count(), __s.__current_, __s.__last_); -// bool __matched = __exp_.__match_at_start_ecma(__s.__current_, __s.__last_, -// __m, __s.__flags_); -// if (__matched != __invert_) -// { -// __s.__do_ = __state::__accept_but_not_consume; -// __s.__node_ = this->first(); -// } -// else -// { -// __s.__do_ = __state::__reject; -// __s.__node_ = nullptr; -// } -} +template <class, class> class __lookahead; template <class _CharT, class _Traits = regex_traits<_CharT> > class basic_regex @@ -2516,10 +2466,8 @@ public: : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0), __left_anchor_(false) {__parse(__p, __p + __len);} - basic_regex(const basic_regex&); -#ifdef _LIBCPP_MOVE - basic_regex(basic_regex&&); -#endif +// basic_regex(const basic_regex&) = default; +// basic_regex(basic_regex&&) = default; template <class _ST, class _SA> explicit basic_regex(const basic_string<value_type, _ST, _SA>& __p, flag_type __f = regex_constants::ECMAScript) @@ -2540,10 +2488,8 @@ public: ~basic_regex(); - basic_regex& operator=(const basic_regex&); -#ifdef _LIBCPP_MOVE - basic_regex& operator=(basic_regex&&); -#endif +// basic_regex& operator=(const basic_regex&) = default; +// basic_regex& operator=(basic_regex&&) = default; basic_regex& operator=(const value_type* __p); basic_regex& operator=(initializer_list<value_type> __il); template <class _ST, class _SA> @@ -2580,7 +2526,8 @@ private: unsigned __loop_count() const {return __loop_count_;} template <class _ForwardIterator> - void __parse(_ForwardIterator __first, _ForwardIterator __last); + _ForwardIterator + __parse(_ForwardIterator __first, _ForwardIterator __last); template <class _ForwardIterator> _ForwardIterator __parse_basic_reg_exp(_ForwardIterator __first, _ForwardIterator __last); @@ -2732,7 +2679,7 @@ private: void __push_end_marked_subexpression(unsigned); void __push_empty(); void __push_word_boundary(bool); - void __push_lookahead(bool) {} + void __push_lookahead(const basic_regex&, bool); template <class _Allocator> bool @@ -2805,6 +2752,8 @@ private: match_results<typename basic_string<_C, _ST, _SA>::const_iterator, _A>&, const basic_regex<_C, _T>& __e, regex_constants::match_flag_type __flags); + + template <class, class> friend class __lookahead; }; template <class _CharT, class _Traits> @@ -2812,9 +2761,61 @@ basic_regex<_CharT, _Traits>::~basic_regex() { } +// __lookahead + +template <class _CharT, class _Traits> +class __lookahead + : public __owns_one_state<_CharT> +{ + typedef __owns_one_state<_CharT> base; + + basic_regex<_CharT, _Traits> __exp_; + bool __invert_; + + __lookahead(const __lookahead&); + __lookahead& operator=(const __lookahead&); +public: + typedef _STD::__state<_CharT> __state; + + __lookahead(const basic_regex<_CharT, _Traits>& __exp, bool __invert, __node<_CharT>* __s) + : base(__s), __exp_(__exp), __invert_(__invert) {} + + virtual void __exec(__state&) const; + + virtual string speak() const + { + ostringstream os; + if (__invert_) + os << "not lookahead"; + else + os << "lookahead"; + return os.str(); + } +}; + template <class _CharT, class _Traits> -template <class _ForwardIterator> void +__lookahead<_CharT, _Traits>::__exec(__state& __s) const +{ + match_results<const _CharT*> __m; + __m.__init(1 + __exp_.mark_count(), __s.__current_, __s.__last_); + bool __matched = __exp_.__match_at_start_ecma(__s.__current_, __s.__last_, + __m, __s.__flags_); + if (__matched != __invert_) + { + __s.__do_ = __state::__accept_but_not_consume; + __s.__node_ = this->first(); + } + else + { + __s.__do_ = __state::__reject; + __s.__node_ = nullptr; + } +} + +template <class _CharT, class _Traits> +template <class _ForwardIterator> +_ForwardIterator basic_regex<_CharT, _Traits>::__parse(_ForwardIterator __first, _ForwardIterator __last) { @@ -2827,25 +2828,26 @@ basic_regex<_CharT, _Traits>::__parse(_ForwardIterator __first, switch (__flags_ & 0x1F0) { case ECMAScript: - __parse_ecma_exp(__first, __last); + __first = __parse_ecma_exp(__first, __last); break; case basic: - __parse_basic_reg_exp(__first, __last); + __first = __parse_basic_reg_exp(__first, __last); break; case extended: - __parse_extended_reg_exp(__first, __last); + __first = __parse_extended_reg_exp(__first, __last); break; case awk: break; case grep: - __parse_grep(__first, __last); + __first = __parse_grep(__first, __last); break; case egrep: - __parse_egrep(__first, __last); + __first = __parse_egrep(__first, __last); break; default: throw regex_error(regex_constants::__re_err_grammar); } + return __first; } template <class _CharT, class _Traits> @@ -3816,18 +3818,28 @@ basic_regex<_CharT, _Traits>::__parse_assertion(_ForwardIterator __first, switch (*__temp) { case '=': - __push_lookahead(false); - __temp = __parse_ecma_exp(++__temp, __last); - if (__temp == __last || *__temp != ')') - throw regex_error(regex_constants::error_paren); - __first = ++__temp; + { + basic_regex __exp; + __exp.__flags_ = __flags_; + __temp = __exp.__parse(++__temp, __last); + __exp.__push_l_anchor(); + __push_lookahead(_STD::move(__exp), false); + if (__temp == __last || *__temp != ')') + throw regex_error(regex_constants::error_paren); + __first = ++__temp; + } break; case '!': - __push_lookahead(true); - __temp = __parse_ecma_exp(++__temp, __last); - if (__temp == __last || *__temp != ')') - throw regex_error(regex_constants::error_paren); - __first = ++__temp; + { + basic_regex __exp; + __exp.__flags_ = __flags_; + __temp = __exp.__parse(++__temp, __last); + __exp.__push_l_anchor(); + __push_lookahead(_STD::move(__exp), true); + if (__temp == __last || *__temp != ')') + throw regex_error(regex_constants::error_paren); + __first = ++__temp; + } break; } } @@ -4321,6 +4333,16 @@ basic_regex<_CharT, _Traits>::__start_matching_list(bool __negate) return __r; } +template <class _CharT, class _Traits> +void +basic_regex<_CharT, _Traits>::__push_lookahead(const basic_regex& __exp, + bool __invert) +{ + __end_->first() = new __lookahead<_CharT, _Traits>(__exp, __invert, + __end_->first()); + __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); +} + typedef basic_regex<char> regex; typedef basic_regex<wchar_t> wregex; @@ -4854,6 +4876,8 @@ private: bool regex_match(_B, _B, match_results<_B, _A>&, const basic_regex<_C, _T>&, regex_constants::match_flag_type); + + template <class, class> friend class __lookahead; }; template <class _BidirectionalIterator, class _Allocator> diff --git a/libcxx/test/re/re.alg/re.alg.search/ecma.pass.cpp b/libcxx/test/re/re.alg/re.alg.search/ecma.pass.cpp index 03025699b43..ed8f54a9294 100644 --- a/libcxx/test/re/re.alg/re.alg.search/ecma.pass.cpp +++ b/libcxx/test/re/re.alg/re.alg.search/ecma.pass.cpp @@ -16,6 +16,8 @@ // const basic_regex<charT, traits>& e, // regex_constants::match_flag_type flags = regex_constants::match_default); +#include <iostream> + #include <regex> #include <cassert> @@ -756,6 +758,36 @@ int main() assert(m.position(0) == 0); assert(m.str(0) == s); } + { + std::cmatch m; + const char s[] = "Jeff Jeffs "; + assert(std::regex_search(s, m, std::regex("Jeff(?=s\\b)"))); + assert(m.size() == 1); + assert(m.prefix().matched); + assert(m.prefix().first == s); + assert(m.prefix().second == m[0].first); + assert(m.suffix().matched); + assert(m.suffix().first == m[0].second); + assert(m.suffix().second == s + std::char_traits<char>::length(s)); + assert(m.length(0) == 4); + assert(m.position(0) == 5); + assert(m.str(0) == "Jeff"); + } + { + std::cmatch m; + const char s[] = "Jeffs Jeff"; + assert(std::regex_search(s, m, std::regex("Jeff(?!s\\b)"))); + assert(m.size() == 1); + assert(m.prefix().matched); + assert(m.prefix().first == s); + assert(m.prefix().second == m[0].first); + assert(!m.suffix().matched); + assert(m.suffix().first == m[0].second); + assert(m.suffix().second == s + std::char_traits<char>::length(s)); + assert(m.length(0) == 4); + assert(m.position(0) == 6); + assert(m.str(0) == "Jeff"); + } { std::wcmatch m; @@ -1490,4 +1522,34 @@ int main() assert(m.position(0) == 0); assert(m.str(0) == s); } + { + std::wcmatch m; + const wchar_t s[] = L"Jeff Jeffs "; + assert(std::regex_search(s, m, std::wregex(L"Jeff(?=s\\b)"))); + assert(m.size() == 1); + assert(m.prefix().matched); + assert(m.prefix().first == s); + assert(m.prefix().second == m[0].first); + assert(m.suffix().matched); + assert(m.suffix().first == m[0].second); + assert(m.suffix().second == s + std::char_traits<wchar_t>::length(s)); + assert(m.length(0) == 4); + assert(m.position(0) == 5); + assert(m.str(0) == L"Jeff"); + } + { + std::wcmatch m; + const wchar_t s[] = L"Jeffs Jeff"; + assert(std::regex_search(s, m, std::wregex(L"Jeff(?!s\\b)"))); + assert(m.size() == 1); + assert(m.prefix().matched); + assert(m.prefix().first == s); + assert(m.prefix().second == m[0].first); + assert(!m.suffix().matched); + assert(m.suffix().first == m[0].second); + assert(m.suffix().second == s + std::char_traits<wchar_t>::length(s)); + assert(m.length(0) == 4); + assert(m.position(0) == 6); + assert(m.str(0) == L"Jeff"); + } } |