annotate DEPENDENCIES/generic/include/boost/regex/v4/perl_matcher_non_recursive.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 /*
Chris@16 2 *
Chris@16 3 * Copyright (c) 2002
Chris@16 4 * John Maddock
Chris@16 5 *
Chris@16 6 * Use, modification and distribution are subject to the
Chris@16 7 * Boost Software License, Version 1.0. (See accompanying file
Chris@16 8 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9 *
Chris@16 10 */
Chris@16 11
Chris@16 12 /*
Chris@16 13 * LOCATION: see http://www.boost.org for most recent version.
Chris@16 14 * FILE perl_matcher_common.cpp
Chris@16 15 * VERSION see <boost/version.hpp>
Chris@16 16 * DESCRIPTION: Definitions of perl_matcher member functions that are
Chris@16 17 * specific to the non-recursive implementation.
Chris@16 18 */
Chris@16 19
Chris@16 20 #ifndef BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
Chris@16 21 #define BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
Chris@16 22
Chris@16 23 #include <new>
Chris@16 24
Chris@16 25 #ifdef BOOST_MSVC
Chris@16 26 #pragma warning(push)
Chris@16 27 #pragma warning(disable: 4103)
Chris@16 28 #endif
Chris@16 29 #ifdef BOOST_HAS_ABI_HEADERS
Chris@16 30 # include BOOST_ABI_PREFIX
Chris@16 31 #endif
Chris@16 32 #ifdef BOOST_MSVC
Chris@16 33 #pragma warning(pop)
Chris@16 34 #endif
Chris@16 35 #ifdef BOOST_MSVC
Chris@16 36 # pragma warning(push)
Chris@16 37 # pragma warning(disable: 4800)
Chris@16 38 #endif
Chris@16 39
Chris@16 40 namespace boost{
Chris@16 41 namespace re_detail{
Chris@16 42
Chris@16 43 template <class T>
Chris@16 44 inline void inplace_destroy(T* p)
Chris@16 45 {
Chris@16 46 (void)p; // warning suppression
Chris@16 47 p->~T();
Chris@16 48 }
Chris@16 49
Chris@16 50 struct saved_state
Chris@16 51 {
Chris@16 52 union{
Chris@16 53 unsigned int state_id;
Chris@16 54 // this padding ensures correct alignment on 64-bit platforms:
Chris@16 55 std::size_t padding1;
Chris@16 56 std::ptrdiff_t padding2;
Chris@16 57 void* padding3;
Chris@16 58 };
Chris@16 59 saved_state(unsigned i) : state_id(i) {}
Chris@16 60 };
Chris@16 61
Chris@16 62 template <class BidiIterator>
Chris@16 63 struct saved_matched_paren : public saved_state
Chris@16 64 {
Chris@16 65 int index;
Chris@16 66 sub_match<BidiIterator> sub;
Chris@16 67 saved_matched_paren(int i, const sub_match<BidiIterator>& s) : saved_state(1), index(i), sub(s){};
Chris@16 68 };
Chris@16 69
Chris@16 70 template <class BidiIterator>
Chris@16 71 struct saved_position : public saved_state
Chris@16 72 {
Chris@16 73 const re_syntax_base* pstate;
Chris@16 74 BidiIterator position;
Chris@16 75 saved_position(const re_syntax_base* ps, BidiIterator pos, int i) : saved_state(i), pstate(ps), position(pos){};
Chris@16 76 };
Chris@16 77
Chris@16 78 template <class BidiIterator>
Chris@16 79 struct saved_assertion : public saved_position<BidiIterator>
Chris@16 80 {
Chris@16 81 bool positive;
Chris@16 82 saved_assertion(bool p, const re_syntax_base* ps, BidiIterator pos)
Chris@16 83 : saved_position<BidiIterator>(ps, pos, saved_type_assertion), positive(p){};
Chris@16 84 };
Chris@16 85
Chris@16 86 template <class BidiIterator>
Chris@16 87 struct saved_repeater : public saved_state
Chris@16 88 {
Chris@16 89 repeater_count<BidiIterator> count;
Chris@16 90 saved_repeater(int i, repeater_count<BidiIterator>** s, BidiIterator start)
Chris@16 91 : saved_state(saved_state_repeater_count), count(i,s,start){}
Chris@16 92 };
Chris@16 93
Chris@16 94 struct saved_extra_block : public saved_state
Chris@16 95 {
Chris@16 96 saved_state *base, *end;
Chris@16 97 saved_extra_block(saved_state* b, saved_state* e)
Chris@16 98 : saved_state(saved_state_extra_block), base(b), end(e) {}
Chris@16 99 };
Chris@16 100
Chris@16 101 struct save_state_init
Chris@16 102 {
Chris@16 103 saved_state** stack;
Chris@16 104 save_state_init(saved_state** base, saved_state** end)
Chris@16 105 : stack(base)
Chris@16 106 {
Chris@16 107 *base = static_cast<saved_state*>(get_mem_block());
Chris@16 108 *end = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(*base)+BOOST_REGEX_BLOCKSIZE);
Chris@16 109 --(*end);
Chris@16 110 (void) new (*end)saved_state(0);
Chris@16 111 BOOST_ASSERT(*end > *base);
Chris@16 112 }
Chris@16 113 ~save_state_init()
Chris@16 114 {
Chris@16 115 put_mem_block(*stack);
Chris@16 116 *stack = 0;
Chris@16 117 }
Chris@16 118 };
Chris@16 119
Chris@16 120 template <class BidiIterator>
Chris@16 121 struct saved_single_repeat : public saved_state
Chris@16 122 {
Chris@16 123 std::size_t count;
Chris@16 124 const re_repeat* rep;
Chris@16 125 BidiIterator last_position;
Chris@16 126 saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id)
Chris@16 127 : saved_state(arg_id), count(c), rep(r), last_position(lp){}
Chris@16 128 };
Chris@16 129
Chris@16 130 template <class Results>
Chris@16 131 struct saved_recursion : public saved_state
Chris@16 132 {
Chris@16 133 saved_recursion(int idx, const re_syntax_base* p, Results* pr)
Chris@16 134 : saved_state(14), recursion_id(idx), preturn_address(p), results(*pr)
Chris@16 135 {}
Chris@16 136 int recursion_id;
Chris@16 137 const re_syntax_base* preturn_address;
Chris@16 138 Results results;
Chris@16 139 };
Chris@16 140
Chris@16 141 template <class BidiIterator, class Allocator, class traits>
Chris@16 142 bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
Chris@16 143 {
Chris@16 144 static matcher_proc_type const s_match_vtable[30] =
Chris@16 145 {
Chris@16 146 (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
Chris@16 147 &perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
Chris@16 148 &perl_matcher<BidiIterator, Allocator, traits>::match_literal,
Chris@16 149 &perl_matcher<BidiIterator, Allocator, traits>::match_start_line,
Chris@16 150 &perl_matcher<BidiIterator, Allocator, traits>::match_end_line,
Chris@16 151 &perl_matcher<BidiIterator, Allocator, traits>::match_wild,
Chris@16 152 &perl_matcher<BidiIterator, Allocator, traits>::match_match,
Chris@16 153 &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary,
Chris@16 154 &perl_matcher<BidiIterator, Allocator, traits>::match_within_word,
Chris@16 155 &perl_matcher<BidiIterator, Allocator, traits>::match_word_start,
Chris@16 156 &perl_matcher<BidiIterator, Allocator, traits>::match_word_end,
Chris@16 157 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start,
Chris@16 158 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end,
Chris@16 159 &perl_matcher<BidiIterator, Allocator, traits>::match_backref,
Chris@16 160 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set,
Chris@16 161 &perl_matcher<BidiIterator, Allocator, traits>::match_set,
Chris@16 162 &perl_matcher<BidiIterator, Allocator, traits>::match_jump,
Chris@16 163 &perl_matcher<BidiIterator, Allocator, traits>::match_alt,
Chris@16 164 &perl_matcher<BidiIterator, Allocator, traits>::match_rep,
Chris@16 165 &perl_matcher<BidiIterator, Allocator, traits>::match_combining,
Chris@16 166 &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end,
Chris@16 167 &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue,
Chris@16 168 // Although this next line *should* be evaluated at compile time, in practice
Chris@16 169 // some compilers (VC++) emit run-time initialisation which breaks thread
Chris@16 170 // safety, so use a dispatch function instead:
Chris@16 171 //(::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),
Chris@16 172 &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch,
Chris@16 173 &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat,
Chris@16 174 &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
Chris@16 175 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
Chris@16 176 &perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
Chris@16 177 &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
Chris@16 178 &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
Chris@16 179 &perl_matcher<BidiIterator, Allocator, traits>::match_recursion,
Chris@16 180 };
Chris@16 181
Chris@16 182 push_recursion_stopper();
Chris@16 183 do{
Chris@16 184 while(pstate)
Chris@16 185 {
Chris@16 186 matcher_proc_type proc = s_match_vtable[pstate->type];
Chris@16 187 ++state_count;
Chris@16 188 if(!(this->*proc)())
Chris@16 189 {
Chris@16 190 if(state_count > max_state_count)
Chris@16 191 raise_error(traits_inst, regex_constants::error_complexity);
Chris@16 192 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
Chris@16 193 m_has_partial_match = true;
Chris@16 194 bool successful_unwind = unwind(false);
Chris@16 195 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
Chris@16 196 m_has_partial_match = true;
Chris@16 197 if(false == successful_unwind)
Chris@16 198 return m_recursive_result;
Chris@16 199 }
Chris@16 200 }
Chris@16 201 }while(unwind(true));
Chris@16 202 return m_recursive_result;
Chris@16 203 }
Chris@16 204
Chris@16 205 template <class BidiIterator, class Allocator, class traits>
Chris@16 206 void perl_matcher<BidiIterator, Allocator, traits>::extend_stack()
Chris@16 207 {
Chris@16 208 if(used_block_count)
Chris@16 209 {
Chris@16 210 --used_block_count;
Chris@16 211 saved_state* stack_base;
Chris@16 212 saved_state* backup_state;
Chris@16 213 stack_base = static_cast<saved_state*>(get_mem_block());
Chris@16 214 backup_state = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(stack_base)+BOOST_REGEX_BLOCKSIZE);
Chris@16 215 saved_extra_block* block = static_cast<saved_extra_block*>(backup_state);
Chris@16 216 --block;
Chris@16 217 (void) new (block) saved_extra_block(m_stack_base, m_backup_state);
Chris@16 218 m_stack_base = stack_base;
Chris@16 219 m_backup_state = block;
Chris@16 220 }
Chris@16 221 else
Chris@16 222 raise_error(traits_inst, regex_constants::error_stack);
Chris@16 223 }
Chris@16 224
Chris@16 225 template <class BidiIterator, class Allocator, class traits>
Chris@16 226 inline void perl_matcher<BidiIterator, Allocator, traits>::push_matched_paren(int index, const sub_match<BidiIterator>& sub)
Chris@16 227 {
Chris@16 228 //BOOST_ASSERT(index);
Chris@16 229 saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
Chris@16 230 --pmp;
Chris@16 231 if(pmp < m_stack_base)
Chris@16 232 {
Chris@16 233 extend_stack();
Chris@16 234 pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
Chris@16 235 --pmp;
Chris@16 236 }
Chris@16 237 (void) new (pmp)saved_matched_paren<BidiIterator>(index, sub);
Chris@16 238 m_backup_state = pmp;
Chris@16 239 }
Chris@16 240
Chris@16 241 template <class BidiIterator, class Allocator, class traits>
Chris@16 242 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_stopper()
Chris@16 243 {
Chris@16 244 saved_state* pmp = m_backup_state;
Chris@16 245 --pmp;
Chris@16 246 if(pmp < m_stack_base)
Chris@16 247 {
Chris@16 248 extend_stack();
Chris@16 249 pmp = m_backup_state;
Chris@16 250 --pmp;
Chris@16 251 }
Chris@16 252 (void) new (pmp)saved_state(saved_type_recurse);
Chris@16 253 m_backup_state = pmp;
Chris@16 254 }
Chris@16 255
Chris@16 256 template <class BidiIterator, class Allocator, class traits>
Chris@16 257 inline void perl_matcher<BidiIterator, Allocator, traits>::push_assertion(const re_syntax_base* ps, bool positive)
Chris@16 258 {
Chris@16 259 saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
Chris@16 260 --pmp;
Chris@16 261 if(pmp < m_stack_base)
Chris@16 262 {
Chris@16 263 extend_stack();
Chris@16 264 pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
Chris@16 265 --pmp;
Chris@16 266 }
Chris@16 267 (void) new (pmp)saved_assertion<BidiIterator>(positive, ps, position);
Chris@16 268 m_backup_state = pmp;
Chris@16 269 }
Chris@16 270
Chris@16 271 template <class BidiIterator, class Allocator, class traits>
Chris@16 272 inline void perl_matcher<BidiIterator, Allocator, traits>::push_alt(const re_syntax_base* ps)
Chris@16 273 {
Chris@16 274 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
Chris@16 275 --pmp;
Chris@16 276 if(pmp < m_stack_base)
Chris@16 277 {
Chris@16 278 extend_stack();
Chris@16 279 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
Chris@16 280 --pmp;
Chris@16 281 }
Chris@16 282 (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_alt);
Chris@16 283 m_backup_state = pmp;
Chris@16 284 }
Chris@16 285
Chris@16 286 template <class BidiIterator, class Allocator, class traits>
Chris@16 287 inline void perl_matcher<BidiIterator, Allocator, traits>::push_non_greedy_repeat(const re_syntax_base* ps)
Chris@16 288 {
Chris@16 289 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
Chris@16 290 --pmp;
Chris@16 291 if(pmp < m_stack_base)
Chris@16 292 {
Chris@16 293 extend_stack();
Chris@16 294 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
Chris@16 295 --pmp;
Chris@16 296 }
Chris@16 297 (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_non_greedy_long_repeat);
Chris@16 298 m_backup_state = pmp;
Chris@16 299 }
Chris@16 300
Chris@16 301 template <class BidiIterator, class Allocator, class traits>
Chris@16 302 inline void perl_matcher<BidiIterator, Allocator, traits>::push_repeater_count(int i, repeater_count<BidiIterator>** s)
Chris@16 303 {
Chris@16 304 saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
Chris@16 305 --pmp;
Chris@16 306 if(pmp < m_stack_base)
Chris@16 307 {
Chris@16 308 extend_stack();
Chris@16 309 pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
Chris@16 310 --pmp;
Chris@16 311 }
Chris@16 312 (void) new (pmp)saved_repeater<BidiIterator>(i, s, position);
Chris@16 313 m_backup_state = pmp;
Chris@16 314 }
Chris@16 315
Chris@16 316 template <class BidiIterator, class Allocator, class traits>
Chris@16 317 inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id)
Chris@16 318 {
Chris@16 319 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
Chris@16 320 --pmp;
Chris@16 321 if(pmp < m_stack_base)
Chris@16 322 {
Chris@16 323 extend_stack();
Chris@16 324 pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
Chris@16 325 --pmp;
Chris@16 326 }
Chris@16 327 (void) new (pmp)saved_single_repeat<BidiIterator>(c, r, last_position, state_id);
Chris@16 328 m_backup_state = pmp;
Chris@16 329 }
Chris@16 330
Chris@16 331 template <class BidiIterator, class Allocator, class traits>
Chris@16 332 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion(int idx, const re_syntax_base* p, results_type* presults)
Chris@16 333 {
Chris@16 334 saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
Chris@16 335 --pmp;
Chris@16 336 if(pmp < m_stack_base)
Chris@16 337 {
Chris@16 338 extend_stack();
Chris@16 339 pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
Chris@16 340 --pmp;
Chris@16 341 }
Chris@16 342 (void) new (pmp)saved_recursion<results_type>(idx, p, presults);
Chris@16 343 m_backup_state = pmp;
Chris@16 344 }
Chris@16 345
Chris@16 346 template <class BidiIterator, class Allocator, class traits>
Chris@16 347 bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
Chris@16 348 {
Chris@16 349 int index = static_cast<const re_brace*>(pstate)->index;
Chris@16 350 icase = static_cast<const re_brace*>(pstate)->icase;
Chris@16 351 switch(index)
Chris@16 352 {
Chris@16 353 case 0:
Chris@16 354 pstate = pstate->next.p;
Chris@16 355 break;
Chris@16 356 case -1:
Chris@16 357 case -2:
Chris@16 358 {
Chris@16 359 // forward lookahead assert:
Chris@16 360 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
Chris@16 361 pstate = pstate->next.p->next.p;
Chris@16 362 push_assertion(next_pstate, index == -1);
Chris@16 363 break;
Chris@16 364 }
Chris@16 365 case -3:
Chris@16 366 {
Chris@16 367 // independent sub-expression, currently this is always recursive:
Chris@16 368 bool old_independent = m_independent;
Chris@16 369 m_independent = true;
Chris@16 370 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
Chris@16 371 pstate = pstate->next.p->next.p;
Chris@16 372 bool r = match_all_states();
Chris@16 373 pstate = next_pstate;
Chris@16 374 m_independent = old_independent;
Chris@16 375 #ifdef BOOST_REGEX_MATCH_EXTRA
Chris@16 376 if(r && (m_match_flags & match_extra))
Chris@16 377 {
Chris@16 378 //
Chris@16 379 // our captures have been stored in *m_presult
Chris@16 380 // we need to unpack them, and insert them
Chris@16 381 // back in the right order when we unwind the stack:
Chris@16 382 //
Chris@16 383 match_results<BidiIterator, Allocator> temp_match(*m_presult);
Chris@16 384 unsigned i;
Chris@16 385 for(i = 0; i < temp_match.size(); ++i)
Chris@16 386 (*m_presult)[i].get_captures().clear();
Chris@16 387 // match everything else:
Chris@16 388 r = match_all_states();
Chris@16 389 // now place the stored captures back:
Chris@16 390 for(i = 0; i < temp_match.size(); ++i)
Chris@16 391 {
Chris@16 392 typedef typename sub_match<BidiIterator>::capture_sequence_type seq;
Chris@16 393 seq& s1 = (*m_presult)[i].get_captures();
Chris@16 394 const seq& s2 = temp_match[i].captures();
Chris@16 395 s1.insert(
Chris@16 396 s1.end(),
Chris@16 397 s2.begin(),
Chris@16 398 s2.end());
Chris@16 399 }
Chris@16 400 }
Chris@16 401 #endif
Chris@16 402 return r;
Chris@16 403 }
Chris@16 404 case -4:
Chris@16 405 {
Chris@16 406 // conditional expression:
Chris@16 407 const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
Chris@16 408 BOOST_ASSERT(alt->type == syntax_element_alt);
Chris@16 409 pstate = alt->next.p;
Chris@16 410 if(pstate->type == syntax_element_assert_backref)
Chris@16 411 {
Chris@16 412 if(!match_assert_backref())
Chris@16 413 pstate = alt->alt.p;
Chris@16 414 break;
Chris@16 415 }
Chris@16 416 else
Chris@16 417 {
Chris@16 418 // zero width assertion, have to match this recursively:
Chris@16 419 BOOST_ASSERT(pstate->type == syntax_element_startmark);
Chris@16 420 bool negated = static_cast<const re_brace*>(pstate)->index == -2;
Chris@16 421 BidiIterator saved_position = position;
Chris@16 422 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
Chris@16 423 pstate = pstate->next.p->next.p;
Chris@16 424 bool r = match_all_states();
Chris@16 425 position = saved_position;
Chris@16 426 if(negated)
Chris@16 427 r = !r;
Chris@16 428 if(r)
Chris@16 429 pstate = next_pstate;
Chris@16 430 else
Chris@16 431 pstate = alt->alt.p;
Chris@16 432 break;
Chris@16 433 }
Chris@16 434 }
Chris@16 435 case -5:
Chris@16 436 {
Chris@16 437 push_matched_paren(0, (*m_presult)[0]);
Chris@16 438 m_presult->set_first(position, 0, true);
Chris@16 439 pstate = pstate->next.p;
Chris@16 440 break;
Chris@16 441 }
Chris@16 442 default:
Chris@16 443 {
Chris@16 444 BOOST_ASSERT(index > 0);
Chris@16 445 if((m_match_flags & match_nosubs) == 0)
Chris@16 446 {
Chris@16 447 push_matched_paren(index, (*m_presult)[index]);
Chris@16 448 m_presult->set_first(position, index);
Chris@16 449 }
Chris@16 450 pstate = pstate->next.p;
Chris@16 451 break;
Chris@16 452 }
Chris@16 453 }
Chris@16 454 return true;
Chris@16 455 }
Chris@16 456
Chris@16 457 template <class BidiIterator, class Allocator, class traits>
Chris@16 458 bool perl_matcher<BidiIterator, Allocator, traits>::match_alt()
Chris@16 459 {
Chris@16 460 bool take_first, take_second;
Chris@16 461 const re_alt* jmp = static_cast<const re_alt*>(pstate);
Chris@16 462
Chris@16 463 // find out which of these two alternatives we need to take:
Chris@16 464 if(position == last)
Chris@16 465 {
Chris@16 466 take_first = jmp->can_be_null & mask_take;
Chris@16 467 take_second = jmp->can_be_null & mask_skip;
Chris@16 468 }
Chris@16 469 else
Chris@16 470 {
Chris@16 471 take_first = can_start(*position, jmp->_map, (unsigned char)mask_take);
Chris@16 472 take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip);
Chris@16 473 }
Chris@16 474
Chris@16 475 if(take_first)
Chris@16 476 {
Chris@16 477 // we can take the first alternative,
Chris@16 478 // see if we need to push next alternative:
Chris@16 479 if(take_second)
Chris@16 480 {
Chris@16 481 push_alt(jmp->alt.p);
Chris@16 482 }
Chris@16 483 pstate = pstate->next.p;
Chris@16 484 return true;
Chris@16 485 }
Chris@16 486 if(take_second)
Chris@16 487 {
Chris@16 488 pstate = jmp->alt.p;
Chris@16 489 return true;
Chris@16 490 }
Chris@16 491 return false; // neither option is possible
Chris@16 492 }
Chris@16 493
Chris@16 494 template <class BidiIterator, class Allocator, class traits>
Chris@16 495 bool perl_matcher<BidiIterator, Allocator, traits>::match_rep()
Chris@16 496 {
Chris@16 497 #ifdef BOOST_MSVC
Chris@16 498 #pragma warning(push)
Chris@16 499 #pragma warning(disable:4127 4244)
Chris@16 500 #endif
Chris@16 501 #ifdef __BORLANDC__
Chris@16 502 #pragma option push -w-8008 -w-8066 -w-8004
Chris@16 503 #endif
Chris@16 504 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 505
Chris@16 506 // find out which of these two alternatives we need to take:
Chris@16 507 bool take_first, take_second;
Chris@16 508 if(position == last)
Chris@16 509 {
Chris@16 510 take_first = rep->can_be_null & mask_take;
Chris@16 511 take_second = rep->can_be_null & mask_skip;
Chris@16 512 }
Chris@16 513 else
Chris@16 514 {
Chris@16 515 take_first = can_start(*position, rep->_map, (unsigned char)mask_take);
Chris@16 516 take_second = can_start(*position, rep->_map, (unsigned char)mask_skip);
Chris@16 517 }
Chris@16 518
Chris@16 519 if((m_backup_state->state_id != saved_state_repeater_count)
Chris@16 520 || (static_cast<saved_repeater<BidiIterator>*>(m_backup_state)->count.get_id() != rep->state_id)
Chris@16 521 || (next_count->get_id() != rep->state_id))
Chris@16 522 {
Chris@16 523 // we're moving to a different repeat from the last
Chris@16 524 // one, so set up a counter object:
Chris@16 525 push_repeater_count(rep->state_id, &next_count);
Chris@16 526 }
Chris@16 527 //
Chris@16 528 // If we've had at least one repeat already, and the last one
Chris@16 529 // matched the NULL string then set the repeat count to
Chris@16 530 // maximum:
Chris@16 531 //
Chris@16 532 next_count->check_null_repeat(position, rep->max);
Chris@16 533
Chris@16 534 if(next_count->get_count() < rep->min)
Chris@16 535 {
Chris@16 536 // we must take the repeat:
Chris@16 537 if(take_first)
Chris@16 538 {
Chris@16 539 // increase the counter:
Chris@16 540 ++(*next_count);
Chris@16 541 pstate = rep->next.p;
Chris@16 542 return true;
Chris@16 543 }
Chris@16 544 return false;
Chris@16 545 }
Chris@16 546
Chris@16 547 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 548 if(greedy)
Chris@16 549 {
Chris@16 550 // try and take the repeat if we can:
Chris@16 551 if((next_count->get_count() < rep->max) && take_first)
Chris@16 552 {
Chris@16 553 if(take_second)
Chris@16 554 {
Chris@16 555 // store position in case we fail:
Chris@16 556 push_alt(rep->alt.p);
Chris@16 557 }
Chris@16 558 // increase the counter:
Chris@16 559 ++(*next_count);
Chris@16 560 pstate = rep->next.p;
Chris@16 561 return true;
Chris@16 562 }
Chris@16 563 else if(take_second)
Chris@16 564 {
Chris@16 565 pstate = rep->alt.p;
Chris@16 566 return true;
Chris@16 567 }
Chris@16 568 return false; // can't take anything, fail...
Chris@16 569 }
Chris@16 570 else // non-greedy
Chris@16 571 {
Chris@16 572 // try and skip the repeat if we can:
Chris@16 573 if(take_second)
Chris@16 574 {
Chris@16 575 if((next_count->get_count() < rep->max) && take_first)
Chris@16 576 {
Chris@16 577 // store position in case we fail:
Chris@16 578 push_non_greedy_repeat(rep->next.p);
Chris@16 579 }
Chris@16 580 pstate = rep->alt.p;
Chris@16 581 return true;
Chris@16 582 }
Chris@16 583 if((next_count->get_count() < rep->max) && take_first)
Chris@16 584 {
Chris@16 585 // increase the counter:
Chris@16 586 ++(*next_count);
Chris@16 587 pstate = rep->next.p;
Chris@16 588 return true;
Chris@16 589 }
Chris@16 590 }
Chris@16 591 return false;
Chris@16 592 #ifdef __BORLANDC__
Chris@16 593 #pragma option pop
Chris@16 594 #endif
Chris@16 595 #ifdef BOOST_MSVC
Chris@16 596 #pragma warning(pop)
Chris@16 597 #endif
Chris@16 598 }
Chris@16 599
Chris@16 600 template <class BidiIterator, class Allocator, class traits>
Chris@16 601 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
Chris@16 602 {
Chris@16 603 unsigned count = 0;
Chris@16 604 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 605 re_syntax_base* psingle = rep->next.p;
Chris@16 606 // match compulsary repeats first:
Chris@16 607 while(count < rep->min)
Chris@16 608 {
Chris@16 609 pstate = psingle;
Chris@16 610 if(!match_wild())
Chris@16 611 return false;
Chris@16 612 ++count;
Chris@16 613 }
Chris@16 614 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 615 if(greedy)
Chris@16 616 {
Chris@16 617 // repeat for as long as we can:
Chris@16 618 while(count < rep->max)
Chris@16 619 {
Chris@16 620 pstate = psingle;
Chris@16 621 if(!match_wild())
Chris@16 622 break;
Chris@16 623 ++count;
Chris@16 624 }
Chris@16 625 // remember where we got to if this is a leading repeat:
Chris@16 626 if((rep->leading) && (count < rep->max))
Chris@16 627 restart = position;
Chris@16 628 // push backtrack info if available:
Chris@16 629 if(count - rep->min)
Chris@16 630 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
Chris@16 631 // jump to next state:
Chris@16 632 pstate = rep->alt.p;
Chris@16 633 return true;
Chris@16 634 }
Chris@16 635 else
Chris@16 636 {
Chris@16 637 // non-greedy, push state and return true if we can skip:
Chris@16 638 if(count < rep->max)
Chris@16 639 push_single_repeat(count, rep, position, saved_state_rep_slow_dot);
Chris@16 640 pstate = rep->alt.p;
Chris@16 641 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
Chris@16 642 }
Chris@16 643 }
Chris@16 644
Chris@16 645 template <class BidiIterator, class Allocator, class traits>
Chris@16 646 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
Chris@16 647 {
Chris@16 648 if(m_match_flags & match_not_dot_null)
Chris@16 649 return match_dot_repeat_slow();
Chris@16 650 if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
Chris@16 651 return match_dot_repeat_slow();
Chris@16 652
Chris@16 653 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 654 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 655 unsigned count = static_cast<unsigned>((std::min)(static_cast<unsigned>(::boost::re_detail::distance(position, last)), static_cast<unsigned>(greedy ? rep->max : rep->min)));
Chris@16 656 if(rep->min > count)
Chris@16 657 {
Chris@16 658 position = last;
Chris@16 659 return false; // not enough text left to match
Chris@16 660 }
Chris@16 661 std::advance(position, count);
Chris@16 662
Chris@16 663 if(greedy)
Chris@16 664 {
Chris@16 665 if((rep->leading) && (count < rep->max))
Chris@16 666 restart = position;
Chris@16 667 // push backtrack info if available:
Chris@16 668 if(count - rep->min)
Chris@16 669 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
Chris@16 670 // jump to next state:
Chris@16 671 pstate = rep->alt.p;
Chris@16 672 return true;
Chris@16 673 }
Chris@16 674 else
Chris@16 675 {
Chris@16 676 // non-greedy, push state and return true if we can skip:
Chris@16 677 if(count < rep->max)
Chris@16 678 push_single_repeat(count, rep, position, saved_state_rep_fast_dot);
Chris@16 679 pstate = rep->alt.p;
Chris@16 680 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
Chris@16 681 }
Chris@16 682 }
Chris@16 683
Chris@16 684 template <class BidiIterator, class Allocator, class traits>
Chris@16 685 bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
Chris@16 686 {
Chris@16 687 #ifdef BOOST_MSVC
Chris@16 688 #pragma warning(push)
Chris@16 689 #pragma warning(disable:4127)
Chris@16 690 #endif
Chris@16 691 #ifdef __BORLANDC__
Chris@16 692 #pragma option push -w-8008 -w-8066 -w-8004
Chris@16 693 #endif
Chris@16 694 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 695 BOOST_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length);
Chris@16 696 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
Chris@16 697 std::size_t count = 0;
Chris@16 698 //
Chris@16 699 // start by working out how much we can skip:
Chris@16 700 //
Chris@16 701 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 702 std::size_t desired = greedy ? rep->max : rep->min;
Chris@16 703 if(::boost::is_random_access_iterator<BidiIterator>::value)
Chris@16 704 {
Chris@16 705 BidiIterator end = position;
Chris@16 706 // Move end forward by "desired", preferably without using distance or advance if we can
Chris@16 707 // as these can be slow for some iterator types.
Chris@16 708 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::re_detail::distance(position, last);
Chris@16 709 if(desired >= len)
Chris@16 710 end = last;
Chris@16 711 else
Chris@16 712 std::advance(end, desired);
Chris@16 713 BidiIterator origin(position);
Chris@16 714 while((position != end) && (traits_inst.translate(*position, icase) == what))
Chris@16 715 {
Chris@16 716 ++position;
Chris@16 717 }
Chris@16 718 count = (unsigned)::boost::re_detail::distance(origin, position);
Chris@16 719 }
Chris@16 720 else
Chris@16 721 {
Chris@16 722 while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what))
Chris@16 723 {
Chris@16 724 ++position;
Chris@16 725 ++count;
Chris@16 726 }
Chris@16 727 }
Chris@16 728
Chris@16 729 if(count < rep->min)
Chris@16 730 return false;
Chris@16 731
Chris@16 732 if(greedy)
Chris@16 733 {
Chris@16 734 if((rep->leading) && (count < rep->max))
Chris@16 735 restart = position;
Chris@16 736 // push backtrack info if available:
Chris@16 737 if(count - rep->min)
Chris@16 738 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
Chris@16 739 // jump to next state:
Chris@16 740 pstate = rep->alt.p;
Chris@16 741 return true;
Chris@16 742 }
Chris@16 743 else
Chris@16 744 {
Chris@16 745 // non-greedy, push state and return true if we can skip:
Chris@16 746 if(count < rep->max)
Chris@16 747 push_single_repeat(count, rep, position, saved_state_rep_char);
Chris@16 748 pstate = rep->alt.p;
Chris@16 749 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
Chris@16 750 }
Chris@16 751 #ifdef __BORLANDC__
Chris@16 752 #pragma option pop
Chris@16 753 #endif
Chris@16 754 #ifdef BOOST_MSVC
Chris@16 755 #pragma warning(pop)
Chris@16 756 #endif
Chris@16 757 }
Chris@16 758
Chris@16 759 template <class BidiIterator, class Allocator, class traits>
Chris@16 760 bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
Chris@16 761 {
Chris@16 762 #ifdef BOOST_MSVC
Chris@16 763 #pragma warning(push)
Chris@16 764 #pragma warning(disable:4127)
Chris@16 765 #endif
Chris@16 766 #ifdef __BORLANDC__
Chris@16 767 #pragma option push -w-8008 -w-8066 -w-8004
Chris@16 768 #endif
Chris@16 769 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 770 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
Chris@16 771 std::size_t count = 0;
Chris@16 772 //
Chris@16 773 // start by working out how much we can skip:
Chris@16 774 //
Chris@16 775 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 776 std::size_t desired = greedy ? rep->max : rep->min;
Chris@16 777 if(::boost::is_random_access_iterator<BidiIterator>::value)
Chris@16 778 {
Chris@16 779 BidiIterator end = position;
Chris@16 780 // Move end forward by "desired", preferably without using distance or advance if we can
Chris@16 781 // as these can be slow for some iterator types.
Chris@16 782 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::re_detail::distance(position, last);
Chris@16 783 if(desired >= len)
Chris@16 784 end = last;
Chris@16 785 else
Chris@16 786 std::advance(end, desired);
Chris@16 787 BidiIterator origin(position);
Chris@16 788 while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
Chris@16 789 {
Chris@16 790 ++position;
Chris@16 791 }
Chris@16 792 count = (unsigned)::boost::re_detail::distance(origin, position);
Chris@16 793 }
Chris@16 794 else
Chris@16 795 {
Chris@16 796 while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
Chris@16 797 {
Chris@16 798 ++position;
Chris@16 799 ++count;
Chris@16 800 }
Chris@16 801 }
Chris@16 802
Chris@16 803 if(count < rep->min)
Chris@16 804 return false;
Chris@16 805
Chris@16 806 if(greedy)
Chris@16 807 {
Chris@16 808 if((rep->leading) && (count < rep->max))
Chris@16 809 restart = position;
Chris@16 810 // push backtrack info if available:
Chris@16 811 if(count - rep->min)
Chris@16 812 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
Chris@16 813 // jump to next state:
Chris@16 814 pstate = rep->alt.p;
Chris@16 815 return true;
Chris@16 816 }
Chris@16 817 else
Chris@16 818 {
Chris@16 819 // non-greedy, push state and return true if we can skip:
Chris@16 820 if(count < rep->max)
Chris@16 821 push_single_repeat(count, rep, position, saved_state_rep_short_set);
Chris@16 822 pstate = rep->alt.p;
Chris@16 823 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
Chris@16 824 }
Chris@16 825 #ifdef __BORLANDC__
Chris@16 826 #pragma option pop
Chris@16 827 #endif
Chris@16 828 #ifdef BOOST_MSVC
Chris@16 829 #pragma warning(pop)
Chris@16 830 #endif
Chris@16 831 }
Chris@16 832
Chris@16 833 template <class BidiIterator, class Allocator, class traits>
Chris@16 834 bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
Chris@16 835 {
Chris@16 836 #ifdef BOOST_MSVC
Chris@16 837 #pragma warning(push)
Chris@16 838 #pragma warning(disable:4127)
Chris@16 839 #endif
Chris@16 840 #ifdef __BORLANDC__
Chris@16 841 #pragma option push -w-8008 -w-8066 -w-8004
Chris@16 842 #endif
Chris@16 843 typedef typename traits::char_class_type m_type;
Chris@16 844 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 845 const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate->next.p);
Chris@16 846 std::size_t count = 0;
Chris@16 847 //
Chris@16 848 // start by working out how much we can skip:
Chris@16 849 //
Chris@16 850 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 851 std::size_t desired = greedy ? rep->max : rep->min;
Chris@16 852 if(::boost::is_random_access_iterator<BidiIterator>::value)
Chris@16 853 {
Chris@16 854 BidiIterator end = position;
Chris@16 855 // Move end forward by "desired", preferably without using distance or advance if we can
Chris@16 856 // as these can be slow for some iterator types.
Chris@16 857 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::re_detail::distance(position, last);
Chris@16 858 if(desired >= len)
Chris@16 859 end = last;
Chris@16 860 else
Chris@16 861 std::advance(end, desired);
Chris@16 862 BidiIterator origin(position);
Chris@16 863 while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
Chris@16 864 {
Chris@16 865 ++position;
Chris@16 866 }
Chris@16 867 count = (unsigned)::boost::re_detail::distance(origin, position);
Chris@16 868 }
Chris@16 869 else
Chris@16 870 {
Chris@16 871 while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
Chris@16 872 {
Chris@16 873 ++position;
Chris@16 874 ++count;
Chris@16 875 }
Chris@16 876 }
Chris@16 877
Chris@16 878 if(count < rep->min)
Chris@16 879 return false;
Chris@16 880
Chris@16 881 if(greedy)
Chris@16 882 {
Chris@16 883 if((rep->leading) && (count < rep->max))
Chris@16 884 restart = position;
Chris@16 885 // push backtrack info if available:
Chris@16 886 if(count - rep->min)
Chris@16 887 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
Chris@16 888 // jump to next state:
Chris@16 889 pstate = rep->alt.p;
Chris@16 890 return true;
Chris@16 891 }
Chris@16 892 else
Chris@16 893 {
Chris@16 894 // non-greedy, push state and return true if we can skip:
Chris@16 895 if(count < rep->max)
Chris@16 896 push_single_repeat(count, rep, position, saved_state_rep_long_set);
Chris@16 897 pstate = rep->alt.p;
Chris@16 898 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
Chris@16 899 }
Chris@16 900 #ifdef __BORLANDC__
Chris@16 901 #pragma option pop
Chris@16 902 #endif
Chris@16 903 #ifdef BOOST_MSVC
Chris@16 904 #pragma warning(pop)
Chris@16 905 #endif
Chris@16 906 }
Chris@16 907
Chris@16 908 template <class BidiIterator, class Allocator, class traits>
Chris@16 909 bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
Chris@16 910 {
Chris@16 911 BOOST_ASSERT(pstate->type == syntax_element_recurse);
Chris@16 912 //
Chris@16 913 // Backup call stack:
Chris@16 914 //
Chris@16 915 push_recursion_pop();
Chris@16 916 //
Chris@16 917 // Set new call stack:
Chris@16 918 //
Chris@16 919 if(recursion_stack.capacity() == 0)
Chris@16 920 {
Chris@16 921 recursion_stack.reserve(50);
Chris@16 922 }
Chris@16 923 recursion_stack.push_back(recursion_info<results_type>());
Chris@16 924 recursion_stack.back().preturn_address = pstate->next.p;
Chris@16 925 recursion_stack.back().results = *m_presult;
Chris@16 926 if(static_cast<const re_recurse*>(pstate)->state_id > 0)
Chris@16 927 {
Chris@16 928 push_repeater_count(static_cast<const re_recurse*>(pstate)->state_id, &next_count);
Chris@16 929 }
Chris@16 930 pstate = static_cast<const re_jump*>(pstate)->alt.p;
Chris@16 931 recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
Chris@16 932
Chris@16 933 return true;
Chris@16 934 }
Chris@16 935
Chris@16 936 template <class BidiIterator, class Allocator, class traits>
Chris@16 937 bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
Chris@16 938 {
Chris@16 939 int index = static_cast<const re_brace*>(pstate)->index;
Chris@16 940 icase = static_cast<const re_brace*>(pstate)->icase;
Chris@16 941 if(index > 0)
Chris@16 942 {
Chris@16 943 if((m_match_flags & match_nosubs) == 0)
Chris@16 944 {
Chris@16 945 m_presult->set_second(position, index);
Chris@16 946 }
Chris@16 947 if(!recursion_stack.empty())
Chris@16 948 {
Chris@16 949 if(index == recursion_stack.back().idx)
Chris@16 950 {
Chris@16 951 pstate = recursion_stack.back().preturn_address;
Chris@16 952 *m_presult = recursion_stack.back().results;
Chris@16 953 push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, &recursion_stack.back().results);
Chris@16 954 recursion_stack.pop_back();
Chris@16 955 }
Chris@16 956 }
Chris@16 957 }
Chris@16 958 else if((index < 0) && (index != -4))
Chris@16 959 {
Chris@16 960 // matched forward lookahead:
Chris@16 961 pstate = 0;
Chris@16 962 return true;
Chris@16 963 }
Chris@16 964 pstate = pstate->next.p;
Chris@16 965 return true;
Chris@16 966 }
Chris@16 967
Chris@16 968 template <class BidiIterator, class Allocator, class traits>
Chris@16 969 bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
Chris@16 970 {
Chris@16 971 if(!recursion_stack.empty())
Chris@16 972 {
Chris@16 973 BOOST_ASSERT(0 == recursion_stack.back().idx);
Chris@16 974 pstate = recursion_stack.back().preturn_address;
Chris@16 975 *m_presult = recursion_stack.back().results;
Chris@16 976 push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, &recursion_stack.back().results);
Chris@16 977 recursion_stack.pop_back();
Chris@16 978 return true;
Chris@16 979 }
Chris@16 980 if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
Chris@16 981 return false;
Chris@16 982 if((m_match_flags & match_all) && (position != last))
Chris@16 983 return false;
Chris@16 984 if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base))
Chris@16 985 return false;
Chris@16 986 m_presult->set_second(position);
Chris@16 987 pstate = 0;
Chris@16 988 m_has_found_match = true;
Chris@16 989 if((m_match_flags & match_posix) == match_posix)
Chris@16 990 {
Chris@16 991 m_result.maybe_assign(*m_presult);
Chris@16 992 if((m_match_flags & match_any) == 0)
Chris@16 993 return false;
Chris@16 994 }
Chris@16 995 #ifdef BOOST_REGEX_MATCH_EXTRA
Chris@16 996 if(match_extra & m_match_flags)
Chris@16 997 {
Chris@16 998 for(unsigned i = 0; i < m_presult->size(); ++i)
Chris@16 999 if((*m_presult)[i].matched)
Chris@16 1000 ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]);
Chris@16 1001 }
Chris@16 1002 #endif
Chris@16 1003 return true;
Chris@16 1004 }
Chris@16 1005
Chris@16 1006 /****************************************************************************
Chris@16 1007
Chris@16 1008 Unwind and associated proceedures follow, these perform what normal stack
Chris@16 1009 unwinding does in the recursive implementation.
Chris@16 1010
Chris@16 1011 ****************************************************************************/
Chris@16 1012
Chris@16 1013 template <class BidiIterator, class Allocator, class traits>
Chris@16 1014 bool perl_matcher<BidiIterator, Allocator, traits>::unwind(bool have_match)
Chris@16 1015 {
Chris@16 1016 static unwind_proc_type const s_unwind_table[18] =
Chris@16 1017 {
Chris@16 1018 &perl_matcher<BidiIterator, Allocator, traits>::unwind_end,
Chris@16 1019 &perl_matcher<BidiIterator, Allocator, traits>::unwind_paren,
Chris@16 1020 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper,
Chris@16 1021 &perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion,
Chris@16 1022 &perl_matcher<BidiIterator, Allocator, traits>::unwind_alt,
Chris@16 1023 &perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter,
Chris@16 1024 &perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block,
Chris@16 1025 &perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat,
Chris@16 1026 &perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat,
Chris@16 1027 &perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat,
Chris@16 1028 &perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat,
Chris@16 1029 &perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat,
Chris@16 1030 &perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat,
Chris@16 1031 &perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat,
Chris@16 1032 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion,
Chris@16 1033 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop,
Chris@16 1034 };
Chris@16 1035
Chris@16 1036 m_recursive_result = have_match;
Chris@16 1037 unwind_proc_type unwinder;
Chris@16 1038 bool cont;
Chris@16 1039 //
Chris@16 1040 // keep unwinding our stack until we have something to do:
Chris@16 1041 //
Chris@16 1042 do
Chris@16 1043 {
Chris@16 1044 unwinder = s_unwind_table[m_backup_state->state_id];
Chris@16 1045 cont = (this->*unwinder)(m_recursive_result);
Chris@16 1046 }while(cont);
Chris@16 1047 //
Chris@16 1048 // return true if we have more states to try:
Chris@16 1049 //
Chris@16 1050 return pstate ? true : false;
Chris@16 1051 }
Chris@16 1052
Chris@16 1053 template <class BidiIterator, class Allocator, class traits>
Chris@16 1054 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_end(bool)
Chris@16 1055 {
Chris@16 1056 pstate = 0; // nothing left to search
Chris@16 1057 return false; // end of stack nothing more to search
Chris@16 1058 }
Chris@16 1059
Chris@16 1060 template <class BidiIterator, class Allocator, class traits>
Chris@16 1061 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_paren(bool have_match)
Chris@16 1062 {
Chris@16 1063 saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
Chris@16 1064 // restore previous values if no match was found:
Chris@16 1065 if(have_match == false)
Chris@16 1066 {
Chris@16 1067 m_presult->set_first(pmp->sub.first, pmp->index, pmp->index == 0);
Chris@16 1068 m_presult->set_second(pmp->sub.second, pmp->index, pmp->sub.matched, pmp->index == 0);
Chris@16 1069 }
Chris@16 1070 #ifdef BOOST_REGEX_MATCH_EXTRA
Chris@16 1071 //
Chris@16 1072 // we have a match, push the capture information onto the stack:
Chris@16 1073 //
Chris@16 1074 else if(pmp->sub.matched && (match_extra & m_match_flags))
Chris@16 1075 ((*m_presult)[pmp->index]).get_captures().push_back(pmp->sub);
Chris@16 1076 #endif
Chris@16 1077 // unwind stack:
Chris@16 1078 m_backup_state = pmp+1;
Chris@16 1079 boost::re_detail::inplace_destroy(pmp);
Chris@16 1080 return true; // keep looking
Chris@16 1081 }
Chris@16 1082
Chris@16 1083 template <class BidiIterator, class Allocator, class traits>
Chris@16 1084 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper(bool)
Chris@16 1085 {
Chris@16 1086 boost::re_detail::inplace_destroy(m_backup_state++);
Chris@16 1087 pstate = 0; // nothing left to search
Chris@16 1088 return false; // end of stack nothing more to search
Chris@16 1089 }
Chris@16 1090
Chris@16 1091 template <class BidiIterator, class Allocator, class traits>
Chris@16 1092 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion(bool r)
Chris@16 1093 {
Chris@16 1094 saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
Chris@16 1095 pstate = pmp->pstate;
Chris@16 1096 position = pmp->position;
Chris@16 1097 bool result = (r == pmp->positive);
Chris@16 1098 m_recursive_result = pmp->positive ? r : !r;
Chris@16 1099 boost::re_detail::inplace_destroy(pmp++);
Chris@16 1100 m_backup_state = pmp;
Chris@16 1101 return !result; // return false if the assertion was matched to stop search.
Chris@16 1102 }
Chris@16 1103
Chris@16 1104 template <class BidiIterator, class Allocator, class traits>
Chris@16 1105 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_alt(bool r)
Chris@16 1106 {
Chris@16 1107 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
Chris@16 1108 if(!r)
Chris@16 1109 {
Chris@16 1110 pstate = pmp->pstate;
Chris@16 1111 position = pmp->position;
Chris@16 1112 }
Chris@16 1113 boost::re_detail::inplace_destroy(pmp++);
Chris@16 1114 m_backup_state = pmp;
Chris@16 1115 return r;
Chris@16 1116 }
Chris@16 1117
Chris@16 1118 template <class BidiIterator, class Allocator, class traits>
Chris@16 1119 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter(bool)
Chris@16 1120 {
Chris@16 1121 saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
Chris@16 1122 boost::re_detail::inplace_destroy(pmp++);
Chris@16 1123 m_backup_state = pmp;
Chris@16 1124 return true; // keep looking
Chris@16 1125 }
Chris@16 1126
Chris@16 1127 template <class BidiIterator, class Allocator, class traits>
Chris@16 1128 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block(bool)
Chris@16 1129 {
Chris@16 1130 saved_extra_block* pmp = static_cast<saved_extra_block*>(m_backup_state);
Chris@16 1131 void* condemmed = m_stack_base;
Chris@16 1132 m_stack_base = pmp->base;
Chris@16 1133 m_backup_state = pmp->end;
Chris@16 1134 boost::re_detail::inplace_destroy(pmp);
Chris@16 1135 put_mem_block(condemmed);
Chris@16 1136 return true; // keep looking
Chris@16 1137 }
Chris@16 1138
Chris@16 1139 template <class BidiIterator, class Allocator, class traits>
Chris@16 1140 inline void perl_matcher<BidiIterator, Allocator, traits>::destroy_single_repeat()
Chris@16 1141 {
Chris@16 1142 saved_single_repeat<BidiIterator>* p = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
Chris@16 1143 boost::re_detail::inplace_destroy(p++);
Chris@16 1144 m_backup_state = p;
Chris@16 1145 }
Chris@16 1146
Chris@16 1147 template <class BidiIterator, class Allocator, class traits>
Chris@16 1148 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat(bool r)
Chris@16 1149 {
Chris@16 1150 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
Chris@16 1151
Chris@16 1152 // if we have a match, just discard this state:
Chris@16 1153 if(r)
Chris@16 1154 {
Chris@16 1155 destroy_single_repeat();
Chris@16 1156 return true;
Chris@16 1157 }
Chris@16 1158
Chris@16 1159 const re_repeat* rep = pmp->rep;
Chris@16 1160 std::size_t count = pmp->count;
Chris@16 1161 BOOST_ASSERT(rep->next.p != 0);
Chris@16 1162 BOOST_ASSERT(rep->alt.p != 0);
Chris@16 1163
Chris@16 1164 count -= rep->min;
Chris@16 1165
Chris@16 1166 if((m_match_flags & match_partial) && (position == last))
Chris@16 1167 m_has_partial_match = true;
Chris@16 1168
Chris@16 1169 BOOST_ASSERT(count);
Chris@16 1170 position = pmp->last_position;
Chris@16 1171
Chris@16 1172 // backtrack till we can skip out:
Chris@16 1173 do
Chris@16 1174 {
Chris@16 1175 --position;
Chris@16 1176 --count;
Chris@16 1177 ++state_count;
Chris@16 1178 }while(count && !can_start(*position, rep->_map, mask_skip));
Chris@16 1179
Chris@16 1180 // if we've hit base, destroy this state:
Chris@16 1181 if(count == 0)
Chris@16 1182 {
Chris@16 1183 destroy_single_repeat();
Chris@16 1184 if(!can_start(*position, rep->_map, mask_skip))
Chris@16 1185 return true;
Chris@16 1186 }
Chris@16 1187 else
Chris@16 1188 {
Chris@16 1189 pmp->count = count + rep->min;
Chris@16 1190 pmp->last_position = position;
Chris@16 1191 }
Chris@16 1192 pstate = rep->alt.p;
Chris@16 1193 return false;
Chris@16 1194 }
Chris@16 1195
Chris@16 1196 template <class BidiIterator, class Allocator, class traits>
Chris@16 1197 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat(bool r)
Chris@16 1198 {
Chris@16 1199 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
Chris@16 1200
Chris@16 1201 // if we have a match, just discard this state:
Chris@16 1202 if(r)
Chris@16 1203 {
Chris@16 1204 destroy_single_repeat();
Chris@16 1205 return true;
Chris@16 1206 }
Chris@16 1207
Chris@16 1208 const re_repeat* rep = pmp->rep;
Chris@16 1209 std::size_t count = pmp->count;
Chris@16 1210 BOOST_ASSERT(rep->type == syntax_element_dot_rep);
Chris@16 1211 BOOST_ASSERT(rep->next.p != 0);
Chris@16 1212 BOOST_ASSERT(rep->alt.p != 0);
Chris@16 1213 BOOST_ASSERT(rep->next.p->type == syntax_element_wild);
Chris@16 1214
Chris@16 1215 BOOST_ASSERT(count < rep->max);
Chris@16 1216 pstate = rep->next.p;
Chris@16 1217 position = pmp->last_position;
Chris@16 1218
Chris@16 1219 if(position != last)
Chris@16 1220 {
Chris@16 1221 // wind forward until we can skip out of the repeat:
Chris@16 1222 do
Chris@16 1223 {
Chris@16 1224 if(!match_wild())
Chris@16 1225 {
Chris@16 1226 // failed repeat match, discard this state and look for another:
Chris@16 1227 destroy_single_repeat();
Chris@16 1228 return true;
Chris@16 1229 }
Chris@16 1230 ++count;
Chris@16 1231 ++state_count;
Chris@16 1232 pstate = rep->next.p;
Chris@16 1233 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
Chris@16 1234 }
Chris@16 1235 if(position == last)
Chris@16 1236 {
Chris@16 1237 // can't repeat any more, remove the pushed state:
Chris@16 1238 destroy_single_repeat();
Chris@16 1239 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
Chris@16 1240 m_has_partial_match = true;
Chris@16 1241 if(0 == (rep->can_be_null & mask_skip))
Chris@16 1242 return true;
Chris@16 1243 }
Chris@16 1244 else if(count == rep->max)
Chris@16 1245 {
Chris@16 1246 // can't repeat any more, remove the pushed state:
Chris@16 1247 destroy_single_repeat();
Chris@16 1248 if(!can_start(*position, rep->_map, mask_skip))
Chris@16 1249 return true;
Chris@16 1250 }
Chris@16 1251 else
Chris@16 1252 {
Chris@16 1253 pmp->count = count;
Chris@16 1254 pmp->last_position = position;
Chris@16 1255 }
Chris@16 1256 pstate = rep->alt.p;
Chris@16 1257 return false;
Chris@16 1258 }
Chris@16 1259
Chris@16 1260 template <class BidiIterator, class Allocator, class traits>
Chris@16 1261 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat(bool r)
Chris@16 1262 {
Chris@16 1263 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
Chris@16 1264
Chris@16 1265 // if we have a match, just discard this state:
Chris@16 1266 if(r)
Chris@16 1267 {
Chris@16 1268 destroy_single_repeat();
Chris@16 1269 return true;
Chris@16 1270 }
Chris@16 1271
Chris@16 1272 const re_repeat* rep = pmp->rep;
Chris@16 1273 std::size_t count = pmp->count;
Chris@16 1274
Chris@16 1275 BOOST_ASSERT(count < rep->max);
Chris@16 1276 position = pmp->last_position;
Chris@16 1277 if(position != last)
Chris@16 1278 {
Chris@16 1279
Chris@16 1280 // wind forward until we can skip out of the repeat:
Chris@16 1281 do
Chris@16 1282 {
Chris@16 1283 ++position;
Chris@16 1284 ++count;
Chris@16 1285 ++state_count;
Chris@16 1286 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
Chris@16 1287 }
Chris@16 1288
Chris@16 1289 // remember where we got to if this is a leading repeat:
Chris@16 1290 if((rep->leading) && (count < rep->max))
Chris@16 1291 restart = position;
Chris@16 1292 if(position == last)
Chris@16 1293 {
Chris@16 1294 // can't repeat any more, remove the pushed state:
Chris@16 1295 destroy_single_repeat();
Chris@16 1296 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
Chris@16 1297 m_has_partial_match = true;
Chris@16 1298 if(0 == (rep->can_be_null & mask_skip))
Chris@16 1299 return true;
Chris@16 1300 }
Chris@16 1301 else if(count == rep->max)
Chris@16 1302 {
Chris@16 1303 // can't repeat any more, remove the pushed state:
Chris@16 1304 destroy_single_repeat();
Chris@16 1305 if(!can_start(*position, rep->_map, mask_skip))
Chris@16 1306 return true;
Chris@16 1307 }
Chris@16 1308 else
Chris@16 1309 {
Chris@16 1310 pmp->count = count;
Chris@16 1311 pmp->last_position = position;
Chris@16 1312 }
Chris@16 1313 pstate = rep->alt.p;
Chris@16 1314 return false;
Chris@16 1315 }
Chris@16 1316
Chris@16 1317 template <class BidiIterator, class Allocator, class traits>
Chris@16 1318 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat(bool r)
Chris@16 1319 {
Chris@16 1320 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
Chris@16 1321
Chris@16 1322 // if we have a match, just discard this state:
Chris@16 1323 if(r)
Chris@16 1324 {
Chris@16 1325 destroy_single_repeat();
Chris@16 1326 return true;
Chris@16 1327 }
Chris@16 1328
Chris@16 1329 const re_repeat* rep = pmp->rep;
Chris@16 1330 std::size_t count = pmp->count;
Chris@16 1331 pstate = rep->next.p;
Chris@16 1332 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1);
Chris@16 1333 position = pmp->last_position;
Chris@16 1334
Chris@16 1335 BOOST_ASSERT(rep->type == syntax_element_char_rep);
Chris@16 1336 BOOST_ASSERT(rep->next.p != 0);
Chris@16 1337 BOOST_ASSERT(rep->alt.p != 0);
Chris@16 1338 BOOST_ASSERT(rep->next.p->type == syntax_element_literal);
Chris@16 1339 BOOST_ASSERT(count < rep->max);
Chris@16 1340
Chris@16 1341 if(position != last)
Chris@16 1342 {
Chris@16 1343 // wind forward until we can skip out of the repeat:
Chris@16 1344 do
Chris@16 1345 {
Chris@16 1346 if(traits_inst.translate(*position, icase) != what)
Chris@16 1347 {
Chris@16 1348 // failed repeat match, discard this state and look for another:
Chris@16 1349 destroy_single_repeat();
Chris@16 1350 return true;
Chris@16 1351 }
Chris@16 1352 ++count;
Chris@16 1353 ++ position;
Chris@16 1354 ++state_count;
Chris@16 1355 pstate = rep->next.p;
Chris@16 1356 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
Chris@16 1357 }
Chris@16 1358 // remember where we got to if this is a leading repeat:
Chris@16 1359 if((rep->leading) && (count < rep->max))
Chris@16 1360 restart = position;
Chris@16 1361 if(position == last)
Chris@16 1362 {
Chris@16 1363 // can't repeat any more, remove the pushed state:
Chris@16 1364 destroy_single_repeat();
Chris@16 1365 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
Chris@16 1366 m_has_partial_match = true;
Chris@16 1367 if(0 == (rep->can_be_null & mask_skip))
Chris@16 1368 return true;
Chris@16 1369 }
Chris@16 1370 else if(count == rep->max)
Chris@16 1371 {
Chris@16 1372 // can't repeat any more, remove the pushed state:
Chris@16 1373 destroy_single_repeat();
Chris@16 1374 if(!can_start(*position, rep->_map, mask_skip))
Chris@16 1375 return true;
Chris@16 1376 }
Chris@16 1377 else
Chris@16 1378 {
Chris@16 1379 pmp->count = count;
Chris@16 1380 pmp->last_position = position;
Chris@16 1381 }
Chris@16 1382 pstate = rep->alt.p;
Chris@16 1383 return false;
Chris@16 1384 }
Chris@16 1385
Chris@16 1386 template <class BidiIterator, class Allocator, class traits>
Chris@16 1387 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat(bool r)
Chris@16 1388 {
Chris@16 1389 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
Chris@16 1390
Chris@16 1391 // if we have a match, just discard this state:
Chris@16 1392 if(r)
Chris@16 1393 {
Chris@16 1394 destroy_single_repeat();
Chris@16 1395 return true;
Chris@16 1396 }
Chris@16 1397
Chris@16 1398 const re_repeat* rep = pmp->rep;
Chris@16 1399 std::size_t count = pmp->count;
Chris@16 1400 pstate = rep->next.p;
Chris@16 1401 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
Chris@16 1402 position = pmp->last_position;
Chris@16 1403
Chris@16 1404 BOOST_ASSERT(rep->type == syntax_element_short_set_rep);
Chris@16 1405 BOOST_ASSERT(rep->next.p != 0);
Chris@16 1406 BOOST_ASSERT(rep->alt.p != 0);
Chris@16 1407 BOOST_ASSERT(rep->next.p->type == syntax_element_set);
Chris@16 1408 BOOST_ASSERT(count < rep->max);
Chris@16 1409
Chris@16 1410 if(position != last)
Chris@16 1411 {
Chris@16 1412 // wind forward until we can skip out of the repeat:
Chris@16 1413 do
Chris@16 1414 {
Chris@16 1415 if(!map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
Chris@16 1416 {
Chris@16 1417 // failed repeat match, discard this state and look for another:
Chris@16 1418 destroy_single_repeat();
Chris@16 1419 return true;
Chris@16 1420 }
Chris@16 1421 ++count;
Chris@16 1422 ++ position;
Chris@16 1423 ++state_count;
Chris@16 1424 pstate = rep->next.p;
Chris@16 1425 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
Chris@16 1426 }
Chris@16 1427 // remember where we got to if this is a leading repeat:
Chris@16 1428 if((rep->leading) && (count < rep->max))
Chris@16 1429 restart = position;
Chris@16 1430 if(position == last)
Chris@16 1431 {
Chris@16 1432 // can't repeat any more, remove the pushed state:
Chris@16 1433 destroy_single_repeat();
Chris@16 1434 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
Chris@16 1435 m_has_partial_match = true;
Chris@16 1436 if(0 == (rep->can_be_null & mask_skip))
Chris@16 1437 return true;
Chris@16 1438 }
Chris@16 1439 else if(count == rep->max)
Chris@16 1440 {
Chris@16 1441 // can't repeat any more, remove the pushed state:
Chris@16 1442 destroy_single_repeat();
Chris@16 1443 if(!can_start(*position, rep->_map, mask_skip))
Chris@16 1444 return true;
Chris@16 1445 }
Chris@16 1446 else
Chris@16 1447 {
Chris@16 1448 pmp->count = count;
Chris@16 1449 pmp->last_position = position;
Chris@16 1450 }
Chris@16 1451 pstate = rep->alt.p;
Chris@16 1452 return false;
Chris@16 1453 }
Chris@16 1454
Chris@16 1455 template <class BidiIterator, class Allocator, class traits>
Chris@16 1456 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat(bool r)
Chris@16 1457 {
Chris@16 1458 typedef typename traits::char_class_type m_type;
Chris@16 1459 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
Chris@16 1460
Chris@16 1461 // if we have a match, just discard this state:
Chris@16 1462 if(r)
Chris@16 1463 {
Chris@16 1464 destroy_single_repeat();
Chris@16 1465 return true;
Chris@16 1466 }
Chris@16 1467
Chris@16 1468 const re_repeat* rep = pmp->rep;
Chris@16 1469 std::size_t count = pmp->count;
Chris@16 1470 pstate = rep->next.p;
Chris@16 1471 const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate);
Chris@16 1472 position = pmp->last_position;
Chris@16 1473
Chris@16 1474 BOOST_ASSERT(rep->type == syntax_element_long_set_rep);
Chris@16 1475 BOOST_ASSERT(rep->next.p != 0);
Chris@16 1476 BOOST_ASSERT(rep->alt.p != 0);
Chris@16 1477 BOOST_ASSERT(rep->next.p->type == syntax_element_long_set);
Chris@16 1478 BOOST_ASSERT(count < rep->max);
Chris@16 1479
Chris@16 1480 if(position != last)
Chris@16 1481 {
Chris@16 1482 // wind forward until we can skip out of the repeat:
Chris@16 1483 do
Chris@16 1484 {
Chris@16 1485 if(position == re_is_set_member(position, last, set, re.get_data(), icase))
Chris@16 1486 {
Chris@16 1487 // failed repeat match, discard this state and look for another:
Chris@16 1488 destroy_single_repeat();
Chris@16 1489 return true;
Chris@16 1490 }
Chris@16 1491 ++position;
Chris@16 1492 ++count;
Chris@16 1493 ++state_count;
Chris@16 1494 pstate = rep->next.p;
Chris@16 1495 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
Chris@16 1496 }
Chris@16 1497 // remember where we got to if this is a leading repeat:
Chris@16 1498 if((rep->leading) && (count < rep->max))
Chris@16 1499 restart = position;
Chris@16 1500 if(position == last)
Chris@16 1501 {
Chris@16 1502 // can't repeat any more, remove the pushed state:
Chris@16 1503 destroy_single_repeat();
Chris@16 1504 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
Chris@16 1505 m_has_partial_match = true;
Chris@16 1506 if(0 == (rep->can_be_null & mask_skip))
Chris@16 1507 return true;
Chris@16 1508 }
Chris@16 1509 else if(count == rep->max)
Chris@16 1510 {
Chris@16 1511 // can't repeat any more, remove the pushed state:
Chris@16 1512 destroy_single_repeat();
Chris@16 1513 if(!can_start(*position, rep->_map, mask_skip))
Chris@16 1514 return true;
Chris@16 1515 }
Chris@16 1516 else
Chris@16 1517 {
Chris@16 1518 pmp->count = count;
Chris@16 1519 pmp->last_position = position;
Chris@16 1520 }
Chris@16 1521 pstate = rep->alt.p;
Chris@16 1522 return false;
Chris@16 1523 }
Chris@16 1524
Chris@16 1525 template <class BidiIterator, class Allocator, class traits>
Chris@16 1526 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat(bool r)
Chris@16 1527 {
Chris@16 1528 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
Chris@16 1529 if(!r)
Chris@16 1530 {
Chris@16 1531 position = pmp->position;
Chris@16 1532 pstate = pmp->pstate;
Chris@16 1533 ++(*next_count);
Chris@16 1534 }
Chris@16 1535 boost::re_detail::inplace_destroy(pmp++);
Chris@16 1536 m_backup_state = pmp;
Chris@16 1537 return r;
Chris@16 1538 }
Chris@16 1539
Chris@16 1540 template <class BidiIterator, class Allocator, class traits>
Chris@16 1541 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion(bool r)
Chris@16 1542 {
Chris@16 1543 saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
Chris@16 1544 if(!r)
Chris@16 1545 {
Chris@16 1546 recursion_stack.push_back(recursion_info<results_type>());
Chris@16 1547 recursion_stack.back().idx = pmp->recursion_id;
Chris@16 1548 recursion_stack.back().preturn_address = pmp->preturn_address;
Chris@16 1549 recursion_stack.back().results = pmp->results;
Chris@16 1550 }
Chris@16 1551 boost::re_detail::inplace_destroy(pmp++);
Chris@16 1552 m_backup_state = pmp;
Chris@16 1553 return true;
Chris@16 1554 }
Chris@16 1555
Chris@16 1556 template <class BidiIterator, class Allocator, class traits>
Chris@16 1557 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop(bool r)
Chris@16 1558 {
Chris@16 1559 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
Chris@16 1560 if(!r)
Chris@16 1561 {
Chris@16 1562 recursion_stack.pop_back();
Chris@16 1563 }
Chris@16 1564 boost::re_detail::inplace_destroy(pmp++);
Chris@16 1565 m_backup_state = pmp;
Chris@16 1566 return true;
Chris@16 1567 }
Chris@16 1568
Chris@16 1569 template <class BidiIterator, class Allocator, class traits>
Chris@16 1570 void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_pop()
Chris@16 1571 {
Chris@16 1572 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
Chris@16 1573 --pmp;
Chris@16 1574 if(pmp < m_stack_base)
Chris@16 1575 {
Chris@16 1576 extend_stack();
Chris@16 1577 pmp = static_cast<saved_state*>(m_backup_state);
Chris@16 1578 --pmp;
Chris@16 1579 }
Chris@16 1580 (void) new (pmp)saved_state(15);
Chris@16 1581 m_backup_state = pmp;
Chris@16 1582 }
Chris@16 1583 /*
Chris@16 1584 template <class BidiIterator, class Allocator, class traits>
Chris@16 1585 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_pop(bool r)
Chris@16 1586 {
Chris@16 1587 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
Chris@16 1588 if(!r)
Chris@16 1589 {
Chris@16 1590 --parenthesis_stack_position;
Chris@16 1591 }
Chris@16 1592 boost::re_detail::inplace_destroy(pmp++);
Chris@16 1593 m_backup_state = pmp;
Chris@16 1594 return true;
Chris@16 1595 }
Chris@16 1596
Chris@16 1597 template <class BidiIterator, class Allocator, class traits>
Chris@16 1598 void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_pop()
Chris@16 1599 {
Chris@16 1600 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
Chris@16 1601 --pmp;
Chris@16 1602 if(pmp < m_stack_base)
Chris@16 1603 {
Chris@16 1604 extend_stack();
Chris@16 1605 pmp = static_cast<saved_state*>(m_backup_state);
Chris@16 1606 --pmp;
Chris@16 1607 }
Chris@16 1608 (void) new (pmp)saved_state(16);
Chris@16 1609 m_backup_state = pmp;
Chris@16 1610 }
Chris@16 1611
Chris@16 1612 template <class BidiIterator, class Allocator, class traits>
Chris@16 1613 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_push(bool r)
Chris@16 1614 {
Chris@16 1615 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
Chris@16 1616 if(!r)
Chris@16 1617 {
Chris@16 1618 parenthesis_stack[parenthesis_stack_position++] = pmp->position;
Chris@16 1619 }
Chris@16 1620 boost::re_detail::inplace_destroy(pmp++);
Chris@16 1621 m_backup_state = pmp;
Chris@16 1622 return true;
Chris@16 1623 }
Chris@16 1624
Chris@16 1625 template <class BidiIterator, class Allocator, class traits>
Chris@16 1626 inline void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_push(BidiIterator p)
Chris@16 1627 {
Chris@16 1628 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
Chris@16 1629 --pmp;
Chris@16 1630 if(pmp < m_stack_base)
Chris@16 1631 {
Chris@16 1632 extend_stack();
Chris@16 1633 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
Chris@16 1634 --pmp;
Chris@16 1635 }
Chris@16 1636 (void) new (pmp)saved_position<BidiIterator>(0, p, 17);
Chris@16 1637 m_backup_state = pmp;
Chris@16 1638 }
Chris@16 1639 */
Chris@16 1640 } // namespace re_detail
Chris@16 1641 } // namespace boost
Chris@16 1642
Chris@16 1643 #ifdef BOOST_MSVC
Chris@16 1644 # pragma warning(pop)
Chris@16 1645 #endif
Chris@16 1646
Chris@16 1647 #ifdef BOOST_MSVC
Chris@16 1648 #pragma warning(push)
Chris@16 1649 #pragma warning(disable: 4103)
Chris@16 1650 #endif
Chris@16 1651 #ifdef BOOST_HAS_ABI_HEADERS
Chris@16 1652 # include BOOST_ABI_SUFFIX
Chris@16 1653 #endif
Chris@16 1654 #ifdef BOOST_MSVC
Chris@16 1655 #pragma warning(pop)
Chris@16 1656 #endif
Chris@16 1657
Chris@16 1658 #endif
Chris@16 1659
Chris@16 1660