6 * Use, modification and distribution are subject to the
7 * Boost Software License, Version 1.0. (See accompanying file
8 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13 * LOCATION: see http://www.boost.org for most recent version.
14 * FILE perl_matcher_common.cpp
15 * VERSION see <boost/version.hpp>
16 * DESCRIPTION: Definitions of perl_matcher member functions that are
17 * specific to the non-recursive implementation.
20 #ifndef BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
21 #define BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
27 #pragma warning(disable: 4103)
29 #ifdef BOOST_HAS_ABI_HEADERS
30 # include BOOST_ABI_PREFIX
36 # pragma warning(push)
37 # pragma warning(disable: 4800 4706)
41 namespace BOOST_REGEX_DETAIL_NS{
44 inline void inplace_destroy(T* p)
46 (void)p; // warning suppression
53 unsigned int state_id;
54 // this padding ensures correct alignment on 64-bit platforms:
56 std::ptrdiff_t padding2;
59 saved_state(unsigned i) : state_id(i) {}
62 template <class BidiIterator>
63 struct saved_matched_paren : public saved_state
66 sub_match<BidiIterator> sub;
67 saved_matched_paren(int i, const sub_match<BidiIterator>& s) : saved_state(1), index(i), sub(s){};
70 template <class BidiIterator>
71 struct saved_position : public saved_state
73 const re_syntax_base* pstate;
74 BidiIterator position;
75 saved_position(const re_syntax_base* ps, BidiIterator pos, int i) : saved_state(i), pstate(ps), position(pos){};
78 template <class BidiIterator>
79 struct saved_assertion : public saved_position<BidiIterator>
82 saved_assertion(bool p, const re_syntax_base* ps, BidiIterator pos)
83 : saved_position<BidiIterator>(ps, pos, saved_type_assertion), positive(p){};
86 template <class BidiIterator>
87 struct saved_repeater : public saved_state
89 repeater_count<BidiIterator> count;
90 saved_repeater(int i, repeater_count<BidiIterator>** s, BidiIterator start, int current_recursion_id)
91 : saved_state(saved_state_repeater_count), count(i, s, start, current_recursion_id){}
94 struct saved_extra_block : public saved_state
96 saved_state *base, *end;
97 saved_extra_block(saved_state* b, saved_state* e)
98 : saved_state(saved_state_extra_block), base(b), end(e) {}
101 struct save_state_init
104 save_state_init(saved_state** base, saved_state** end)
107 *base = static_cast<saved_state*>(get_mem_block());
108 *end = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(*base)+BOOST_REGEX_BLOCKSIZE);
110 (void) new (*end)saved_state(0);
111 BOOST_ASSERT(*end > *base);
115 put_mem_block(*stack);
120 template <class BidiIterator>
121 struct saved_single_repeat : public saved_state
124 const re_repeat* rep;
125 BidiIterator last_position;
126 saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id)
127 : saved_state(arg_id), count(c), rep(r), last_position(lp){}
130 template <class Results>
131 struct saved_recursion : public saved_state
133 saved_recursion(int idx, const re_syntax_base* p, Results* pr, Results* pr2)
134 : saved_state(14), recursion_id(idx), preturn_address(p), internal_results(*pr), prior_results(*pr2) {}
136 const re_syntax_base* preturn_address;
137 Results internal_results, prior_results;
140 struct saved_change_case : public saved_state
143 saved_change_case(bool c) : saved_state(18), icase(c) {}
148 incrementer(unsigned* pu) : m_pu(pu) { ++*m_pu; }
149 ~incrementer() { --*m_pu; }
150 bool operator > (unsigned i) { return *m_pu > i; }
155 template <class BidiIterator, class Allocator, class traits>
156 bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
158 static matcher_proc_type const s_match_vtable[34] =
160 (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
161 &perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
162 &perl_matcher<BidiIterator, Allocator, traits>::match_literal,
163 &perl_matcher<BidiIterator, Allocator, traits>::match_start_line,
164 &perl_matcher<BidiIterator, Allocator, traits>::match_end_line,
165 &perl_matcher<BidiIterator, Allocator, traits>::match_wild,
166 &perl_matcher<BidiIterator, Allocator, traits>::match_match,
167 &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary,
168 &perl_matcher<BidiIterator, Allocator, traits>::match_within_word,
169 &perl_matcher<BidiIterator, Allocator, traits>::match_word_start,
170 &perl_matcher<BidiIterator, Allocator, traits>::match_word_end,
171 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start,
172 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end,
173 &perl_matcher<BidiIterator, Allocator, traits>::match_backref,
174 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set,
175 &perl_matcher<BidiIterator, Allocator, traits>::match_set,
176 &perl_matcher<BidiIterator, Allocator, traits>::match_jump,
177 &perl_matcher<BidiIterator, Allocator, traits>::match_alt,
178 &perl_matcher<BidiIterator, Allocator, traits>::match_rep,
179 &perl_matcher<BidiIterator, Allocator, traits>::match_combining,
180 &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end,
181 &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue,
182 // Although this next line *should* be evaluated at compile time, in practice
183 // some compilers (VC++) emit run-time initialisation which breaks thread
184 // safety, so use a dispatch function instead:
185 //(::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),
186 &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch,
187 &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat,
188 &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
189 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
190 &perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
191 &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
192 &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
193 &perl_matcher<BidiIterator, Allocator, traits>::match_recursion,
194 &perl_matcher<BidiIterator, Allocator, traits>::match_fail,
195 &perl_matcher<BidiIterator, Allocator, traits>::match_accept,
196 &perl_matcher<BidiIterator, Allocator, traits>::match_commit,
197 &perl_matcher<BidiIterator, Allocator, traits>::match_then,
199 incrementer inc(&m_recursions);
201 raise_error(traits_inst, regex_constants::error_complexity);
202 push_recursion_stopper();
206 matcher_proc_type proc = s_match_vtable[pstate->type];
210 if(state_count > max_state_count)
211 raise_error(traits_inst, regex_constants::error_complexity);
212 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
213 m_has_partial_match = true;
214 bool successful_unwind = unwind(false);
215 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
216 m_has_partial_match = true;
217 if(false == successful_unwind)
218 return m_recursive_result;
221 }while(unwind(true));
222 return m_recursive_result;
225 template <class BidiIterator, class Allocator, class traits>
226 void perl_matcher<BidiIterator, Allocator, traits>::extend_stack()
231 saved_state* stack_base;
232 saved_state* backup_state;
233 stack_base = static_cast<saved_state*>(get_mem_block());
234 backup_state = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(stack_base)+BOOST_REGEX_BLOCKSIZE);
235 saved_extra_block* block = static_cast<saved_extra_block*>(backup_state);
237 (void) new (block) saved_extra_block(m_stack_base, m_backup_state);
238 m_stack_base = stack_base;
239 m_backup_state = block;
242 raise_error(traits_inst, regex_constants::error_stack);
245 template <class BidiIterator, class Allocator, class traits>
246 inline void perl_matcher<BidiIterator, Allocator, traits>::push_matched_paren(int index, const sub_match<BidiIterator>& sub)
248 //BOOST_ASSERT(index);
249 saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
251 if(pmp < m_stack_base)
254 pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
257 (void) new (pmp)saved_matched_paren<BidiIterator>(index, sub);
258 m_backup_state = pmp;
261 template <class BidiIterator, class Allocator, class traits>
262 inline void perl_matcher<BidiIterator, Allocator, traits>::push_case_change(bool c)
264 //BOOST_ASSERT(index);
265 saved_change_case* pmp = static_cast<saved_change_case*>(m_backup_state);
267 if(pmp < m_stack_base)
270 pmp = static_cast<saved_change_case*>(m_backup_state);
273 (void) new (pmp)saved_change_case(c);
274 m_backup_state = pmp;
277 template <class BidiIterator, class Allocator, class traits>
278 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_stopper()
280 saved_state* pmp = m_backup_state;
282 if(pmp < m_stack_base)
285 pmp = m_backup_state;
288 (void) new (pmp)saved_state(saved_type_recurse);
289 m_backup_state = pmp;
292 template <class BidiIterator, class Allocator, class traits>
293 inline void perl_matcher<BidiIterator, Allocator, traits>::push_assertion(const re_syntax_base* ps, bool positive)
295 saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
297 if(pmp < m_stack_base)
300 pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
303 (void) new (pmp)saved_assertion<BidiIterator>(positive, ps, position);
304 m_backup_state = pmp;
307 template <class BidiIterator, class Allocator, class traits>
308 inline void perl_matcher<BidiIterator, Allocator, traits>::push_alt(const re_syntax_base* ps)
310 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
312 if(pmp < m_stack_base)
315 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
318 (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_alt);
319 m_backup_state = pmp;
322 template <class BidiIterator, class Allocator, class traits>
323 inline void perl_matcher<BidiIterator, Allocator, traits>::push_non_greedy_repeat(const re_syntax_base* ps)
325 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
327 if(pmp < m_stack_base)
330 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
333 (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_non_greedy_long_repeat);
334 m_backup_state = pmp;
337 template <class BidiIterator, class Allocator, class traits>
338 inline void perl_matcher<BidiIterator, Allocator, traits>::push_repeater_count(int i, repeater_count<BidiIterator>** s)
340 saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
342 if(pmp < m_stack_base)
345 pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
348 (void) new (pmp)saved_repeater<BidiIterator>(i, s, position, this->recursion_stack.size() ? this->recursion_stack.back().idx : (INT_MIN + 3));
349 m_backup_state = pmp;
352 template <class BidiIterator, class Allocator, class traits>
353 inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id)
355 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
357 if(pmp < m_stack_base)
360 pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
363 (void) new (pmp)saved_single_repeat<BidiIterator>(c, r, last_position, state_id);
364 m_backup_state = pmp;
367 template <class BidiIterator, class Allocator, class traits>
368 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion(int idx, const re_syntax_base* p, results_type* presults, results_type* presults2)
370 saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
372 if(pmp < m_stack_base)
375 pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
378 (void) new (pmp)saved_recursion<results_type>(idx, p, presults, presults2);
379 m_backup_state = pmp;
382 template <class BidiIterator, class Allocator, class traits>
383 bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
385 // change our case sensitivity:
386 push_case_change(this->icase);
387 this->icase = static_cast<const re_case*>(pstate)->icase;
388 pstate = pstate->next.p;
392 template <class BidiIterator, class Allocator, class traits>
393 bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
395 int index = static_cast<const re_brace*>(pstate)->index;
396 icase = static_cast<const re_brace*>(pstate)->icase;
400 pstate = pstate->next.p;
405 // forward lookahead assert:
406 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
407 pstate = pstate->next.p->next.p;
408 push_assertion(next_pstate, index == -1);
413 // independent sub-expression, currently this is always recursive:
414 bool old_independent = m_independent;
415 m_independent = true;
416 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
417 pstate = pstate->next.p->next.p;
419 #if !defined(BOOST_NO_EXCEPTIONS)
422 r = match_all_states();
423 if(!r && !m_independent)
425 // Must be unwinding from a COMMIT/SKIP/PRUNE and the independent
426 // sub failed, need to unwind everything else:
427 while(unwind(false));
430 #if !defined(BOOST_NO_EXCEPTIONS)
434 pstate = next_pstate;
435 // unwind all pushed states, apart from anything else this
436 // ensures that all the states are correctly destructed
437 // not just the memory freed.
438 while(unwind(true)) {}
442 pstate = next_pstate;
443 m_independent = old_independent;
444 #ifdef BOOST_REGEX_MATCH_EXTRA
445 if(r && (m_match_flags & match_extra))
448 // our captures have been stored in *m_presult
449 // we need to unpack them, and insert them
450 // back in the right order when we unwind the stack:
452 match_results<BidiIterator, Allocator> temp_match(*m_presult);
454 for(i = 0; i < temp_match.size(); ++i)
455 (*m_presult)[i].get_captures().clear();
456 // match everything else:
457 #if !defined(BOOST_NO_EXCEPTIONS)
460 r = match_all_states();
461 #if !defined(BOOST_NO_EXCEPTIONS)
465 pstate = next_pstate;
466 // unwind all pushed states, apart from anything else this
467 // ensures that all the states are correctly destructed
468 // not just the memory freed.
469 while(unwind(true)) {}
473 // now place the stored captures back:
474 for(i = 0; i < temp_match.size(); ++i)
476 typedef typename sub_match<BidiIterator>::capture_sequence_type seq;
477 seq& s1 = (*m_presult)[i].get_captures();
478 const seq& s2 = temp_match[i].captures();
490 // conditional expression:
491 const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
492 BOOST_ASSERT(alt->type == syntax_element_alt);
493 pstate = alt->next.p;
494 if(pstate->type == syntax_element_assert_backref)
496 if(!match_assert_backref())
502 // zero width assertion, have to match this recursively:
503 BOOST_ASSERT(pstate->type == syntax_element_startmark);
504 bool negated = static_cast<const re_brace*>(pstate)->index == -2;
505 BidiIterator saved_position = position;
506 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
507 pstate = pstate->next.p->next.p;
508 #if !defined(BOOST_NO_EXCEPTIONS)
511 bool r = match_all_states();
512 position = saved_position;
516 pstate = next_pstate;
519 #if !defined(BOOST_NO_EXCEPTIONS)
523 pstate = next_pstate;
524 // unwind all pushed states, apart from anything else this
525 // ensures that all the states are correctly destructed
526 // not just the memory freed.
527 while(unwind(true)){}
536 push_matched_paren(0, (*m_presult)[0]);
537 m_presult->set_first(position, 0, true);
538 pstate = pstate->next.p;
543 BOOST_ASSERT(index > 0);
544 if((m_match_flags & match_nosubs) == 0)
546 push_matched_paren(index, (*m_presult)[index]);
547 m_presult->set_first(position, index);
549 pstate = pstate->next.p;
556 template <class BidiIterator, class Allocator, class traits>
557 bool perl_matcher<BidiIterator, Allocator, traits>::match_alt()
559 bool take_first, take_second;
560 const re_alt* jmp = static_cast<const re_alt*>(pstate);
562 // find out which of these two alternatives we need to take:
565 take_first = jmp->can_be_null & mask_take;
566 take_second = jmp->can_be_null & mask_skip;
570 take_first = can_start(*position, jmp->_map, (unsigned char)mask_take);
571 take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip);
576 // we can take the first alternative,
577 // see if we need to push next alternative:
580 push_alt(jmp->alt.p);
582 pstate = pstate->next.p;
590 return false; // neither option is possible
593 template <class BidiIterator, class Allocator, class traits>
594 bool perl_matcher<BidiIterator, Allocator, traits>::match_rep()
597 #pragma warning(push)
598 #pragma warning(disable:4127 4244)
601 #pragma option push -w-8008 -w-8066 -w-8004
603 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
605 // find out which of these two alternatives we need to take:
606 bool take_first, take_second;
609 take_first = rep->can_be_null & mask_take;
610 take_second = rep->can_be_null & mask_skip;
614 take_first = can_start(*position, rep->_map, (unsigned char)mask_take);
615 take_second = can_start(*position, rep->_map, (unsigned char)mask_skip);
618 if((m_backup_state->state_id != saved_state_repeater_count)
619 || (static_cast<saved_repeater<BidiIterator>*>(m_backup_state)->count.get_id() != rep->state_id)
620 || (next_count->get_id() != rep->state_id))
622 // we're moving to a different repeat from the last
623 // one, so set up a counter object:
624 push_repeater_count(rep->state_id, &next_count);
627 // If we've had at least one repeat already, and the last one
628 // matched the NULL string then set the repeat count to
631 next_count->check_null_repeat(position, rep->max);
633 if(next_count->get_count() < rep->min)
635 // we must take the repeat:
638 // increase the counter:
640 pstate = rep->next.p;
646 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
649 // try and take the repeat if we can:
650 if((next_count->get_count() < rep->max) && take_first)
654 // store position in case we fail:
655 push_alt(rep->alt.p);
657 // increase the counter:
659 pstate = rep->next.p;
667 return false; // can't take anything, fail...
671 // try and skip the repeat if we can:
674 if((next_count->get_count() < rep->max) && take_first)
676 // store position in case we fail:
677 push_non_greedy_repeat(rep->next.p);
682 if((next_count->get_count() < rep->max) && take_first)
684 // increase the counter:
686 pstate = rep->next.p;
699 template <class BidiIterator, class Allocator, class traits>
700 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
702 std::size_t count = 0;
703 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
704 re_syntax_base* psingle = rep->next.p;
705 // match compulsary repeats first:
706 while(count < rep->min)
713 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
716 // repeat for as long as we can:
717 while(count < rep->max)
724 // remember where we got to if this is a leading repeat:
725 if((rep->leading) && (count < rep->max))
727 // push backtrack info if available:
729 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
730 // jump to next state:
736 // non-greedy, push state and return true if we can skip:
738 push_single_repeat(count, rep, position, saved_state_rep_slow_dot);
740 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
744 template <class BidiIterator, class Allocator, class traits>
745 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
747 if(m_match_flags & match_not_dot_null)
748 return match_dot_repeat_slow();
749 if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
750 return match_dot_repeat_slow();
752 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
753 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
754 std::size_t count = static_cast<std::size_t>((std::min)(static_cast<std::size_t>(::boost::BOOST_REGEX_DETAIL_NS::distance(position, last)), greedy ? rep->max : rep->min));
758 return false; // not enough text left to match
760 std::advance(position, count);
764 if((rep->leading) && (count < rep->max))
766 // push backtrack info if available:
768 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
769 // jump to next state:
775 // non-greedy, push state and return true if we can skip:
777 push_single_repeat(count, rep, position, saved_state_rep_fast_dot);
779 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
783 template <class BidiIterator, class Allocator, class traits>
784 bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
787 #pragma warning(push)
788 #pragma warning(disable:4127)
791 #pragma option push -w-8008 -w-8066 -w-8004
793 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
794 BOOST_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length);
795 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
796 std::size_t count = 0;
798 // start by working out how much we can skip:
800 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
801 std::size_t desired = greedy ? rep->max : rep->min;
802 if(::boost::is_random_access_iterator<BidiIterator>::value)
804 BidiIterator end = position;
805 // Move end forward by "desired", preferably without using distance or advance if we can
806 // as these can be slow for some iterator types.
807 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
811 std::advance(end, desired);
812 BidiIterator origin(position);
813 while((position != end) && (traits_inst.translate(*position, icase) == what))
817 count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
821 while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what))
833 if((rep->leading) && (count < rep->max))
835 // push backtrack info if available:
837 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
838 // jump to next state:
844 // non-greedy, push state and return true if we can skip:
846 push_single_repeat(count, rep, position, saved_state_rep_char);
848 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
858 template <class BidiIterator, class Allocator, class traits>
859 bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
862 #pragma warning(push)
863 #pragma warning(disable:4127)
866 #pragma option push -w-8008 -w-8066 -w-8004
868 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
869 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
870 std::size_t count = 0;
872 // start by working out how much we can skip:
874 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
875 std::size_t desired = greedy ? rep->max : rep->min;
876 if(::boost::is_random_access_iterator<BidiIterator>::value)
878 BidiIterator end = position;
879 // Move end forward by "desired", preferably without using distance or advance if we can
880 // as these can be slow for some iterator types.
881 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
885 std::advance(end, desired);
886 BidiIterator origin(position);
887 while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
891 count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
895 while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
907 if((rep->leading) && (count < rep->max))
909 // push backtrack info if available:
911 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
912 // jump to next state:
918 // non-greedy, push state and return true if we can skip:
920 push_single_repeat(count, rep, position, saved_state_rep_short_set);
922 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
932 template <class BidiIterator, class Allocator, class traits>
933 bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
936 #pragma warning(push)
937 #pragma warning(disable:4127)
940 #pragma option push -w-8008 -w-8066 -w-8004
942 typedef typename traits::char_class_type m_type;
943 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
944 const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate->next.p);
945 std::size_t count = 0;
947 // start by working out how much we can skip:
949 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
950 std::size_t desired = greedy ? rep->max : rep->min;
951 if(::boost::is_random_access_iterator<BidiIterator>::value)
953 BidiIterator end = position;
954 // Move end forward by "desired", preferably without using distance or advance if we can
955 // as these can be slow for some iterator types.
956 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
960 std::advance(end, desired);
961 BidiIterator origin(position);
962 while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
966 count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
970 while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
982 if((rep->leading) && (count < rep->max))
984 // push backtrack info if available:
986 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
987 // jump to next state:
993 // non-greedy, push state and return true if we can skip:
995 push_single_repeat(count, rep, position, saved_state_rep_long_set);
997 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
1003 #pragma warning(pop)
1007 template <class BidiIterator, class Allocator, class traits>
1008 bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
1010 BOOST_ASSERT(pstate->type == syntax_element_recurse);
1012 // See if we've seen this recursion before at this location, if we have then
1013 // we need to prevent infinite recursion:
1015 for(typename std::vector<recursion_info<results_type> >::reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i)
1017 if(i->idx == static_cast<const re_brace*>(static_cast<const re_jump*>(pstate)->alt.p)->index)
1019 if(i->location_of_start == position)
1025 // Backup call stack:
1027 push_recursion_pop();
1029 // Set new call stack:
1031 if(recursion_stack.capacity() == 0)
1033 recursion_stack.reserve(50);
1035 recursion_stack.push_back(recursion_info<results_type>());
1036 recursion_stack.back().preturn_address = pstate->next.p;
1037 recursion_stack.back().results = *m_presult;
1038 pstate = static_cast<const re_jump*>(pstate)->alt.p;
1039 recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
1040 recursion_stack.back().location_of_start = position;
1041 //if(static_cast<const re_recurse*>(pstate)->state_id > 0)
1043 push_repeater_count(-(2 + static_cast<const re_brace*>(pstate)->index), &next_count);
1049 template <class BidiIterator, class Allocator, class traits>
1050 bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
1052 int index = static_cast<const re_brace*>(pstate)->index;
1053 icase = static_cast<const re_brace*>(pstate)->icase;
1056 if((m_match_flags & match_nosubs) == 0)
1058 m_presult->set_second(position, index);
1060 if(!recursion_stack.empty())
1062 if(index == recursion_stack.back().idx)
1064 pstate = recursion_stack.back().preturn_address;
1065 *m_presult = recursion_stack.back().results;
1066 push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results);
1067 recursion_stack.pop_back();
1068 push_repeater_count(-(2 + index), &next_count);
1072 else if((index < 0) && (index != -4))
1074 // matched forward lookahead:
1078 pstate = pstate->next.p;
1082 template <class BidiIterator, class Allocator, class traits>
1083 bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
1085 if(!recursion_stack.empty())
1087 BOOST_ASSERT(0 == recursion_stack.back().idx);
1088 pstate = recursion_stack.back().preturn_address;
1089 push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results);
1090 *m_presult = recursion_stack.back().results;
1091 recursion_stack.pop_back();
1094 if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
1096 if((m_match_flags & match_all) && (position != last))
1098 if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base))
1100 m_presult->set_second(position);
1102 m_has_found_match = true;
1103 if((m_match_flags & match_posix) == match_posix)
1105 m_result.maybe_assign(*m_presult);
1106 if((m_match_flags & match_any) == 0)
1109 #ifdef BOOST_REGEX_MATCH_EXTRA
1110 if(match_extra & m_match_flags)
1112 for(unsigned i = 0; i < m_presult->size(); ++i)
1113 if((*m_presult)[i].matched)
1114 ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]);
1120 template <class BidiIterator, class Allocator, class traits>
1121 bool perl_matcher<BidiIterator, Allocator, traits>::match_commit()
1123 // Ideally we would just junk all the states that are on the stack,
1124 // however we might not unwind correctly in that case, so for now,
1125 // just mark that we don't backtrack into whatever is left (or rather
1126 // we'll unwind it unconditionally without pausing to try other matches).
1128 switch(static_cast<const re_commit*>(pstate)->action)
1134 if(base != position)
1137 // Have to decrement restart since it will get incremented again later:
1145 saved_state* pmp = m_backup_state;
1147 if(pmp < m_stack_base)
1150 pmp = m_backup_state;
1153 (void) new (pmp)saved_state(16);
1154 m_backup_state = pmp;
1155 pstate = pstate->next.p;
1159 template <class BidiIterator, class Allocator, class traits>
1160 bool perl_matcher<BidiIterator, Allocator, traits>::match_then()
1162 // Just leave a mark that we need to skip to next alternative:
1163 saved_state* pmp = m_backup_state;
1165 if(pmp < m_stack_base)
1168 pmp = m_backup_state;
1171 (void) new (pmp)saved_state(17);
1172 m_backup_state = pmp;
1173 pstate = pstate->next.p;
1177 template <class BidiIterator, class Allocator, class traits>
1178 bool perl_matcher<BidiIterator, Allocator, traits>::skip_until_paren(int index, bool have_match)
1182 if(pstate->type == syntax_element_endmark)
1184 if(static_cast<const re_brace*>(pstate)->index == index)
1187 return this->match_endmark();
1188 pstate = pstate->next.p;
1193 // Unenclosed closing ), occurs when (*ACCEPT) is inside some other
1194 // parenthesis which may or may not have other side effects associated with it.
1195 const re_syntax_base* sp = pstate;
1200 // unwind may leave pstate NULL if we've unwound a forward lookahead, in which
1201 // case just move to the next state and keep looking...
1203 pstate = sp->next.p;
1208 else if(pstate->type == syntax_element_match)
1210 else if(pstate->type == syntax_element_startmark)
1212 int idx = static_cast<const re_brace*>(pstate)->index;
1213 pstate = pstate->next.p;
1214 skip_until_paren(idx, false);
1217 pstate = pstate->next.p;
1222 /****************************************************************************
1224 Unwind and associated proceedures follow, these perform what normal stack
1225 unwinding does in the recursive implementation.
1227 ****************************************************************************/
1229 template <class BidiIterator, class Allocator, class traits>
1230 bool perl_matcher<BidiIterator, Allocator, traits>::unwind(bool have_match)
1232 static unwind_proc_type const s_unwind_table[19] =
1234 &perl_matcher<BidiIterator, Allocator, traits>::unwind_end,
1235 &perl_matcher<BidiIterator, Allocator, traits>::unwind_paren,
1236 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper,
1237 &perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion,
1238 &perl_matcher<BidiIterator, Allocator, traits>::unwind_alt,
1239 &perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter,
1240 &perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block,
1241 &perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat,
1242 &perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat,
1243 &perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat,
1244 &perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat,
1245 &perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat,
1246 &perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat,
1247 &perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat,
1248 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion,
1249 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop,
1250 &perl_matcher<BidiIterator, Allocator, traits>::unwind_commit,
1251 &perl_matcher<BidiIterator, Allocator, traits>::unwind_then,
1252 &perl_matcher<BidiIterator, Allocator, traits>::unwind_case,
1255 m_recursive_result = have_match;
1256 m_unwound_lookahead = false;
1257 m_unwound_alt = false;
1258 unwind_proc_type unwinder;
1261 // keep unwinding our stack until we have something to do:
1265 unwinder = s_unwind_table[m_backup_state->state_id];
1266 cont = (this->*unwinder)(m_recursive_result);
1269 // return true if we have more states to try:
1271 return pstate ? true : false;
1274 template <class BidiIterator, class Allocator, class traits>
1275 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_end(bool)
1277 pstate = 0; // nothing left to search
1278 return false; // end of stack nothing more to search
1281 template <class BidiIterator, class Allocator, class traits>
1282 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_case(bool)
1284 saved_change_case* pmp = static_cast<saved_change_case*>(m_backup_state);
1286 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1287 m_backup_state = pmp;
1291 template <class BidiIterator, class Allocator, class traits>
1292 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_paren(bool have_match)
1294 saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
1295 // restore previous values if no match was found:
1296 if(have_match == false)
1298 m_presult->set_first(pmp->sub.first, pmp->index, pmp->index == 0);
1299 m_presult->set_second(pmp->sub.second, pmp->index, pmp->sub.matched, pmp->index == 0);
1301 #ifdef BOOST_REGEX_MATCH_EXTRA
1303 // we have a match, push the capture information onto the stack:
1305 else if(pmp->sub.matched && (match_extra & m_match_flags))
1306 ((*m_presult)[pmp->index]).get_captures().push_back(pmp->sub);
1309 m_backup_state = pmp+1;
1310 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp);
1311 return true; // keep looking
1314 template <class BidiIterator, class Allocator, class traits>
1315 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper(bool)
1317 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1318 pstate = 0; // nothing left to search
1319 return false; // end of stack nothing more to search
1322 template <class BidiIterator, class Allocator, class traits>
1323 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion(bool r)
1325 saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
1326 pstate = pmp->pstate;
1327 position = pmp->position;
1328 bool result = (r == pmp->positive);
1329 m_recursive_result = pmp->positive ? r : !r;
1330 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1331 m_backup_state = pmp;
1332 m_unwound_lookahead = true;
1333 return !result; // return false if the assertion was matched to stop search.
1336 template <class BidiIterator, class Allocator, class traits>
1337 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_alt(bool r)
1339 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1342 pstate = pmp->pstate;
1343 position = pmp->position;
1345 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1346 m_backup_state = pmp;
1351 template <class BidiIterator, class Allocator, class traits>
1352 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter(bool)
1354 saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
1355 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1356 m_backup_state = pmp;
1357 return true; // keep looking
1360 template <class BidiIterator, class Allocator, class traits>
1361 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block(bool)
1363 saved_extra_block* pmp = static_cast<saved_extra_block*>(m_backup_state);
1364 void* condemmed = m_stack_base;
1365 m_stack_base = pmp->base;
1366 m_backup_state = pmp->end;
1367 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp);
1368 put_mem_block(condemmed);
1369 return true; // keep looking
1372 template <class BidiIterator, class Allocator, class traits>
1373 inline void perl_matcher<BidiIterator, Allocator, traits>::destroy_single_repeat()
1375 saved_single_repeat<BidiIterator>* p = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1376 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(p++);
1380 template <class BidiIterator, class Allocator, class traits>
1381 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat(bool r)
1383 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1385 // if we have a match, just discard this state:
1388 destroy_single_repeat();
1392 const re_repeat* rep = pmp->rep;
1393 std::size_t count = pmp->count;
1394 BOOST_ASSERT(rep->next.p != 0);
1395 BOOST_ASSERT(rep->alt.p != 0);
1399 if((m_match_flags & match_partial) && (position == last))
1400 m_has_partial_match = true;
1402 BOOST_ASSERT(count);
1403 position = pmp->last_position;
1405 // backtrack till we can skip out:
1411 }while(count && !can_start(*position, rep->_map, mask_skip));
1413 // if we've hit base, destroy this state:
1416 destroy_single_repeat();
1417 if(!can_start(*position, rep->_map, mask_skip))
1422 pmp->count = count + rep->min;
1423 pmp->last_position = position;
1425 pstate = rep->alt.p;
1429 template <class BidiIterator, class Allocator, class traits>
1430 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat(bool r)
1432 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1434 // if we have a match, just discard this state:
1437 destroy_single_repeat();
1441 const re_repeat* rep = pmp->rep;
1442 std::size_t count = pmp->count;
1443 BOOST_ASSERT(rep->type == syntax_element_dot_rep);
1444 BOOST_ASSERT(rep->next.p != 0);
1445 BOOST_ASSERT(rep->alt.p != 0);
1446 BOOST_ASSERT(rep->next.p->type == syntax_element_wild);
1448 BOOST_ASSERT(count < rep->max);
1449 pstate = rep->next.p;
1450 position = pmp->last_position;
1452 if(position != last)
1454 // wind forward until we can skip out of the repeat:
1459 // failed repeat match, discard this state and look for another:
1460 destroy_single_repeat();
1465 pstate = rep->next.p;
1466 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1468 if(position == last)
1470 // can't repeat any more, remove the pushed state:
1471 destroy_single_repeat();
1472 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1473 m_has_partial_match = true;
1474 if(0 == (rep->can_be_null & mask_skip))
1477 else if(count == rep->max)
1479 // can't repeat any more, remove the pushed state:
1480 destroy_single_repeat();
1481 if(!can_start(*position, rep->_map, mask_skip))
1487 pmp->last_position = position;
1489 pstate = rep->alt.p;
1493 template <class BidiIterator, class Allocator, class traits>
1494 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat(bool r)
1496 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1498 // if we have a match, just discard this state:
1501 destroy_single_repeat();
1505 const re_repeat* rep = pmp->rep;
1506 std::size_t count = pmp->count;
1508 BOOST_ASSERT(count < rep->max);
1509 position = pmp->last_position;
1510 if(position != last)
1513 // wind forward until we can skip out of the repeat:
1519 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1522 // remember where we got to if this is a leading repeat:
1523 if((rep->leading) && (count < rep->max))
1525 if(position == last)
1527 // can't repeat any more, remove the pushed state:
1528 destroy_single_repeat();
1529 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1530 m_has_partial_match = true;
1531 if(0 == (rep->can_be_null & mask_skip))
1534 else if(count == rep->max)
1536 // can't repeat any more, remove the pushed state:
1537 destroy_single_repeat();
1538 if(!can_start(*position, rep->_map, mask_skip))
1544 pmp->last_position = position;
1546 pstate = rep->alt.p;
1550 template <class BidiIterator, class Allocator, class traits>
1551 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat(bool r)
1553 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1555 // if we have a match, just discard this state:
1558 destroy_single_repeat();
1562 const re_repeat* rep = pmp->rep;
1563 std::size_t count = pmp->count;
1564 pstate = rep->next.p;
1565 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1);
1566 position = pmp->last_position;
1568 BOOST_ASSERT(rep->type == syntax_element_char_rep);
1569 BOOST_ASSERT(rep->next.p != 0);
1570 BOOST_ASSERT(rep->alt.p != 0);
1571 BOOST_ASSERT(rep->next.p->type == syntax_element_literal);
1572 BOOST_ASSERT(count < rep->max);
1574 if(position != last)
1576 // wind forward until we can skip out of the repeat:
1579 if(traits_inst.translate(*position, icase) != what)
1581 // failed repeat match, discard this state and look for another:
1582 destroy_single_repeat();
1588 pstate = rep->next.p;
1589 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1591 // remember where we got to if this is a leading repeat:
1592 if((rep->leading) && (count < rep->max))
1594 if(position == last)
1596 // can't repeat any more, remove the pushed state:
1597 destroy_single_repeat();
1598 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1599 m_has_partial_match = true;
1600 if(0 == (rep->can_be_null & mask_skip))
1603 else if(count == rep->max)
1605 // can't repeat any more, remove the pushed state:
1606 destroy_single_repeat();
1607 if(!can_start(*position, rep->_map, mask_skip))
1613 pmp->last_position = position;
1615 pstate = rep->alt.p;
1619 template <class BidiIterator, class Allocator, class traits>
1620 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat(bool r)
1622 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1624 // if we have a match, just discard this state:
1627 destroy_single_repeat();
1631 const re_repeat* rep = pmp->rep;
1632 std::size_t count = pmp->count;
1633 pstate = rep->next.p;
1634 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
1635 position = pmp->last_position;
1637 BOOST_ASSERT(rep->type == syntax_element_short_set_rep);
1638 BOOST_ASSERT(rep->next.p != 0);
1639 BOOST_ASSERT(rep->alt.p != 0);
1640 BOOST_ASSERT(rep->next.p->type == syntax_element_set);
1641 BOOST_ASSERT(count < rep->max);
1643 if(position != last)
1645 // wind forward until we can skip out of the repeat:
1648 if(!map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
1650 // failed repeat match, discard this state and look for another:
1651 destroy_single_repeat();
1657 pstate = rep->next.p;
1658 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1660 // remember where we got to if this is a leading repeat:
1661 if((rep->leading) && (count < rep->max))
1663 if(position == last)
1665 // can't repeat any more, remove the pushed state:
1666 destroy_single_repeat();
1667 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1668 m_has_partial_match = true;
1669 if(0 == (rep->can_be_null & mask_skip))
1672 else if(count == rep->max)
1674 // can't repeat any more, remove the pushed state:
1675 destroy_single_repeat();
1676 if(!can_start(*position, rep->_map, mask_skip))
1682 pmp->last_position = position;
1684 pstate = rep->alt.p;
1688 template <class BidiIterator, class Allocator, class traits>
1689 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat(bool r)
1691 typedef typename traits::char_class_type m_type;
1692 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1694 // if we have a match, just discard this state:
1697 destroy_single_repeat();
1701 const re_repeat* rep = pmp->rep;
1702 std::size_t count = pmp->count;
1703 pstate = rep->next.p;
1704 const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate);
1705 position = pmp->last_position;
1707 BOOST_ASSERT(rep->type == syntax_element_long_set_rep);
1708 BOOST_ASSERT(rep->next.p != 0);
1709 BOOST_ASSERT(rep->alt.p != 0);
1710 BOOST_ASSERT(rep->next.p->type == syntax_element_long_set);
1711 BOOST_ASSERT(count < rep->max);
1713 if(position != last)
1715 // wind forward until we can skip out of the repeat:
1718 if(position == re_is_set_member(position, last, set, re.get_data(), icase))
1720 // failed repeat match, discard this state and look for another:
1721 destroy_single_repeat();
1727 pstate = rep->next.p;
1728 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1730 // remember where we got to if this is a leading repeat:
1731 if((rep->leading) && (count < rep->max))
1733 if(position == last)
1735 // can't repeat any more, remove the pushed state:
1736 destroy_single_repeat();
1737 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1738 m_has_partial_match = true;
1739 if(0 == (rep->can_be_null & mask_skip))
1742 else if(count == rep->max)
1744 // can't repeat any more, remove the pushed state:
1745 destroy_single_repeat();
1746 if(!can_start(*position, rep->_map, mask_skip))
1752 pmp->last_position = position;
1754 pstate = rep->alt.p;
1758 template <class BidiIterator, class Allocator, class traits>
1759 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat(bool r)
1761 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1764 position = pmp->position;
1765 pstate = pmp->pstate;
1768 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1769 m_backup_state = pmp;
1773 template <class BidiIterator, class Allocator, class traits>
1774 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion(bool r)
1776 // We are backtracking back inside a recursion, need to push the info
1777 // back onto the recursion stack, and do so unconditionally, otherwise
1778 // we can get mismatched pushes and pops...
1779 saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
1782 recursion_stack.push_back(recursion_info<results_type>());
1783 recursion_stack.back().idx = pmp->recursion_id;
1784 recursion_stack.back().preturn_address = pmp->preturn_address;
1785 recursion_stack.back().results = pmp->prior_results;
1786 recursion_stack.back().location_of_start = position;
1787 *m_presult = pmp->internal_results;
1789 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1790 m_backup_state = pmp;
1794 template <class BidiIterator, class Allocator, class traits>
1795 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop(bool r)
1797 // Backtracking out of a recursion, we must pop state off the recursion
1798 // stack unconditionally to ensure matched pushes and pops:
1799 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1802 *m_presult = recursion_stack.back().results;
1803 position = recursion_stack.back().location_of_start;
1804 recursion_stack.pop_back();
1806 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1807 m_backup_state = pmp;
1811 template <class BidiIterator, class Allocator, class traits>
1812 void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_pop()
1814 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1816 if(pmp < m_stack_base)
1819 pmp = static_cast<saved_state*>(m_backup_state);
1822 (void) new (pmp)saved_state(15);
1823 m_backup_state = pmp;
1826 template <class BidiIterator, class Allocator, class traits>
1827 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_commit(bool b)
1829 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1830 while(unwind(b) && !m_unwound_lookahead){}
1831 if(m_unwound_lookahead && pstate)
1834 // If we stop because we just unwound an assertion, put the
1835 // commit state back on the stack again:
1837 saved_state* pmp = m_backup_state;
1839 if(pmp < m_stack_base)
1842 pmp = m_backup_state;
1845 (void) new (pmp)saved_state(16);
1846 m_backup_state = pmp;
1848 // This prevents us from stopping when we exit from an independent sub-expression:
1849 m_independent = false;
1853 template <class BidiIterator, class Allocator, class traits>
1854 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_then(bool b)
1856 // Unwind everything till we hit an alternative:
1857 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1858 bool result = false;
1859 while((result = unwind(b)) && !m_unwound_alt){}
1860 // We're now pointing at the next alternative, need one more backtrack
1861 // since *all* the other alternatives must fail once we've reached a THEN clause:
1862 if(result && m_unwound_alt)
1868 template <class BidiIterator, class Allocator, class traits>
1869 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_pop(bool r)
1871 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1874 --parenthesis_stack_position;
1876 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1877 m_backup_state = pmp;
1881 template <class BidiIterator, class Allocator, class traits>
1882 void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_pop()
1884 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1886 if(pmp < m_stack_base)
1889 pmp = static_cast<saved_state*>(m_backup_state);
1892 (void) new (pmp)saved_state(16);
1893 m_backup_state = pmp;
1896 template <class BidiIterator, class Allocator, class traits>
1897 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_push(bool r)
1899 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1902 parenthesis_stack[parenthesis_stack_position++] = pmp->position;
1904 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1905 m_backup_state = pmp;
1909 template <class BidiIterator, class Allocator, class traits>
1910 inline void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_push(BidiIterator p)
1912 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1914 if(pmp < m_stack_base)
1917 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1920 (void) new (pmp)saved_position<BidiIterator>(0, p, 17);
1921 m_backup_state = pmp;
1924 } // namespace BOOST_REGEX_DETAIL_NS
1925 } // namespace boost
1928 # pragma warning(pop)
1932 #pragma warning(push)
1933 #pragma warning(disable: 4103)
1935 #ifdef BOOST_HAS_ABI_HEADERS
1936 # include BOOST_ABI_SUFFIX
1939 #pragma warning(pop)