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