perl_matcher_non_recursive.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,401 行 · 第 1/3 页

HPP
1,401
字号
/* * * Copyright (c) 2002 * John Maddock * * Use, modification and distribution are subject to the  * Boost Software License, Version 1.0. (See accompanying file  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * */ /*  *   LOCATION:    see http://www.boost.org for most recent version.  *   FILE         perl_matcher_common.cpp  *   VERSION      see <boost/version.hpp>  *   DESCRIPTION: Definitions of perl_matcher member functions that are   *                specific to the non-recursive implementation.  */#ifndef BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP#define BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP#include <new>#ifdef BOOST_MSVC#pragma warning(push)#pragma warning(disable: 4103)#endif#ifdef BOOST_HAS_ABI_HEADERS#  include BOOST_ABI_PREFIX#endif#ifdef BOOST_MSVC#pragma warning(pop)#endif#ifdef BOOST_MSVC#  pragma warning(push)#  pragma warning(disable: 4800)#endifnamespace boost{namespace re_detail{template <class T>inline void inplace_destroy(T* p){   (void)p;  // warning suppression   p->~T();}struct saved_state{   union{      unsigned int state_id;      // this padding ensures correct alignment on 64-bit platforms:      std::size_t padding1;      std::ptrdiff_t padding2;      void* padding3;   };   saved_state(unsigned i) : state_id(i) {}};template <class BidiIterator>struct saved_matched_paren : public saved_state{   int index;   sub_match<BidiIterator> sub;   saved_matched_paren(int i, const sub_match<BidiIterator>& s) : saved_state(1), index(i), sub(s){};};template <class BidiIterator>struct saved_position : public saved_state{   const re_syntax_base* pstate;   BidiIterator position;   saved_position(const re_syntax_base* ps, BidiIterator pos, int i) : saved_state(i), pstate(ps), position(pos){};};template <class BidiIterator>struct saved_assertion : public saved_position<BidiIterator>{   bool positive;   saved_assertion(bool p, const re_syntax_base* ps, BidiIterator pos)       : saved_position<BidiIterator>(ps, pos, saved_type_assertion), positive(p){};};template <class BidiIterator>struct saved_repeater : public saved_state{   repeater_count<BidiIterator> count;   saved_repeater(int i, repeater_count<BidiIterator>** s, BidiIterator start)       : saved_state(saved_state_repeater_count), count(i,s,start){}};struct saved_extra_block : public saved_state{   saved_state *base, *end;   saved_extra_block(saved_state* b, saved_state* e)       : saved_state(saved_state_extra_block), base(b), end(e) {}};struct save_state_init{   saved_state** stack;   save_state_init(saved_state** base, saved_state** end)      : stack(base)   {      *base = static_cast<saved_state*>(get_mem_block());      *end = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(*base)+BOOST_REGEX_BLOCKSIZE);      --(*end);      (void) new (*end)saved_state(0);      BOOST_ASSERT(*end > *base);   }   ~save_state_init()   {      put_mem_block(*stack);      *stack = 0;   }};template <class BidiIterator>struct saved_single_repeat : public saved_state{   std::size_t count;   const re_repeat* rep;   BidiIterator last_position;   saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id)       : saved_state(arg_id), count(c), rep(r), last_position(lp){}};template <class BidiIterator, class Allocator, class traits>bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states(){   static matcher_proc_type const s_match_vtable[29] =    {      (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),      &perl_matcher<BidiIterator, Allocator, traits>::match_endmark,      &perl_matcher<BidiIterator, Allocator, traits>::match_literal,      &perl_matcher<BidiIterator, Allocator, traits>::match_start_line,      &perl_matcher<BidiIterator, Allocator, traits>::match_end_line,      &perl_matcher<BidiIterator, Allocator, traits>::match_wild,      &perl_matcher<BidiIterator, Allocator, traits>::match_match,      &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary,      &perl_matcher<BidiIterator, Allocator, traits>::match_within_word,      &perl_matcher<BidiIterator, Allocator, traits>::match_word_start,      &perl_matcher<BidiIterator, Allocator, traits>::match_word_end,      &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start,      &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end,      &perl_matcher<BidiIterator, Allocator, traits>::match_backref,      &perl_matcher<BidiIterator, Allocator, traits>::match_long_set,      &perl_matcher<BidiIterator, Allocator, traits>::match_set,      &perl_matcher<BidiIterator, Allocator, traits>::match_jump,      &perl_matcher<BidiIterator, Allocator, traits>::match_alt,      &perl_matcher<BidiIterator, Allocator, traits>::match_rep,      &perl_matcher<BidiIterator, Allocator, traits>::match_combining,      &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end,      &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue,      (::boost::is_random_access_iterator<BidiIterator>::value ? &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast : &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow),      &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat,      &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,      &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,      &perl_matcher<BidiIterator, Allocator, traits>::match_backstep,      &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,      &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,   };   push_recursion_stopper();   do{      while(pstate)      {         matcher_proc_type proc = s_match_vtable[pstate->type];         ++state_count;         if(!(this->*proc)())         {            if(state_count > max_state_count)               raise_error(traits_inst, regex_constants::error_space);            if((m_match_flags & match_partial) && (position == last) && (position != search_base))               m_has_partial_match = true;            bool successful_unwind = unwind(false);            if((m_match_flags & match_partial) && (position == last) && (position != search_base))               m_has_partial_match = true;            if(false == successful_unwind)               return m_recursive_result;         }      }   }while(unwind(true));   return m_recursive_result;}template <class BidiIterator, class Allocator, class traits>void perl_matcher<BidiIterator, Allocator, traits>::extend_stack(){   if(used_block_count)   {      --used_block_count;      saved_state* stack_base;      saved_state* backup_state;      stack_base = static_cast<saved_state*>(get_mem_block());      backup_state = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(stack_base)+BOOST_REGEX_BLOCKSIZE);      saved_extra_block* block = static_cast<saved_extra_block*>(backup_state);      --block;      (void) new (block) saved_extra_block(m_stack_base, m_backup_state);      m_stack_base = stack_base;      m_backup_state = block;   }   else      raise_error(traits_inst, regex_constants::error_size);}template <class BidiIterator, class Allocator, class traits>inline void perl_matcher<BidiIterator, Allocator, traits>::push_matched_paren(int index, const sub_match<BidiIterator>& sub){   BOOST_ASSERT(index);   saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);   --pmp;   if(pmp < m_stack_base)   {      extend_stack();      pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);      --pmp;   }   (void) new (pmp)saved_matched_paren<BidiIterator>(index, sub);   m_backup_state = pmp;}template <class BidiIterator, class Allocator, class traits>inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_stopper(){   saved_state* pmp = m_backup_state;   --pmp;   if(pmp < m_stack_base)   {      extend_stack();      pmp = m_backup_state;      --pmp;   }   (void) new (pmp)saved_state(saved_type_recurse);   m_backup_state = pmp;}template <class BidiIterator, class Allocator, class traits>inline void perl_matcher<BidiIterator, Allocator, traits>::push_assertion(const re_syntax_base* ps, bool positive){   saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);   --pmp;   if(pmp < m_stack_base)   {      extend_stack();      pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);      --pmp;   }   (void) new (pmp)saved_assertion<BidiIterator>(positive, ps, position);   m_backup_state = pmp;}template <class BidiIterator, class Allocator, class traits>inline void perl_matcher<BidiIterator, Allocator, traits>::push_alt(const re_syntax_base* ps){   saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);   --pmp;   if(pmp < m_stack_base)   {      extend_stack();      pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);      --pmp;   }   (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_alt);   m_backup_state = pmp;}template <class BidiIterator, class Allocator, class traits>inline void perl_matcher<BidiIterator, Allocator, traits>::push_non_greedy_repeat(const re_syntax_base* ps){   saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);   --pmp;   if(pmp < m_stack_base)   {      extend_stack();      pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);      --pmp;   }   (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_non_greedy_long_repeat);   m_backup_state = pmp;}template <class BidiIterator, class Allocator, class traits>inline void perl_matcher<BidiIterator, Allocator, traits>::push_repeater_count(int i, repeater_count<BidiIterator>** s){   saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);   --pmp;   if(pmp < m_stack_base)   {      extend_stack();      pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);      --pmp;   }   (void) new (pmp)saved_repeater<BidiIterator>(i, s, position);   m_backup_state = pmp;}template <class BidiIterator, class Allocator, class traits>inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id){   saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);   --pmp;   if(pmp < m_stack_base)   {      extend_stack();      pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);      --pmp;   }   (void) new (pmp)saved_single_repeat<BidiIterator>(c, r, last_position, state_id);   m_backup_state = pmp;}template <class BidiIterator, class Allocator, class traits>bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark(){   int index = static_cast<const re_brace*>(pstate)->index;   switch(index)   {   case 0:      pstate = pstate->next.p;      break;   case -1:   case -2:      {         // forward lookahead assert:         const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;         pstate = pstate->next.p->next.p;         push_assertion(next_pstate, index == -1);         break;      }   case -3:      {         // independent sub-expression, currently this is always recursive:         bool old_independent = m_independent;         m_independent = true;         const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;         pstate = pstate->next.p->next.p;         bool r = match_all_states();         pstate = next_pstate;         m_independent = old_independent;#ifdef BOOST_REGEX_MATCH_EXTRA         if(r && (m_match_flags & match_extra))         {            //            // our captures have been stored in *m_presult            // we need to unpack them, and insert them            // back in the right order when we unwind the stack:            //            match_results<BidiIterator, Allocator> temp_match(*m_presult);            unsigned i;            for(i = 0; i < temp_match.size(); ++i)               (*m_presult)[i].get_captures().clear();            // match everything else:            r = match_all_states();            // now place the stored captures back:            for(i = 0; i < temp_match.size(); ++i)            {               typedef typename sub_match<BidiIterator>::capture_sequence_type seq;               seq& s1 = (*m_presult)[i].get_captures();               const seq& s2 = temp_match[i].captures();               s1.insert(                  s1.end(),                   s2.begin(),                   s2.end());            }         }#endif         return r;      }   case -4:      {      // conditional expression:      const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);      BOOST_ASSERT(alt->type == syntax_element_alt);      pstate = alt->next.p;      if(pstate->type == syntax_element_assert_backref)      {         if(!match_assert_backref())            pstate = alt->alt.p;         break;      }      else      {         // zero width assertion, have to match this recursively:         BOOST_ASSERT(pstate->type == syntax_element_startmark);         bool negated = static_cast<const re_brace*>(pstate)->index == -2;         BidiIterator saved_position = position;         const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;         pstate = pstate->next.p->next.p;         bool r = match_all_states();         position = saved_position;         if(negated)            r = !r;         if(r)            pstate = next_pstate;         else            pstate = alt->alt.p;         break;      }      }   default:   {      BOOST_ASSERT(index > 0);      if((m_match_flags & match_nosubs) == 0)      {         push_matched_paren(index, (*m_presult)[index]);         m_presult->set_first(position, index);      }      pstate = pstate->next.p;      break;   }   }   return true;}template <class BidiIterator, class Allocator, class traits>bool perl_matcher<BidiIterator, Allocator, traits>::match_alt(){   bool take_first, take_second;   const re_alt* jmp = static_cast<const re_alt*>(pstate);   // find out which of these two alternatives we need to take:   if(position == last)   {      take_first = jmp->can_be_null & mask_take;      take_second = jmp->can_be_null & mask_skip;   }   else   {      take_first = can_start(*position, jmp->_map, (unsigned char)mask_take);      take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip);  }   if(take_first)   {      // we can take the first alternative,      // see if we need to push next alternative:      if(take_second)      {         push_alt(jmp->alt.p);      }      pstate = pstate->next.p;      return true;   }   if(take_second)   {      pstate = jmp->alt.p;      return true;   }   return false;  // neither option is possible}template <class BidiIterator, class Allocator, class traits>bool perl_matcher<BidiIterator, Allocator, traits>::match_rep(){#ifdef BOOST_MSVC#pragma warning(push)#pragma warning(disable:4127 4244)#endif#ifdef __BORLANDC__#pragma option push -w-8008 -w-8066 -w-8004#endif   const re_repeat* rep = static_cast<const re_repeat*>(pstate);   // find out which of these two alternatives we need to take:

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?