perl_matcher_non_recursive.hpp
来自「CGAL is a collaborative effort of severa」· HPP 代码 · 共 1,303 行 · 第 1/3 页
HPP
1,303 行
// 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; } if(rep->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) { // 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, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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; } if(rep->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) : access::can_start(*position, rep->_map, mask_skip); }}template <class BidiIterator, class Allocator, class traits, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_dot_repeat_fast(){ if(m_match_flags & (match_not_dot_newline | match_not_dot_null)) return match_dot_repeat_slow(); const re_repeat* rep = static_cast<const re_repeat*>(pstate); unsigned count = (std::min)(static_cast<unsigned>(re_detail::distance(position, last)), static_cast<unsigned>(rep->greedy ? rep->max : rep->min)); if(rep->min > count) return false; // not enough text left to match std::advance(position, count); if(rep->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) : access::can_start(*position, rep->_map, mask_skip); }}template <class BidiIterator, class Allocator, class traits, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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); 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); unsigned count = 0; // // start by working out how much we can skip: // unsigned desired = rep->greedy ? rep->max : rep->min; if(::boost::is_random_access_iterator<BidiIterator>::value) { BidiIterator end = position; std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired)); BidiIterator origin(position); while((position != end) && (traits_inst.translate(*position, icase) == what)) { ++position; } count = (unsigned)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(rep->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) : access::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, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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; unsigned count = 0; // // start by working out how much we can skip: // unsigned desired = rep->greedy ? rep->max : rep->min; if(::boost::is_random_access_iterator<BidiIterator>::value) { BidiIterator end = position; std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired)); BidiIterator origin(position); while((position != end) && map[(traits_uchar_type)traits_inst.translate(*position, icase)]) { ++position; } count = (unsigned)re_detail::distance(origin, position); } else { while((count < desired) && (position != last) && map[(traits_uchar_type)traits_inst.translate(*position, icase)]) { ++position; ++count; } } if(count < rep->min) return false; if(rep->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) : access::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, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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 const re_repeat* rep = static_cast<const re_repeat*>(pstate); const re_set_long* set = static_cast<const re_set_long*>(pstate->next.p); unsigned count = 0; // // start by working out how much we can skip: // unsigned desired = rep->greedy ? rep->max : rep->min; if(::boost::is_random_access_iterator<BidiIterator>::value) { BidiIterator end = position; std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired)); BidiIterator origin(position); while((position != end) && (position != re_is_set_member(position, last, set, re))) { ++position; } count = (unsigned)re_detail::distance(origin, position); } else { while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re))) { ++position; ++count; } } if(count < rep->min) return false; if(rep->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) : access::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, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind(bool have_match){ static unwind_proc_type const s_unwind_table[14] = { &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_end, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_paren, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_recursion_stopper, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_assertion, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_alt, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_repeater_counter, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_extra_block, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_greedy_single_repeat, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_slow_dot_repeat, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_fast_dot_repeat, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_char_repeat, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_short_set_repeat, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_long_set_repeat, &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::unwind_assertion(bool r){ saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state); pstate = pmp->pstate;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?