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 + -
显示快捷键?