📄 perl_matcher_non_recursive.hpp
字号:
const re_repeat* rep = static_cast<const re_repeat*>(pstate);
// find out which of these two alternatives we need to take:
bool take_first, take_second;
if(position == last)
{
take_first = rep->can_be_null & mask_take;
take_second = rep->can_be_null & mask_skip;
}
else
{
take_first = can_start(*position, rep->_map, (unsigned char)mask_take);
take_second = can_start(*position, rep->_map, (unsigned char)mask_skip);
}
if(take_first || (next_count->get_id() != rep->id))
{
// we're moving to a different repeat from the last
// one, so set up a counter object:
push_repeater_count(rep->id, &next_count);
}
//
// If we've had at least one repeat already, and the last one
// matched the NULL string then set the repeat count to
// maximum:
//
next_count->check_null_repeat(position, rep->max);
if(next_count->get_count() < rep->min)
{
// we must take the repeat:
if(take_first)
{
// increase the counter:
++(*next_count);
pstate = rep->next.p;
return true;
}
return false;
}
bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
if(greedy)
{
// try and take the repeat if we can:
if((next_count->get_count() < rep->max) && take_first)
{
if(take_second)
{
// store position in case we fail:
push_alt(rep->alt.p);
}
// increase the counter:
++(*next_count);
pstate = rep->next.p;
return true;
}
else if(take_second)
{
pstate = rep->alt.p;
return true;
}
return false; // can't take anything, fail...
}
else // non-greedy
{
// try and skip the repeat if we can:
if(take_second)
{
if((next_count->get_count() < rep->max) && take_first)
{
// store position in case we fail:
push_non_greedy_repeat(rep->next.p);
}
pstate = rep->alt.p;
return true;
}
if((next_count->get_count() < rep->max) && take_first)
{
// increase the counter:
++(*next_count);
pstate = rep->next.p;
return true;
}
}
return false;
#ifdef __BORLANDC__
#pragma option pop
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
{
unsigned count = 0;
const re_repeat* rep = static_cast<const re_repeat*>(pstate);
re_syntax_base* psingle = rep->next.p;
// match compulsary repeats first:
while(count < rep->min)
{
pstate = psingle;
if(!match_wild())
return false;
++count;
}
bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
if(greedy)
{
// repeat for as long as we can:
while(count < rep->max)
{
pstate = psingle;
if(!match_wild())
break;
++count;
}
// remember where we got to if this is a leading repeat:
if((rep->leading) && (count < rep->max))
restart = position;
// push backtrack info if available:
if(count - rep->min)
push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
// jump to next state:
pstate = rep->alt.p;
return true;
}
else
{
// non-greedy, push state and return true if we can skip:
if(count < rep->max)
push_single_repeat(count, rep, position, saved_state_rep_slow_dot);
pstate = rep->alt.p;
return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
}
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
{
if(m_match_flags & match_not_dot_null)
return match_dot_repeat_slow();
if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
return match_dot_repeat_slow();
const re_repeat* rep = static_cast<const re_repeat*>(pstate);
bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
unsigned count = static_cast<unsigned>((std::min)(static_cast<unsigned>(::boost::re_detail::distance(position, last)), static_cast<unsigned>(greedy ? rep->max : rep->min)));
if(rep->min > count)
{
position = last;
return false; // not enough text left to match
}
std::advance(position, count);
if(greedy)
{
if((rep->leading) && (count < rep->max))
restart = position;
// push backtrack info if available:
if(count - rep->min)
push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
// jump to next state:
pstate = rep->alt.p;
return true;
}
else
{
// non-greedy, push state and return true if we can skip:
if(count < rep->max)
push_single_repeat(count, rep, position, saved_state_rep_fast_dot);
pstate = rep->alt.p;
return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
}
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127)
#endif
#ifdef __BORLANDC__
#pragma option push -w-8008 -w-8066 -w-8004
#endif
const re_repeat* rep = static_cast<const re_repeat*>(pstate);
BOOST_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length);
const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
std::size_t count = 0;
//
// start by working out how much we can skip:
//
bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
std::size_t desired = greedy ? rep->max : rep->min;
if(::boost::is_random_access_iterator<BidiIterator>::value)
{
BidiIterator end = position;
std::advance(end, (std::min)((std::size_t)::boost::re_detail::distance(position, last), desired));
BidiIterator origin(position);
while((position != end) && (traits_inst.translate(*position, icase) == what))
{
++position;
}
count = (unsigned)::boost::re_detail::distance(origin, position);
}
else
{
while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what))
{
++position;
++count;
}
}
if(count < rep->min)
return false;
if(greedy)
{
if((rep->leading) && (count < rep->max))
restart = position;
// push backtrack info if available:
if(count - rep->min)
push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
// jump to next state:
pstate = rep->alt.p;
return true;
}
else
{
// non-greedy, push state and return true if we can skip:
if(count < rep->max)
push_single_repeat(count, rep, position, saved_state_rep_char);
pstate = rep->alt.p;
return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
}
#ifdef __BORLANDC__
#pragma option pop
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127)
#endif
#ifdef __BORLANDC__
#pragma option push -w-8008 -w-8066 -w-8004
#endif
const re_repeat* rep = static_cast<const re_repeat*>(pstate);
const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
std::size_t count = 0;
//
// start by working out how much we can skip:
//
bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
std::size_t desired = greedy ? rep->max : rep->min;
if(::boost::is_random_access_iterator<BidiIterator>::value)
{
BidiIterator end = position;
std::advance(end, (std::min)((std::size_t)::boost::re_detail::distance(position, last), desired));
BidiIterator origin(position);
while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
{
++position;
}
count = (unsigned)::boost::re_detail::distance(origin, position);
}
else
{
while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
{
++position;
++count;
}
}
if(count < rep->min)
return false;
if(greedy)
{
if((rep->leading) && (count < rep->max))
restart = position;
// push backtrack info if available:
if(count - rep->min)
push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
// jump to next state:
pstate = rep->alt.p;
return true;
}
else
{
// non-greedy, push state and return true if we can skip:
if(count < rep->max)
push_single_repeat(count, rep, position, saved_state_rep_short_set);
pstate = rep->alt.p;
return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
}
#ifdef __BORLANDC__
#pragma option pop
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4127)
#endif
#ifdef __BORLANDC__
#pragma option push -w-8008 -w-8066 -w-8004
#endif
typedef typename traits::char_class_type mask_type;
const re_repeat* rep = static_cast<const re_repeat*>(pstate);
const re_set_long<mask_type>* set = static_cast<const re_set_long<mask_type>*>(pstate->next.p);
std::size_t count = 0;
//
// start by working out how much we can skip:
//
bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
std::size_t desired = greedy ? rep->max : rep->min;
if(::boost::is_random_access_iterator<BidiIterator>::value)
{
BidiIterator end = position;
std::advance(end, (std::min)((std::size_t)::boost::re_detail::distance(position, last), desired));
BidiIterator origin(position);
while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
{
++position;
}
count = (unsigned)::boost::re_detail::distance(origin, position);
}
else
{
while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
{
++position;
++count;
}
}
if(count < rep->min)
return false;
if(greedy)
{
if((rep->leading) && (count < rep->max))
restart = position;
// push backtrack info if available:
if(count - rep->min)
push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
// jump to next state:
pstate = rep->alt.p;
return true;
}
else
{
// non-greedy, push state and return true if we can skip:
if(count < rep->max)
push_single_repeat(count, rep, position, saved_state_rep_long_set);
pstate = rep->alt.p;
return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
}
#ifdef __BORLANDC__
#pragma option pop
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
/****************************************************************************
Unwind and associated proceedures follow, these perform what normal stack
unwinding does in the recursive implementation.
****************************************************************************/
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::unwind(bool have_match)
{
static unwind_proc_type const s_unwind_table[14] =
{
&perl_matcher<BidiIterator, Allocator, traits>::unwind_end,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_paren,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_alt,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat,
&perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat,
};
m_recursive_result = have_match;
unwind_proc_type unwinder;
bool cont;
//
// keep unwinding our stack until we have something to do:
//
do
{
unwinder = s_unwind_table[m_backup_state->id];
cont = (this->*unwinder)(m_recursive_result);
}while(cont);
//
// return true if we have more states to try:
//
return pstate ? true : false;
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::unwind_end(bool)
{
pstate = 0; // nothing left to search
return false; // end of stack nothing more to search
}
template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::unwind_paren(bool have_match)
{
saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
// restore previous values if no match was found:
if(have_match == false)
{
m_presult->set_first(pmp->sub.first, pmp->index);
m_presult->set_second(pmp->sub.second, pmp->index, pmp->sub.matched);
}
#ifdef BOOST_REGEX_MATCH_EXTRA
//
// we have a match, push the capture information onto the stack:
//
else if(pmp->sub.matched && (match_extra & m_match_flags))
((*m_presult)[pmp->index]).get_captures().push_back(pmp->sub);
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -