lookahead for ecma

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@109548 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Howard Hinnant 2010-07-27 22:20:32 +00:00
parent 856846b66f
commit e9de5ff443
2 changed files with 163 additions and 77 deletions

View File

@ -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>
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>
void
_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>

View File

@ -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");
}
}