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 recursive implementation.
20 #ifndef BOOST_REGEX_V4_PERL_MATCHER_RECURSIVE_HPP
21 #define BOOST_REGEX_V4_PERL_MATCHER_RECURSIVE_HPP
25 #pragma warning(disable: 4103)
27 #ifdef BOOST_HAS_ABI_HEADERS
28 # include BOOST_ABI_PREFIX
36 #pragma warning(disable: 4800)
40 namespace BOOST_REGEX_DETAIL_NS{
42 template <class BidiIterator>
46 sub_match<BidiIterator> sub;
49 backup_subex(const match_results<BidiIterator, A>& w, int i)
50 : index(i), sub(w[i], false) {}
52 void restore(match_results<BidiIterator, A>& w)
54 w.set_first(sub.first, index, index == 0);
55 w.set_second(sub.second, index, sub.matched, index == 0);
57 const sub_match<BidiIterator>& get() { return sub; }
60 template <class BidiIterator, class Allocator, class traits>
61 bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
63 static matcher_proc_type const s_match_vtable[34] =
65 (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
66 &perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
67 &perl_matcher<BidiIterator, Allocator, traits>::match_literal,
68 &perl_matcher<BidiIterator, Allocator, traits>::match_start_line,
69 &perl_matcher<BidiIterator, Allocator, traits>::match_end_line,
70 &perl_matcher<BidiIterator, Allocator, traits>::match_wild,
71 &perl_matcher<BidiIterator, Allocator, traits>::match_match,
72 &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary,
73 &perl_matcher<BidiIterator, Allocator, traits>::match_within_word,
74 &perl_matcher<BidiIterator, Allocator, traits>::match_word_start,
75 &perl_matcher<BidiIterator, Allocator, traits>::match_word_end,
76 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start,
77 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end,
78 &perl_matcher<BidiIterator, Allocator, traits>::match_backref,
79 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set,
80 &perl_matcher<BidiIterator, Allocator, traits>::match_set,
81 &perl_matcher<BidiIterator, Allocator, traits>::match_jump,
82 &perl_matcher<BidiIterator, Allocator, traits>::match_alt,
83 &perl_matcher<BidiIterator, Allocator, traits>::match_rep,
84 &perl_matcher<BidiIterator, Allocator, traits>::match_combining,
85 &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end,
86 &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue,
87 // Although this next line *should* be evaluated at compile time, in practice
88 // some compilers (VC++) emit run-time initialisation which breaks thread
89 // safety, so use a dispatch function instead:
90 //(::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),
91 &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch,
92 &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat,
93 &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
94 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
95 &perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
96 &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
97 &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
98 &perl_matcher<BidiIterator, Allocator, traits>::match_recursion,
99 &perl_matcher<BidiIterator, Allocator, traits>::match_fail,
100 &perl_matcher<BidiIterator, Allocator, traits>::match_accept,
101 &perl_matcher<BidiIterator, Allocator, traits>::match_commit,
102 &perl_matcher<BidiIterator, Allocator, traits>::match_then,
105 if(state_count > max_state_count)
106 raise_error(traits_inst, regex_constants::error_complexity);
109 matcher_proc_type proc = s_match_vtable[pstate->type];
113 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
114 m_has_partial_match = true;
121 template <class BidiIterator, class Allocator, class traits>
122 bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
124 int index = static_cast<const re_brace*>(pstate)->index;
125 icase = static_cast<const re_brace*>(pstate)->icase;
130 pstate = pstate->next.p;
135 // forward lookahead assert:
136 BidiIterator old_position(position);
137 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
138 pstate = pstate->next.p->next.p;
139 r = match_all_states();
140 pstate = next_pstate;
141 position = old_position;
142 if((r && (index != -1)) || (!r && (index != -2)))
146 if(r && m_have_accept)
147 r = skip_until_paren(INT_MAX);
152 // independent sub-expression:
153 bool old_independent = m_independent;
154 m_independent = true;
155 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
156 pstate = pstate->next.p->next.p;
157 bool can_backtrack = m_can_backtrack;
158 r = match_all_states();
160 m_can_backtrack = can_backtrack;
161 pstate = next_pstate;
162 m_independent = old_independent;
163 #ifdef BOOST_REGEX_MATCH_EXTRA
164 if(r && (m_match_flags & match_extra))
167 // our captures have been stored in *m_presult
168 // we need to unpack them, and insert them
169 // back in the right order when we unwind the stack:
172 match_results<BidiIterator, Allocator> tm(*m_presult);
173 for(i = 0; i < tm.size(); ++i)
174 (*m_presult)[i].get_captures().clear();
175 // match everything else:
176 r = match_all_states();
177 // now place the stored captures back:
178 for(i = 0; i < tm.size(); ++i)
180 typedef typename sub_match<BidiIterator>::capture_sequence_type seq;
181 seq& s1 = (*m_presult)[i].get_captures();
182 const seq& s2 = tm[i].captures();
190 if(r && m_have_accept)
191 r = skip_until_paren(INT_MAX);
196 // conditional expression:
197 const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
198 BOOST_ASSERT(alt->type == syntax_element_alt);
199 pstate = alt->next.p;
200 if(pstate->type == syntax_element_assert_backref)
202 if(!match_assert_backref())
208 // zero width assertion, have to match this recursively:
209 BOOST_ASSERT(pstate->type == syntax_element_startmark);
210 bool negated = static_cast<const re_brace*>(pstate)->index == -2;
211 BidiIterator saved_position = position;
212 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
213 pstate = pstate->next.p->next.p;
214 bool res = match_all_states();
215 position = saved_position;
219 pstate = next_pstate;
227 // Reset start of $0, since we have a \K escape
228 backup_subex<BidiIterator> sub(*m_presult, 0);
229 m_presult->set_first(position, 0, true);
230 pstate = pstate->next.p;
231 r = match_all_states();
233 sub.restore(*m_presult);
238 BOOST_ASSERT(index > 0);
239 if((m_match_flags & match_nosubs) == 0)
241 backup_subex<BidiIterator> sub(*m_presult, index);
242 m_presult->set_first(position, index);
243 pstate = pstate->next.p;
244 r = match_all_states();
246 sub.restore(*m_presult);
247 #ifdef BOOST_REGEX_MATCH_EXTRA
249 // we have a match, push the capture information onto the stack:
251 else if(sub.get().matched && (match_extra & m_match_flags))
252 ((*m_presult)[index]).get_captures().push_back(sub.get());
257 pstate = pstate->next.p;
265 template <class BidiIterator, class Allocator, class traits>
266 bool perl_matcher<BidiIterator, Allocator, traits>::match_alt()
268 bool take_first, take_second;
269 const re_alt* jmp = static_cast<const re_alt*>(pstate);
271 // find out which of these two alternatives we need to take:
274 take_first = jmp->can_be_null & mask_take;
275 take_second = jmp->can_be_null & mask_skip;
279 take_first = can_start(*position, jmp->_map, (unsigned char)mask_take);
280 take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip);
285 // we can take the first alternative,
286 // see if we need to push next alternative:
289 BidiIterator oldposition(position);
290 const re_syntax_base* old_pstate = jmp->alt.p;
291 pstate = pstate->next.p;
292 bool oldcase = icase;
294 if(!match_all_states())
297 position = oldposition;
301 m_can_backtrack = true;
307 return m_can_backtrack;
309 pstate = pstate->next.p;
317 return false; // neither option is possible
320 template <class BidiIterator, class Allocator, class traits>
321 bool perl_matcher<BidiIterator, Allocator, traits>::match_rep()
324 #pragma warning(push)
325 #pragma warning(disable:4127 4244)
327 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
329 // Always copy the repeat count, so that the state is restored
330 // when we exit this scope:
332 repeater_count<BidiIterator> r(rep->state_id, &next_count, position, this->recursion_stack.size() ? this->recursion_stack.back().idx : INT_MIN + 3);
334 // If we've had at least one repeat already, and the last one
335 // matched the NULL string then set the repeat count to
338 next_count->check_null_repeat(position, rep->max);
340 // find out which of these two alternatives we need to take:
341 bool take_first, take_second;
344 take_first = rep->can_be_null & mask_take;
345 take_second = rep->can_be_null & mask_skip;
349 take_first = can_start(*position, rep->_map, (unsigned char)mask_take);
350 take_second = can_start(*position, rep->_map, (unsigned char)mask_skip);
353 if(next_count->get_count() < rep->min)
355 // we must take the repeat:
358 // increase the counter:
360 pstate = rep->next.p;
361 return match_all_states();
365 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
368 // try and take the repeat if we can:
369 if((next_count->get_count() < rep->max) && take_first)
371 // store position in case we fail:
372 BidiIterator pos = position;
373 // increase the counter:
375 pstate = rep->next.p;
376 if(match_all_states())
380 // failed repeat, reset posistion and fall through for alternative:
388 return false; // can't take anything, fail...
392 // try and skip the repeat if we can:
395 // store position in case we fail:
396 BidiIterator pos = position;
398 if(match_all_states())
402 // failed alternative, reset posistion and fall through for repeat:
405 if((next_count->get_count() < rep->max) && take_first)
407 // increase the counter:
409 pstate = rep->next.p;
410 return match_all_states();
419 template <class BidiIterator, class Allocator, class traits>
420 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
423 #pragma warning(push)
424 #pragma warning(disable:4127)
427 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
428 re_syntax_base* psingle = rep->next.p;
429 // match compulsary repeats first:
430 while(count < rep->min)
437 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
441 while(count < rep->max)
448 if((rep->leading) && (count < rep->max))
451 return backtrack_till_match(count - rep->min);
455 // non-greedy, keep trying till we get a match:
456 BidiIterator save_pos;
459 if((rep->leading) && (rep->max == UINT_MAX))
464 if(match_all_states())
466 if((count >= rep->max) || !m_can_backtrack)
480 template <class BidiIterator, class Allocator, class traits>
481 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
484 #pragma warning(push)
485 #pragma warning(disable:4127)
487 if(m_match_flags & match_not_dot_null)
488 return match_dot_repeat_slow();
489 if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
490 return match_dot_repeat_slow();
492 // start by working out how much we can skip:
494 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
496 #pragma warning(push)
497 #pragma warning(disable:4267)
499 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
500 std::size_t count = (std::min)(static_cast<std::size_t>(::boost::BOOST_REGEX_DETAIL_NS::distance(position, last)), static_cast<std::size_t>(greedy ? rep->max : rep->min));
504 return false; // not enough text left to match
506 std::advance(position, count);
510 if((rep->leading) && (count < rep->max) && greedy)
513 return backtrack_till_match(count - rep->min);
515 // non-greedy, keep trying till we get a match:
516 BidiIterator save_pos;
519 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
524 if((rep->leading) && (rep->max == UINT_MAX))
529 if(match_all_states())
531 if((count >= rep->max) || !m_can_backtrack)
535 position = ++save_pos;
543 template <class BidiIterator, class Allocator, class traits>
544 bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
547 #pragma warning(push)
548 #pragma warning(disable:4127)
549 #pragma warning(disable:4267)
552 #pragma option push -w-8008 -w-8066 -w-8004
554 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
555 BOOST_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length);
556 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
558 // start by working out how much we can skip:
560 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
561 std::size_t count, desired;
562 if(::boost::is_random_access_iterator<BidiIterator>::value)
566 (std::size_t)(greedy ? rep->max : rep->min),
567 (std::size_t)::boost::BOOST_REGEX_DETAIL_NS::distance(position, last));
572 while(--desired && (traits_inst.translate_nocase(*position) == what))
579 while(--desired && (traits_inst.translate(*position) == what))
584 count = count - desired;
589 desired = greedy ? rep->max : rep->min;
590 while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what))
596 if((rep->leading) && (count < rep->max) && greedy)
602 return backtrack_till_match(count - rep->min);
604 // non-greedy, keep trying till we get a match:
605 BidiIterator save_pos;
608 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
610 if((traits_inst.translate(*position, icase) == what))
616 return false; // counldn't repeat even though it was the only option
618 if((rep->leading) && (rep->max == UINT_MAX))
623 if(match_all_states())
625 if((count >= rep->max) || !m_can_backtrack)
630 if(traits_inst.translate(*position, icase) == what)
648 template <class BidiIterator, class Allocator, class traits>
649 bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
652 #pragma warning(push)
653 #pragma warning(disable:4127)
656 #pragma option push -w-8008 -w-8066 -w-8004
658 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
659 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
662 // start by working out how much we can skip:
664 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
665 std::size_t desired = greedy ? rep->max : rep->min;
666 if(::boost::is_random_access_iterator<BidiIterator>::value)
668 BidiIterator end = position;
669 // Move end forward by "desired", preferably without using distance or advance if we can
670 // as these can be slow for some iterator types.
671 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
675 std::advance(end, desired);
676 BidiIterator origin(position);
677 while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
681 count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
685 while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
691 if((rep->leading) && (count < rep->max) && greedy)
697 return backtrack_till_match(count - rep->min);
699 // non-greedy, keep trying till we get a match:
700 BidiIterator save_pos;
703 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
705 if(map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
711 return false; // counldn't repeat even though it was the only option
713 if((rep->leading) && (rep->max == UINT_MAX))
718 if(match_all_states())
720 if((count >= rep->max) || !m_can_backtrack)
725 if(map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
743 template <class BidiIterator, class Allocator, class traits>
744 bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
747 #pragma warning(push)
748 #pragma warning(disable:4127)
751 #pragma option push -w-8008 -w-8066 -w-8004
753 typedef typename traits::char_class_type char_class_type;
754 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
755 const re_set_long<char_class_type>* set = static_cast<const re_set_long<char_class_type>*>(pstate->next.p);
758 // start by working out how much we can skip:
760 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
761 std::size_t desired = greedy ? rep->max : rep->min;
762 if(::boost::is_random_access_iterator<BidiIterator>::value)
764 BidiIterator end = position;
765 // Move end forward by "desired", preferably without using distance or advance if we can
766 // as these can be slow for some iterator types.
767 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
771 std::advance(end, desired);
772 BidiIterator origin(position);
773 while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
777 count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
781 while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
787 if((rep->leading) && (count < rep->max) && greedy)
793 return backtrack_till_match(count - rep->min);
795 // non-greedy, keep trying till we get a match:
796 BidiIterator save_pos;
799 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
801 if(position != re_is_set_member(position, last, set, re.get_data(), icase))
807 return false; // counldn't repeat even though it was the only option
809 if((rep->leading) && (rep->max == UINT_MAX))
814 if(match_all_states())
816 if((count >= rep->max) || !m_can_backtrack)
821 if(position != re_is_set_member(position, last, set, re.get_data(), icase))
839 template <class BidiIterator, class Allocator, class traits>
840 bool perl_matcher<BidiIterator, Allocator, traits>::backtrack_till_match(std::size_t count)
843 #pragma warning(push)
844 #pragma warning(disable:4127)
848 if((m_match_flags & match_partial) && (position == last))
849 m_has_partial_match = true;
851 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
852 BidiIterator backtrack = position;
855 if(rep->can_be_null & mask_skip)
858 if(match_all_states())
863 position = --backtrack;
871 while(count && !can_start(*position, rep->_map, mask_skip))
878 backtrack = position;
879 if(match_all_states())
883 position = --backtrack;
892 template <class BidiIterator, class Allocator, class traits>
893 bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
895 BOOST_ASSERT(pstate->type == syntax_element_recurse);
897 // Set new call stack:
899 if(recursion_stack.capacity() == 0)
901 recursion_stack.reserve(50);
903 recursion_stack.push_back(recursion_info<results_type>());
904 recursion_stack.back().preturn_address = pstate->next.p;
905 recursion_stack.back().results = *m_presult;
906 recursion_stack.back().repeater_stack = next_count;
907 pstate = static_cast<const re_jump*>(pstate)->alt.p;
908 recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
910 repeater_count<BidiIterator>* saved = next_count;
911 repeater_count<BidiIterator> r(&next_count); // resets all repeat counts since we're recursing and starting fresh on those
913 bool can_backtrack = m_can_backtrack;
914 bool result = match_all_states();
915 m_can_backtrack = can_backtrack;
920 next_count = recursion_stack.back().repeater_stack;
921 *m_presult = recursion_stack.back().results;
922 recursion_stack.pop_back();
928 template <class BidiIterator, class Allocator, class traits>
929 bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
931 int index = static_cast<const re_brace*>(pstate)->index;
932 icase = static_cast<const re_brace*>(pstate)->icase;
935 if((m_match_flags & match_nosubs) == 0)
937 m_presult->set_second(position, index);
939 if(!recursion_stack.empty())
941 if(index == recursion_stack.back().idx)
943 recursion_info<results_type> saved = recursion_stack.back();
944 recursion_stack.pop_back();
945 pstate = saved.preturn_address;
946 repeater_count<BidiIterator>* saved_count = next_count;
947 next_count = saved.repeater_stack;
948 *m_presult = saved.results;
949 if(!match_all_states())
951 recursion_stack.push_back(saved);
952 next_count = saved_count;
958 else if((index < 0) && (index != -4))
960 // matched forward lookahead:
964 pstate = pstate ? pstate->next.p : 0;
968 template <class BidiIterator, class Allocator, class traits>
969 bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
971 if(!recursion_stack.empty())
973 BOOST_ASSERT(0 == recursion_stack.back().idx);
974 const re_syntax_base* saved_state = pstate = recursion_stack.back().preturn_address;
975 *m_presult = recursion_stack.back().results;
976 recursion_stack.pop_back();
977 if(!match_all_states())
979 recursion_stack.push_back(recursion_info<results_type>());
980 recursion_stack.back().preturn_address = saved_state;
981 recursion_stack.back().results = *m_presult;
986 if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
988 if((m_match_flags & match_all) && (position != last))
990 if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base))
992 m_presult->set_second(position);
994 m_has_found_match = true;
995 if((m_match_flags & match_posix) == match_posix)
997 m_result.maybe_assign(*m_presult);
998 if((m_match_flags & match_any) == 0)
1001 #ifdef BOOST_REGEX_MATCH_EXTRA
1002 if(match_extra & m_match_flags)
1004 for(unsigned i = 0; i < m_presult->size(); ++i)
1005 if((*m_presult)[i].matched)
1006 ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]);
1012 template <class BidiIterator, class Allocator, class traits>
1013 bool perl_matcher<BidiIterator, Allocator, traits>::match_commit()
1015 m_can_backtrack = false;
1016 int action = static_cast<const re_commit*>(pstate)->action;
1026 pstate = pstate->next.p;
1030 template <class BidiIterator, class Allocator, class traits>
1031 bool perl_matcher<BidiIterator, Allocator, traits>::match_then()
1033 pstate = pstate->next.p;
1034 if(match_all_states())
1036 m_can_backtrack = false;
1041 template <class BidiIterator, class Allocator, class traits>
1042 bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
1044 // change our case sensitivity:
1045 bool oldcase = this->icase;
1046 this->icase = static_cast<const re_case*>(pstate)->icase;
1047 pstate = pstate->next.p;
1048 bool result = match_all_states();
1049 this->icase = oldcase;
1055 template <class BidiIterator, class Allocator, class traits>
1056 bool perl_matcher<BidiIterator, Allocator, traits>::skip_until_paren(int index, bool have_match)
1060 if(pstate->type == syntax_element_endmark)
1062 if(static_cast<const re_brace*>(pstate)->index == index)
1065 return this->match_endmark();
1066 pstate = pstate->next.p;
1071 // Unenclosed closing ), occurs when (*ACCEPT) is inside some other
1072 // parenthesis which may or may not have other side effects associated with it.
1073 bool r = match_endmark();
1074 m_have_accept = true;
1080 else if(pstate->type == syntax_element_match)
1082 else if(pstate->type == syntax_element_startmark)
1084 int idx = static_cast<const re_brace*>(pstate)->index;
1085 pstate = pstate->next.p;
1086 skip_until_paren(idx, false);
1089 pstate = pstate->next.p;
1095 } // namespace BOOST_REGEX_DETAIL_NS
1096 } // namespace boost
1098 #pragma warning(pop)
1102 #pragma warning(push)
1103 #pragma warning(disable: 4103)
1105 #ifdef BOOST_HAS_ABI_HEADERS
1106 # include BOOST_ABI_SUFFIX
1109 #pragma warning(pop)