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