perl_matcher_non_recursive.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,401 行 · 第 1/3 页
HPP
1,401 行
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((m_backup_state->state_id != saved_state_repeater_count) || (static_cast<saved_repeater<BidiIterator>*>(m_backup_state)->count.get_id() != rep->state_id) || (next_count->get_id() != rep->state_id)) { // we're moving to a different repeat from the last // one, so set up a counter object: push_repeater_count(rep->state_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 stackunwinding 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->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 // unwind stack: m_backup_state = pmp+1; boost::re_detail::inplace_destroy(pmp); return true; // keep looking}template <class BidiIterator, class Allocator, class traits>bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper(bool){ boost::re_detail::inplace_destroy(m_backup_state++); pstate = 0; // nothing left to search return false; // end of stack nothing more to search}template <class BidiIterator, class Allocator, class traits>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?