perl_matcher_non_recursive.hpp

来自「CGAL is a collaborative effort of severa」· HPP 代码 · 共 1,303 行 · 第 1/3 页

HPP
1,303
字号
/* * * Copyright (c) 2002 * Dr 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_HAS_ABI_HEADERS#  include BOOST_ABI_PREFIX#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 id;      // these ensure that this struct gets the same alignment as derived structs:      void* padding1;      std::size_t padding2;      std::ptrdiff_t padding3;   };   saved_state(unsigned i) : 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);      assert(*end > *base);   }   ~save_state_init()   {      put_mem_block(*stack);      *stack = 0;   }};template <class BidiIterator>struct saved_single_repeat : public saved_state{   unsigned count;   const re_repeat* rep;   BidiIterator last_position;   saved_single_repeat(unsigned 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, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_all_states(){   static matcher_proc_type const s_match_vtable[26] =    {      (&perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_startmark),      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_endmark,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_literal,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_start_line,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_end_line,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_wild,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_match,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_word_boundary,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_within_word,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_word_start,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_word_end,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_buffer_start,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_buffer_end,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_backref,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_long_set,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_set,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_jump,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_alt,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_rep,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_combining,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_soft_buffer_end,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_restart_continue,      (::boost::is_random_access_iterator<BidiIterator>::value ? &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_dot_repeat_fast : &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_dot_repeat_slow),      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_char_repeat,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_set_repeat,      &perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_long_set_repeat,   };   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, REG_ESPACE);            if((m_match_flags & match_partial) && (position == last))               m_has_partial_match = true;            if(false == unwind(false))               return m_recursive_result;         }      }   }while(unwind(true));   return m_recursive_result;}template <class BidiIterator, class Allocator, class traits, class Allocator2>void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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, REG_E_MEMORY);}template <class BidiIterator, class Allocator, class traits, class Allocator2>inline void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::push_matched_paren(int index, const sub_match<BidiIterator>& sub){   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, class Allocator2>inline void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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, class Allocator2>inline void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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, class Allocator2>inline void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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, class Allocator2>inline void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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, class Allocator2>inline void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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, class Allocator2>inline void perl_matcher<BidiIterator, Allocator, traits, Allocator2>::push_single_repeat(unsigned c, const re_repeat* r, BidiIterator last_position, int 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, id);   m_backup_state = pmp;}template <class BidiIterator, class Allocator, class traits, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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:         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;#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;      }   default:   {      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, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::match_alt(){   bool take_first, take_second;   const re_jump* jmp = static_cast<const re_jump*>(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 = access::can_start(*position, jmp->_map, (unsigned char)mask_take);      take_second = access::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, class Allocator2>bool perl_matcher<BidiIterator, Allocator, traits, Allocator2>::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:   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 = access::can_start(*position, rep->_map, (unsigned char)mask_take);      take_second = access::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);   }   //

⌨️ 快捷键说明

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