inline std::shared_ptr<_NFA<_TraitsT>>
__compile_nfa(const typename _TraitsT::char_type* __first,
const typename _TraitsT::char_type* __last,
- const _TraitsT& __traits,
+ const typename _TraitsT::locale_type& __loc,
regex_constants::syntax_option_type __flags);
_GLIBCXX_END_NAMESPACE_VERSION
* character sequence.
*/
basic_regex()
- : _M_flags(ECMAScript), _M_automaton(nullptr)
+ : _M_flags(ECMAScript), _M_loc(), _M_original_str(), _M_automaton(nullptr)
{ }
/**
*
* @param __rhs A @p regex object.
*/
- basic_regex(const basic_regex&& __rhs) noexcept
- : _M_flags(__rhs._M_flags), _M_traits(__rhs._M_traits),
- _M_automaton(std::move(__rhs._M_automaton))
- { }
+ basic_regex(basic_regex&& __rhs) noexcept = default;
/**
* @brief Constructs a basic regular expression from the string
basic_regex(_FwdIter __first, _FwdIter __last,
flag_type __f = ECMAScript)
: _M_flags(__f),
+ _M_loc(),
_M_original_str(__first, __last),
- _M_automaton(__detail::__compile_nfa(_M_original_str.c_str(),
- _M_original_str.c_str()
- + _M_original_str.size(),
- _M_traits,
- _M_flags))
+ _M_automaton(__detail::__compile_nfa<_Rx_traits>(
+ _M_original_str.c_str(),
+ _M_original_str.c_str() + _M_original_str.size(),
+ _M_loc,
+ _M_flags))
{ }
/**
_M_flags = __flags;
_M_original_str.assign(__s.begin(), __s.end());
auto __p = _M_original_str.c_str();
- _M_automaton = __detail::__compile_nfa(__p,
- __p + _M_original_str.size(),
- _M_traits, _M_flags);
+ _M_automaton = __detail::__compile_nfa<_Rx_traits>(
+ __p,
+ __p + _M_original_str.size(),
+ _M_loc,
+ _M_flags);
return *this;
}
locale_type
imbue(locale_type __loc)
{
- auto __ret = _M_traits.imbue(__loc);
- this->assign(_M_original_str, _M_flags);
- return __ret;
+ std::swap(__loc, _M_loc);
+ if (_M_automaton != nullptr)
+ this->assign(_M_original_str, _M_flags);
+ return __loc;
}
/**
*/
locale_type
getloc() const
- { return _M_traits.getloc(); }
+ { return _M_loc; }
// [7.8.6] swap
/**
swap(basic_regex& __rhs)
{
std::swap(_M_flags, __rhs._M_flags);
- std::swap(_M_traits, __rhs._M_traits);
+ std::swap(_M_loc, __rhs._M_loc);
+ std::swap(_M_original_str, __rhs._M_original_str);
std::swap(_M_automaton, __rhs._M_automaton);
}
{ _M_automaton->_M_dot(__ostr); }
#endif
- protected:
+ private:
typedef std::shared_ptr<__detail::_NFA<_Rx_traits>> _AutomatonPtr;
template<typename _Bp, typename _Ap, typename _Cp, typename _Rp,
friend class __detail::_Executor;
flag_type _M_flags;
- _Rx_traits _M_traits;
+ locale_type _M_loc;
basic_string<_Ch_type> _M_original_str;
_AutomatonPtr _M_automaton;
};
template<typename _TraitsT>
_Compiler<_TraitsT>::
_Compiler(_IterT __b, _IterT __e,
- const _TraitsT& __traits, _FlagT __flags)
+ const typename _TraitsT::locale_type& __loc, _FlagT __flags)
: _M_flags((__flags
& (regex_constants::ECMAScript
| regex_constants::basic
| regex_constants::awk))
? __flags
: __flags | regex_constants::ECMAScript),
- _M_traits(__traits),
- _M_ctype(std::use_facet<_CtypeT>(_M_traits.getloc())),
- _M_scanner(__b, __e, _M_flags, _M_traits.getloc()),
- _M_nfa(_M_flags)
+ _M_scanner(__b, __e, _M_flags, __loc),
+ _M_nfa(make_shared<_RegexT>(__loc, _M_flags)),
+ _M_traits(_M_nfa->_M_traits),
+ _M_ctype(std::use_facet<_CtypeT>(__loc))
{
- _StateSeqT __r(_M_nfa, _M_nfa._M_start());
- __r._M_append(_M_nfa._M_insert_subexpr_begin());
+ _StateSeqT __r(*_M_nfa, _M_nfa->_M_start());
+ __r._M_append(_M_nfa->_M_insert_subexpr_begin());
this->_M_disjunction();
if (!_M_match_token(_ScannerT::_S_token_eof))
__throw_regex_error(regex_constants::error_paren);
__r._M_append(_M_pop());
_GLIBCXX_DEBUG_ASSERT(_M_stack.empty());
- __r._M_append(_M_nfa._M_insert_subexpr_end());
- __r._M_append(_M_nfa._M_insert_accept());
- _M_nfa._M_eliminate_dummy();
+ __r._M_append(_M_nfa->_M_insert_subexpr_end());
+ __r._M_append(_M_nfa->_M_insert_accept());
+ _M_nfa->_M_eliminate_dummy();
}
template<typename _TraitsT>
_StateSeqT __alt1 = _M_pop();
this->_M_alternative();
_StateSeqT __alt2 = _M_pop();
- auto __end = _M_nfa._M_insert_dummy();
+ auto __end = _M_nfa->_M_insert_dummy();
__alt1._M_append(__end);
__alt2._M_append(__end);
// __alt2 is state._M_next, __alt1 is state._M_alt. The executor
// executes _M_alt before _M_next, as well as executing left
// alternative before right one.
- _M_stack.push(_StateSeqT(_M_nfa,
- _M_nfa._M_insert_alt(__alt2._M_start,
- __alt1._M_start, false),
+ _M_stack.push(_StateSeqT(*_M_nfa,
+ _M_nfa->_M_insert_alt(
+ __alt2._M_start, __alt1._M_start, false),
__end));
}
}
_M_stack.push(__re);
}
else
- _M_stack.push(_StateSeqT(_M_nfa, _M_nfa._M_insert_dummy()));
+ _M_stack.push(_StateSeqT(*_M_nfa, _M_nfa->_M_insert_dummy()));
}
template<typename _TraitsT>
_M_assertion()
{
if (_M_match_token(_ScannerT::_S_token_line_begin))
- _M_stack.push(_StateSeqT(_M_nfa, _M_nfa._M_insert_line_begin()));
+ _M_stack.push(_StateSeqT(*_M_nfa, _M_nfa->_M_insert_line_begin()));
else if (_M_match_token(_ScannerT::_S_token_line_end))
- _M_stack.push(_StateSeqT(_M_nfa, _M_nfa._M_insert_line_end()));
+ _M_stack.push(_StateSeqT(*_M_nfa, _M_nfa->_M_insert_line_end()));
else if (_M_match_token(_ScannerT::_S_token_word_bound))
// _M_value[0] == 'n' means it's negative, say "not word boundary".
- _M_stack.push(_StateSeqT(_M_nfa, _M_nfa.
+ _M_stack.push(_StateSeqT(*_M_nfa, _M_nfa->
_M_insert_word_bound(_M_value[0] == 'n')));
else if (_M_match_token(_ScannerT::_S_token_subexpr_lookahead_begin))
{
if (!_M_match_token(_ScannerT::_S_token_subexpr_end))
__throw_regex_error(regex_constants::error_paren);
auto __tmp = _M_pop();
- __tmp._M_append(_M_nfa._M_insert_accept());
+ __tmp._M_append(_M_nfa->_M_insert_accept());
_M_stack.push(
_StateSeqT(
- _M_nfa,
- _M_nfa._M_insert_lookahead(__tmp._M_start, __neg)));
+ *_M_nfa,
+ _M_nfa->_M_insert_lookahead(__tmp._M_start, __neg)));
}
else
return false;
{
__init();
auto __e = _M_pop();
- _StateSeqT __r(_M_nfa, _M_nfa._M_insert_repeat(_S_invalid_state_id,
- __e._M_start, __neg));
+ _StateSeqT __r(*_M_nfa,
+ _M_nfa->_M_insert_repeat(_S_invalid_state_id,
+ __e._M_start, __neg));
__e._M_append(__r);
_M_stack.push(__r);
}
{
__init();
auto __e = _M_pop();
- __e._M_append(_M_nfa._M_insert_repeat(_S_invalid_state_id,
- __e._M_start, __neg));
+ __e._M_append(_M_nfa->_M_insert_repeat(_S_invalid_state_id,
+ __e._M_start, __neg));
_M_stack.push(__e);
}
else if (_M_match_token(_ScannerT::_S_token_opt))
{
__init();
auto __e = _M_pop();
- auto __end = _M_nfa._M_insert_dummy();
- _StateSeqT __r(_M_nfa, _M_nfa._M_insert_repeat(_S_invalid_state_id,
- __e._M_start, __neg));
+ auto __end = _M_nfa->_M_insert_dummy();
+ _StateSeqT __r(*_M_nfa,
+ _M_nfa->_M_insert_repeat(_S_invalid_state_id,
+ __e._M_start, __neg));
__e._M_append(__end);
__r._M_append(__end);
_M_stack.push(__r);
if (!_M_match_token(_ScannerT::_S_token_dup_count))
__throw_regex_error(regex_constants::error_badbrace);
_StateSeqT __r(_M_pop());
- _StateSeqT __e(_M_nfa, _M_nfa._M_insert_dummy());
+ _StateSeqT __e(*_M_nfa, _M_nfa->_M_insert_dummy());
long __min_rep = _M_cur_int_value(10);
bool __infi = false;
long __n;
if (__infi)
{
auto __tmp = __r._M_clone();
- _StateSeqT __s(_M_nfa,
- _M_nfa._M_insert_repeat(_S_invalid_state_id,
- __tmp._M_start, __neg));
+ _StateSeqT __s(*_M_nfa,
+ _M_nfa->_M_insert_repeat(_S_invalid_state_id,
+ __tmp._M_start, __neg));
__tmp._M_append(__s);
__e._M_append(__s);
}
{
if (__n < 0)
__throw_regex_error(regex_constants::error_badbrace);
- auto __end = _M_nfa._M_insert_dummy();
+ auto __end = _M_nfa->_M_insert_dummy();
// _M_alt is the "match more" branch, and _M_next is the
// "match less" one. Switch _M_alt and _M_next of all created
// nodes. This is a hack but IMO works well.
for (long __i = 0; __i < __n; ++__i)
{
auto __tmp = __r._M_clone();
- auto __alt = _M_nfa._M_insert_repeat(__tmp._M_start,
- __end, __neg);
+ auto __alt = _M_nfa->_M_insert_repeat(__tmp._M_start,
+ __end, __neg);
__stack.push(__alt);
- __e._M_append(_StateSeqT(_M_nfa, __alt, __tmp._M_end));
+ __e._M_append(_StateSeqT(*_M_nfa, __alt, __tmp._M_end));
}
__e._M_append(__end);
while (!__stack.empty())
{
- auto& __tmp = _M_nfa[__stack.top()];
+ auto& __tmp = (*_M_nfa)[__stack.top()];
__stack.pop();
swap(__tmp._M_next, __tmp._M_alt);
}
else if (_M_try_char())
__INSERT_REGEX_MATCHER(_M_insert_char_matcher);
else if (_M_match_token(_ScannerT::_S_token_backref))
- _M_stack.push(_StateSeqT(_M_nfa, _M_nfa.
+ _M_stack.push(_StateSeqT(*_M_nfa, _M_nfa->
_M_insert_backref(_M_cur_int_value(10))));
else if (_M_match_token(_ScannerT::_S_token_quoted_class))
__INSERT_REGEX_MATCHER(_M_insert_character_class_matcher);
else if (_M_match_token(_ScannerT::_S_token_subexpr_no_group_begin))
{
- _StateSeqT __r(_M_nfa, _M_nfa._M_insert_dummy());
+ _StateSeqT __r(*_M_nfa, _M_nfa->_M_insert_dummy());
this->_M_disjunction();
if (!_M_match_token(_ScannerT::_S_token_subexpr_end))
__throw_regex_error(regex_constants::error_paren);
}
else if (_M_match_token(_ScannerT::_S_token_subexpr_begin))
{
- _StateSeqT __r(_M_nfa, _M_nfa._M_insert_subexpr_begin());
+ _StateSeqT __r(*_M_nfa, _M_nfa->_M_insert_subexpr_begin());
this->_M_disjunction();
if (!_M_match_token(_ScannerT::_S_token_subexpr_end))
__throw_regex_error(regex_constants::error_paren);
__r._M_append(_M_pop());
- __r._M_append(_M_nfa._M_insert_subexpr_end());
+ __r._M_append(_M_nfa->_M_insert_subexpr_end());
_M_stack.push(__r);
}
else if (!_M_bracket_expression())
_Compiler<_TraitsT>::
_M_insert_any_matcher_ecma()
{
- _M_stack.push(_StateSeqT(_M_nfa,
- _M_nfa._M_insert_matcher
+ _M_stack.push(_StateSeqT(*_M_nfa,
+ _M_nfa->_M_insert_matcher
(_AnyMatcher<_TraitsT, true, __icase, __collate>
(_M_traits))));
}
_Compiler<_TraitsT>::
_M_insert_any_matcher_posix()
{
- _M_stack.push(_StateSeqT(_M_nfa,
- _M_nfa._M_insert_matcher
+ _M_stack.push(_StateSeqT(*_M_nfa,
+ _M_nfa->_M_insert_matcher
(_AnyMatcher<_TraitsT, false, __icase, __collate>
(_M_traits))));
}
_Compiler<_TraitsT>::
_M_insert_char_matcher()
{
- _M_stack.push(_StateSeqT(_M_nfa,
- _M_nfa._M_insert_matcher
+ _M_stack.push(_StateSeqT(*_M_nfa,
+ _M_nfa->_M_insert_matcher
(_CharMatcher<_TraitsT, __icase, __collate>
(_M_value[0], _M_traits))));
}
(_M_ctype.is(_CtypeT::upper, _M_value[0]), _M_traits);
__matcher._M_add_character_class(_M_value, false);
__matcher._M_ready();
- _M_stack.push(_StateSeqT(_M_nfa,
- _M_nfa._M_insert_matcher(std::move(__matcher))));
+ _M_stack.push(_StateSeqT(*_M_nfa,
+ _M_nfa->_M_insert_matcher(std::move(__matcher))));
}
template<typename _TraitsT>
while (!_M_match_token(_ScannerT::_S_token_bracket_end))
_M_expression_term(__matcher);
__matcher._M_ready();
- _M_stack.push(_StateSeqT(_M_nfa,
- _M_nfa._M_insert_matcher(std::move(__matcher))));
+ _M_stack.push(_StateSeqT(
+ *_M_nfa,
+ _M_nfa->_M_insert_matcher(std::move(__matcher))));
}
template<typename _TraitsT>
--- /dev/null
+// { dg-options "-std=gnu++11" }
+
+//
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <regex>
+#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
+
+// libstdc++/63199
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ std::setlocale(LC_ALL, "");
+
+ std::wstring current_token(L"II.");
+
+ std::vector<std::wregex> regex_vector;
+
+ for (int i = 0; i < 4; ++i)
+ {
+ std::regex_constants::syntax_option_type flag;
+ flag = std::regex_constants::ECMAScript | std::regex_constants::icase;
+
+ std::wregex reg;
+ reg.imbue(std::locale(""));
+ reg.assign(L"^(M*(?:CM|DC{1,3}|D|CD|C{1,3}){0,1}(?:XC|LX{1,3}|L|XL|X{1,3}){0,1}(?:IX|VI{0,3}|IV|I{1,3}){0,1}\\.)$", flag);
+
+ regex_vector.emplace_back(reg);
+ }
+
+ for (auto cit = regex_vector.cbegin(); cit != regex_vector.cend(); ++cit)
+ {
+ std::wstring::const_iterator it1 = current_token.begin();
+ std::wstring::const_iterator it2 = current_token.end();
+ std::wsmatch current_token_match;
+
+ regex_match_debug(it1, it2, current_token_match, *cit);
+ VERIFY(current_token_match[0] == current_token);
+ VERIFY(current_token_match[1] == current_token);
+ }
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}