annotate DEPENDENCIES/generic/include/boost/regex/v4/perl_matcher_recursive.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +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 recursive implementation.
Chris@16 18 */
Chris@16 19
Chris@16 20 #ifndef BOOST_REGEX_V4_PERL_MATCHER_RECURSIVE_HPP
Chris@16 21 #define BOOST_REGEX_V4_PERL_MATCHER_RECURSIVE_HPP
Chris@16 22
Chris@16 23 #ifdef BOOST_MSVC
Chris@16 24 #pragma warning(push)
Chris@16 25 #pragma warning(disable: 4103)
Chris@16 26 #endif
Chris@16 27 #ifdef BOOST_HAS_ABI_HEADERS
Chris@16 28 # include BOOST_ABI_PREFIX
Chris@16 29 #endif
Chris@16 30 #ifdef BOOST_MSVC
Chris@16 31 #pragma warning(pop)
Chris@16 32 #endif
Chris@16 33
Chris@16 34 #ifdef BOOST_MSVC
Chris@16 35 #pragma warning(push)
Chris@16 36 #pragma warning(disable: 4800)
Chris@16 37 #endif
Chris@16 38
Chris@16 39 namespace boost{
Chris@16 40 namespace re_detail{
Chris@16 41
Chris@16 42 template <class BidiIterator>
Chris@16 43 class backup_subex
Chris@16 44 {
Chris@16 45 int index;
Chris@16 46 sub_match<BidiIterator> sub;
Chris@16 47 public:
Chris@16 48 template <class A>
Chris@16 49 backup_subex(const match_results<BidiIterator, A>& w, int i)
Chris@16 50 : index(i), sub(w[i], false) {}
Chris@16 51 template <class A>
Chris@16 52 void restore(match_results<BidiIterator, A>& w)
Chris@16 53 {
Chris@16 54 w.set_first(sub.first, index, index == 0);
Chris@16 55 w.set_second(sub.second, index, sub.matched, index == 0);
Chris@16 56 }
Chris@16 57 const sub_match<BidiIterator>& get() { return sub; }
Chris@16 58 };
Chris@16 59
Chris@16 60 template <class BidiIterator, class Allocator, class traits>
Chris@16 61 bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
Chris@16 62 {
Chris@16 63 static matcher_proc_type const s_match_vtable[30] =
Chris@16 64 {
Chris@16 65 (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
Chris@16 66 &perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
Chris@16 67 &perl_matcher<BidiIterator, Allocator, traits>::match_literal,
Chris@16 68 &perl_matcher<BidiIterator, Allocator, traits>::match_start_line,
Chris@16 69 &perl_matcher<BidiIterator, Allocator, traits>::match_end_line,
Chris@16 70 &perl_matcher<BidiIterator, Allocator, traits>::match_wild,
Chris@16 71 &perl_matcher<BidiIterator, Allocator, traits>::match_match,
Chris@16 72 &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary,
Chris@16 73 &perl_matcher<BidiIterator, Allocator, traits>::match_within_word,
Chris@16 74 &perl_matcher<BidiIterator, Allocator, traits>::match_word_start,
Chris@16 75 &perl_matcher<BidiIterator, Allocator, traits>::match_word_end,
Chris@16 76 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start,
Chris@16 77 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end,
Chris@16 78 &perl_matcher<BidiIterator, Allocator, traits>::match_backref,
Chris@16 79 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set,
Chris@16 80 &perl_matcher<BidiIterator, Allocator, traits>::match_set,
Chris@16 81 &perl_matcher<BidiIterator, Allocator, traits>::match_jump,
Chris@16 82 &perl_matcher<BidiIterator, Allocator, traits>::match_alt,
Chris@16 83 &perl_matcher<BidiIterator, Allocator, traits>::match_rep,
Chris@16 84 &perl_matcher<BidiIterator, Allocator, traits>::match_combining,
Chris@16 85 &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end,
Chris@16 86 &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue,
Chris@16 87 // Although this next line *should* be evaluated at compile time, in practice
Chris@16 88 // some compilers (VC++) emit run-time initialisation which breaks thread
Chris@16 89 // safety, so use a dispatch function instead:
Chris@16 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),
Chris@16 91 &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch,
Chris@16 92 &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat,
Chris@16 93 &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
Chris@16 94 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
Chris@16 95 &perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
Chris@16 96 &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
Chris@16 97 &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
Chris@16 98 &perl_matcher<BidiIterator, Allocator, traits>::match_recursion,
Chris@16 99 };
Chris@16 100
Chris@16 101 if(state_count > max_state_count)
Chris@16 102 raise_error(traits_inst, regex_constants::error_complexity);
Chris@16 103 while(pstate)
Chris@16 104 {
Chris@16 105 matcher_proc_type proc = s_match_vtable[pstate->type];
Chris@16 106 ++state_count;
Chris@16 107 if(!(this->*proc)())
Chris@16 108 {
Chris@16 109 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
Chris@16 110 m_has_partial_match = true;
Chris@16 111 return 0;
Chris@16 112 }
Chris@16 113 }
Chris@16 114 return true;
Chris@16 115 }
Chris@16 116
Chris@16 117 template <class BidiIterator, class Allocator, class traits>
Chris@16 118 bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
Chris@16 119 {
Chris@16 120 int index = static_cast<const re_brace*>(pstate)->index;
Chris@16 121 icase = static_cast<const re_brace*>(pstate)->icase;
Chris@16 122 bool r = true;
Chris@16 123 switch(index)
Chris@16 124 {
Chris@16 125 case 0:
Chris@16 126 pstate = pstate->next.p;
Chris@16 127 break;
Chris@16 128 case -1:
Chris@16 129 case -2:
Chris@16 130 {
Chris@16 131 // forward lookahead assert:
Chris@16 132 BidiIterator old_position(position);
Chris@16 133 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
Chris@16 134 pstate = pstate->next.p->next.p;
Chris@16 135 r = match_all_states();
Chris@16 136 pstate = next_pstate;
Chris@16 137 position = old_position;
Chris@16 138 if((r && (index != -1)) || (!r && (index != -2)))
Chris@16 139 r = false;
Chris@16 140 else
Chris@16 141 r = true;
Chris@16 142 break;
Chris@16 143 }
Chris@16 144 case -3:
Chris@16 145 {
Chris@16 146 // independent sub-expression:
Chris@16 147 bool old_independent = m_independent;
Chris@16 148 m_independent = true;
Chris@16 149 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
Chris@16 150 pstate = pstate->next.p->next.p;
Chris@16 151 r = match_all_states();
Chris@16 152 pstate = next_pstate;
Chris@16 153 m_independent = old_independent;
Chris@16 154 #ifdef BOOST_REGEX_MATCH_EXTRA
Chris@16 155 if(r && (m_match_flags & match_extra))
Chris@16 156 {
Chris@16 157 //
Chris@16 158 // our captures have been stored in *m_presult
Chris@16 159 // we need to unpack them, and insert them
Chris@16 160 // back in the right order when we unwind the stack:
Chris@16 161 //
Chris@16 162 unsigned i;
Chris@16 163 match_results<BidiIterator, Allocator> tm(*m_presult);
Chris@16 164 for(i = 0; i < tm.size(); ++i)
Chris@16 165 (*m_presult)[i].get_captures().clear();
Chris@16 166 // match everything else:
Chris@16 167 r = match_all_states();
Chris@16 168 // now place the stored captures back:
Chris@16 169 for(i = 0; i < tm.size(); ++i)
Chris@16 170 {
Chris@16 171 typedef typename sub_match<BidiIterator>::capture_sequence_type seq;
Chris@16 172 seq& s1 = (*m_presult)[i].get_captures();
Chris@16 173 const seq& s2 = tm[i].captures();
Chris@16 174 s1.insert(
Chris@16 175 s1.end(),
Chris@16 176 s2.begin(),
Chris@16 177 s2.end());
Chris@16 178 }
Chris@16 179 }
Chris@16 180 #endif
Chris@16 181 break;
Chris@16 182 }
Chris@16 183 case -4:
Chris@16 184 {
Chris@16 185 // conditional expression:
Chris@16 186 const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
Chris@16 187 BOOST_ASSERT(alt->type == syntax_element_alt);
Chris@16 188 pstate = alt->next.p;
Chris@16 189 if(pstate->type == syntax_element_assert_backref)
Chris@16 190 {
Chris@16 191 if(!match_assert_backref())
Chris@16 192 pstate = alt->alt.p;
Chris@16 193 break;
Chris@16 194 }
Chris@16 195 else
Chris@16 196 {
Chris@16 197 // zero width assertion, have to match this recursively:
Chris@16 198 BOOST_ASSERT(pstate->type == syntax_element_startmark);
Chris@16 199 bool negated = static_cast<const re_brace*>(pstate)->index == -2;
Chris@16 200 BidiIterator saved_position = position;
Chris@16 201 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
Chris@16 202 pstate = pstate->next.p->next.p;
Chris@16 203 bool res = match_all_states();
Chris@16 204 position = saved_position;
Chris@16 205 if(negated)
Chris@16 206 res = !res;
Chris@16 207 if(res)
Chris@16 208 pstate = next_pstate;
Chris@16 209 else
Chris@16 210 pstate = alt->alt.p;
Chris@16 211 break;
Chris@16 212 }
Chris@16 213 }
Chris@16 214 case -5:
Chris@16 215 {
Chris@16 216 // Reset start of $0, since we have a \K escape
Chris@16 217 backup_subex<BidiIterator> sub(*m_presult, 0);
Chris@16 218 m_presult->set_first(position, 0, true);
Chris@16 219 pstate = pstate->next.p;
Chris@16 220 r = match_all_states();
Chris@16 221 if(r == false)
Chris@16 222 sub.restore(*m_presult);
Chris@16 223 break;
Chris@16 224 }
Chris@16 225 default:
Chris@16 226 {
Chris@16 227 BOOST_ASSERT(index > 0);
Chris@16 228 if((m_match_flags & match_nosubs) == 0)
Chris@16 229 {
Chris@16 230 backup_subex<BidiIterator> sub(*m_presult, index);
Chris@16 231 m_presult->set_first(position, index);
Chris@16 232 pstate = pstate->next.p;
Chris@16 233 r = match_all_states();
Chris@16 234 if(r == false)
Chris@16 235 sub.restore(*m_presult);
Chris@16 236 #ifdef BOOST_REGEX_MATCH_EXTRA
Chris@16 237 //
Chris@16 238 // we have a match, push the capture information onto the stack:
Chris@16 239 //
Chris@16 240 else if(sub.get().matched && (match_extra & m_match_flags))
Chris@16 241 ((*m_presult)[index]).get_captures().push_back(sub.get());
Chris@16 242 #endif
Chris@16 243 }
Chris@16 244 else
Chris@16 245 {
Chris@16 246 pstate = pstate->next.p;
Chris@16 247 }
Chris@16 248 break;
Chris@16 249 }
Chris@16 250 }
Chris@16 251 return r;
Chris@16 252 }
Chris@16 253
Chris@16 254 template <class BidiIterator, class Allocator, class traits>
Chris@16 255 bool perl_matcher<BidiIterator, Allocator, traits>::match_alt()
Chris@16 256 {
Chris@16 257 bool take_first, take_second;
Chris@16 258 const re_alt* jmp = static_cast<const re_alt*>(pstate);
Chris@16 259
Chris@16 260 // find out which of these two alternatives we need to take:
Chris@16 261 if(position == last)
Chris@16 262 {
Chris@16 263 take_first = jmp->can_be_null & mask_take;
Chris@16 264 take_second = jmp->can_be_null & mask_skip;
Chris@16 265 }
Chris@16 266 else
Chris@16 267 {
Chris@16 268 take_first = can_start(*position, jmp->_map, (unsigned char)mask_take);
Chris@16 269 take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip);
Chris@16 270 }
Chris@16 271
Chris@16 272 if(take_first)
Chris@16 273 {
Chris@16 274 // we can take the first alternative,
Chris@16 275 // see if we need to push next alternative:
Chris@16 276 if(take_second)
Chris@16 277 {
Chris@16 278 BidiIterator oldposition(position);
Chris@16 279 const re_syntax_base* old_pstate = jmp->alt.p;
Chris@16 280 pstate = pstate->next.p;
Chris@16 281 if(!match_all_states())
Chris@16 282 {
Chris@16 283 pstate = old_pstate;
Chris@16 284 position = oldposition;
Chris@16 285 }
Chris@16 286 return true;
Chris@16 287 }
Chris@16 288 pstate = pstate->next.p;
Chris@16 289 return true;
Chris@16 290 }
Chris@16 291 if(take_second)
Chris@16 292 {
Chris@16 293 pstate = jmp->alt.p;
Chris@16 294 return true;
Chris@16 295 }
Chris@16 296 return false; // neither option is possible
Chris@16 297 }
Chris@16 298
Chris@16 299 template <class BidiIterator, class Allocator, class traits>
Chris@16 300 bool perl_matcher<BidiIterator, Allocator, traits>::match_rep()
Chris@16 301 {
Chris@16 302 #ifdef BOOST_MSVC
Chris@16 303 #pragma warning(push)
Chris@16 304 #pragma warning(disable:4127 4244)
Chris@16 305 #endif
Chris@16 306 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 307 //
Chris@16 308 // Always copy the repeat count, so that the state is restored
Chris@16 309 // when we exit this scope:
Chris@16 310 //
Chris@16 311 repeater_count<BidiIterator> r(rep->state_id, &next_count, position);
Chris@16 312 //
Chris@16 313 // If we've had at least one repeat already, and the last one
Chris@16 314 // matched the NULL string then set the repeat count to
Chris@16 315 // maximum:
Chris@16 316 //
Chris@16 317 next_count->check_null_repeat(position, rep->max);
Chris@16 318
Chris@16 319 // find out which of these two alternatives we need to take:
Chris@16 320 bool take_first, take_second;
Chris@16 321 if(position == last)
Chris@16 322 {
Chris@16 323 take_first = rep->can_be_null & mask_take;
Chris@16 324 take_second = rep->can_be_null & mask_skip;
Chris@16 325 }
Chris@16 326 else
Chris@16 327 {
Chris@16 328 take_first = can_start(*position, rep->_map, (unsigned char)mask_take);
Chris@16 329 take_second = can_start(*position, rep->_map, (unsigned char)mask_skip);
Chris@16 330 }
Chris@16 331
Chris@16 332 if(next_count->get_count() < rep->min)
Chris@16 333 {
Chris@16 334 // we must take the repeat:
Chris@16 335 if(take_first)
Chris@16 336 {
Chris@16 337 // increase the counter:
Chris@16 338 ++(*next_count);
Chris@16 339 pstate = rep->next.p;
Chris@16 340 return match_all_states();
Chris@16 341 }
Chris@16 342 return false;
Chris@16 343 }
Chris@16 344 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 345 if(greedy)
Chris@16 346 {
Chris@16 347 // try and take the repeat if we can:
Chris@16 348 if((next_count->get_count() < rep->max) && take_first)
Chris@16 349 {
Chris@16 350 // store position in case we fail:
Chris@16 351 BidiIterator pos = position;
Chris@16 352 // increase the counter:
Chris@16 353 ++(*next_count);
Chris@16 354 pstate = rep->next.p;
Chris@16 355 if(match_all_states())
Chris@16 356 return true;
Chris@16 357 // failed repeat, reset posistion and fall through for alternative:
Chris@16 358 position = pos;
Chris@16 359 }
Chris@16 360 if(take_second)
Chris@16 361 {
Chris@16 362 pstate = rep->alt.p;
Chris@16 363 return true;
Chris@16 364 }
Chris@16 365 return false; // can't take anything, fail...
Chris@16 366 }
Chris@16 367 else // non-greedy
Chris@16 368 {
Chris@16 369 // try and skip the repeat if we can:
Chris@16 370 if(take_second)
Chris@16 371 {
Chris@16 372 // store position in case we fail:
Chris@16 373 BidiIterator pos = position;
Chris@16 374 pstate = rep->alt.p;
Chris@16 375 if(match_all_states())
Chris@16 376 return true;
Chris@16 377 // failed alternative, reset posistion and fall through for repeat:
Chris@16 378 position = pos;
Chris@16 379 }
Chris@16 380 if((next_count->get_count() < rep->max) && take_first)
Chris@16 381 {
Chris@16 382 // increase the counter:
Chris@16 383 ++(*next_count);
Chris@16 384 pstate = rep->next.p;
Chris@16 385 return match_all_states();
Chris@16 386 }
Chris@16 387 }
Chris@16 388 return false;
Chris@16 389 #ifdef BOOST_MSVC
Chris@16 390 #pragma warning(pop)
Chris@16 391 #endif
Chris@16 392 }
Chris@16 393
Chris@16 394 template <class BidiIterator, class Allocator, class traits>
Chris@16 395 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
Chris@16 396 {
Chris@16 397 #ifdef BOOST_MSVC
Chris@16 398 #pragma warning(push)
Chris@16 399 #pragma warning(disable:4127)
Chris@16 400 #endif
Chris@16 401 unsigned count = 0;
Chris@16 402 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 403 re_syntax_base* psingle = rep->next.p;
Chris@16 404 // match compulsary repeats first:
Chris@16 405 while(count < rep->min)
Chris@16 406 {
Chris@16 407 pstate = psingle;
Chris@16 408 if(!match_wild())
Chris@16 409 return false;
Chris@16 410 ++count;
Chris@16 411 }
Chris@16 412 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 413 if(greedy)
Chris@16 414 {
Chris@16 415 // normal repeat:
Chris@16 416 while(count < rep->max)
Chris@16 417 {
Chris@16 418 pstate = psingle;
Chris@16 419 if(!match_wild())
Chris@16 420 break;
Chris@16 421 ++count;
Chris@16 422 }
Chris@16 423 if((rep->leading) && (count < rep->max))
Chris@16 424 restart = position;
Chris@16 425 pstate = rep;
Chris@16 426 return backtrack_till_match(count - rep->min);
Chris@16 427 }
Chris@16 428 else
Chris@16 429 {
Chris@16 430 // non-greedy, keep trying till we get a match:
Chris@16 431 BidiIterator save_pos;
Chris@16 432 do
Chris@16 433 {
Chris@16 434 if((rep->leading) && (rep->max == UINT_MAX))
Chris@16 435 restart = position;
Chris@16 436 pstate = rep->alt.p;
Chris@16 437 save_pos = position;
Chris@16 438 ++state_count;
Chris@16 439 if(match_all_states())
Chris@16 440 return true;
Chris@16 441 if(count >= rep->max)
Chris@16 442 return false;
Chris@16 443 ++count;
Chris@16 444 pstate = psingle;
Chris@16 445 position = save_pos;
Chris@16 446 if(!match_wild())
Chris@16 447 return false;
Chris@16 448 }while(true);
Chris@16 449 }
Chris@16 450 #ifdef BOOST_MSVC
Chris@16 451 #pragma warning(pop)
Chris@16 452 #endif
Chris@16 453 }
Chris@16 454
Chris@16 455 template <class BidiIterator, class Allocator, class traits>
Chris@16 456 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
Chris@16 457 {
Chris@16 458 #ifdef BOOST_MSVC
Chris@16 459 #pragma warning(push)
Chris@16 460 #pragma warning(disable:4127)
Chris@16 461 #endif
Chris@16 462 if(m_match_flags & match_not_dot_null)
Chris@16 463 return match_dot_repeat_slow();
Chris@16 464 if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
Chris@16 465 return match_dot_repeat_slow();
Chris@16 466 //
Chris@16 467 // start by working out how much we can skip:
Chris@16 468 //
Chris@16 469 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 470 #ifdef BOOST_MSVC
Chris@16 471 #pragma warning(push)
Chris@16 472 #pragma warning(disable:4267)
Chris@16 473 #endif
Chris@16 474 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 475 std::size_t count = (std::min)(static_cast<std::size_t>(::boost::re_detail::distance(position, last)), static_cast<std::size_t>(greedy ? rep->max : rep->min));
Chris@16 476 if(rep->min > count)
Chris@16 477 {
Chris@16 478 position = last;
Chris@16 479 return false; // not enough text left to match
Chris@16 480 }
Chris@16 481 std::advance(position, count);
Chris@16 482 #ifdef BOOST_MSVC
Chris@16 483 #pragma warning(pop)
Chris@16 484 #endif
Chris@16 485 if((rep->leading) && (count < rep->max) && greedy)
Chris@16 486 restart = position;
Chris@16 487 if(greedy)
Chris@16 488 return backtrack_till_match(count - rep->min);
Chris@16 489
Chris@16 490 // non-greedy, keep trying till we get a match:
Chris@16 491 BidiIterator save_pos;
Chris@16 492 do
Chris@16 493 {
Chris@16 494 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
Chris@16 495 {
Chris@16 496 ++position;
Chris@16 497 ++count;
Chris@16 498 }
Chris@16 499 if((rep->leading) && (rep->max == UINT_MAX))
Chris@16 500 restart = position;
Chris@16 501 pstate = rep->alt.p;
Chris@16 502 save_pos = position;
Chris@16 503 ++state_count;
Chris@16 504 if(match_all_states())
Chris@16 505 return true;
Chris@16 506 if(count >= rep->max)
Chris@16 507 return false;
Chris@16 508 if(save_pos == last)
Chris@16 509 return false;
Chris@16 510 position = ++save_pos;
Chris@16 511 ++count;
Chris@16 512 }while(true);
Chris@16 513 #ifdef BOOST_MSVC
Chris@16 514 #pragma warning(pop)
Chris@16 515 #endif
Chris@16 516 }
Chris@16 517
Chris@16 518 template <class BidiIterator, class Allocator, class traits>
Chris@16 519 bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
Chris@16 520 {
Chris@16 521 #ifdef BOOST_MSVC
Chris@16 522 #pragma warning(push)
Chris@16 523 #pragma warning(disable:4127)
Chris@16 524 #pragma warning(disable:4267)
Chris@16 525 #endif
Chris@16 526 #ifdef __BORLANDC__
Chris@16 527 #pragma option push -w-8008 -w-8066 -w-8004
Chris@16 528 #endif
Chris@16 529 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 530 BOOST_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length);
Chris@16 531 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
Chris@16 532 //
Chris@16 533 // start by working out how much we can skip:
Chris@16 534 //
Chris@16 535 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 536 std::size_t count, desired;
Chris@16 537 if(::boost::is_random_access_iterator<BidiIterator>::value)
Chris@16 538 {
Chris@16 539 desired =
Chris@16 540 (std::min)(
Chris@16 541 (std::size_t)(greedy ? rep->max : rep->min),
Chris@16 542 (std::size_t)::boost::re_detail::distance(position, last));
Chris@16 543 count = desired;
Chris@16 544 ++desired;
Chris@16 545 if(icase)
Chris@16 546 {
Chris@16 547 while(--desired && (traits_inst.translate_nocase(*position) == what))
Chris@16 548 {
Chris@16 549 ++position;
Chris@16 550 }
Chris@16 551 }
Chris@16 552 else
Chris@16 553 {
Chris@16 554 while(--desired && (traits_inst.translate(*position) == what))
Chris@16 555 {
Chris@16 556 ++position;
Chris@16 557 }
Chris@16 558 }
Chris@16 559 count = count - desired;
Chris@16 560 }
Chris@16 561 else
Chris@16 562 {
Chris@16 563 count = 0;
Chris@16 564 desired = greedy ? rep->max : rep->min;
Chris@16 565 while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what))
Chris@16 566 {
Chris@16 567 ++position;
Chris@16 568 ++count;
Chris@16 569 }
Chris@16 570 }
Chris@16 571 if((rep->leading) && (count < rep->max) && greedy)
Chris@16 572 restart = position;
Chris@16 573 if(count < rep->min)
Chris@16 574 return false;
Chris@16 575
Chris@16 576 if(greedy)
Chris@16 577 return backtrack_till_match(count - rep->min);
Chris@16 578
Chris@16 579 // non-greedy, keep trying till we get a match:
Chris@16 580 BidiIterator save_pos;
Chris@16 581 do
Chris@16 582 {
Chris@16 583 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
Chris@16 584 {
Chris@16 585 if((traits_inst.translate(*position, icase) == what))
Chris@16 586 {
Chris@16 587 ++position;
Chris@16 588 ++count;
Chris@16 589 }
Chris@16 590 else
Chris@16 591 return false; // counldn't repeat even though it was the only option
Chris@16 592 }
Chris@16 593 if((rep->leading) && (rep->max == UINT_MAX))
Chris@16 594 restart = position;
Chris@16 595 pstate = rep->alt.p;
Chris@16 596 save_pos = position;
Chris@16 597 ++state_count;
Chris@16 598 if(match_all_states())
Chris@16 599 return true;
Chris@16 600 if(count >= rep->max)
Chris@16 601 return false;
Chris@16 602 position = save_pos;
Chris@16 603 if(position == last)
Chris@16 604 return false;
Chris@16 605 if(traits_inst.translate(*position, icase) == what)
Chris@16 606 {
Chris@16 607 ++position;
Chris@16 608 ++count;
Chris@16 609 }
Chris@16 610 else
Chris@16 611 {
Chris@16 612 return false;
Chris@16 613 }
Chris@16 614 }while(true);
Chris@16 615 #ifdef __BORLANDC__
Chris@16 616 #pragma option pop
Chris@16 617 #endif
Chris@16 618 #ifdef BOOST_MSVC
Chris@16 619 #pragma warning(pop)
Chris@16 620 #endif
Chris@16 621 }
Chris@16 622
Chris@16 623 template <class BidiIterator, class Allocator, class traits>
Chris@16 624 bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
Chris@16 625 {
Chris@16 626 #ifdef BOOST_MSVC
Chris@16 627 #pragma warning(push)
Chris@16 628 #pragma warning(disable:4127)
Chris@16 629 #endif
Chris@16 630 #ifdef __BORLANDC__
Chris@16 631 #pragma option push -w-8008 -w-8066 -w-8004
Chris@16 632 #endif
Chris@16 633 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 634 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
Chris@16 635 unsigned count = 0;
Chris@16 636 //
Chris@16 637 // start by working out how much we can skip:
Chris@16 638 //
Chris@16 639 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 640 std::size_t desired = greedy ? rep->max : rep->min;
Chris@16 641 if(::boost::is_random_access_iterator<BidiIterator>::value)
Chris@16 642 {
Chris@16 643 BidiIterator end = position;
Chris@16 644 // Move end forward by "desired", preferably without using distance or advance if we can
Chris@16 645 // as these can be slow for some iterator types.
Chris@16 646 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::re_detail::distance(position, last);
Chris@16 647 if(desired >= len)
Chris@16 648 end = last;
Chris@16 649 else
Chris@16 650 std::advance(end, desired);
Chris@16 651 BidiIterator origin(position);
Chris@16 652 while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
Chris@16 653 {
Chris@16 654 ++position;
Chris@16 655 }
Chris@16 656 count = (unsigned)::boost::re_detail::distance(origin, position);
Chris@16 657 }
Chris@16 658 else
Chris@16 659 {
Chris@16 660 while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
Chris@16 661 {
Chris@16 662 ++position;
Chris@16 663 ++count;
Chris@16 664 }
Chris@16 665 }
Chris@16 666 if((rep->leading) && (count < rep->max) && greedy)
Chris@16 667 restart = position;
Chris@16 668 if(count < rep->min)
Chris@16 669 return false;
Chris@16 670
Chris@16 671 if(greedy)
Chris@16 672 return backtrack_till_match(count - rep->min);
Chris@16 673
Chris@16 674 // non-greedy, keep trying till we get a match:
Chris@16 675 BidiIterator save_pos;
Chris@16 676 do
Chris@16 677 {
Chris@16 678 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
Chris@16 679 {
Chris@16 680 if(map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
Chris@16 681 {
Chris@16 682 ++position;
Chris@16 683 ++count;
Chris@16 684 }
Chris@16 685 else
Chris@16 686 return false; // counldn't repeat even though it was the only option
Chris@16 687 }
Chris@16 688 if((rep->leading) && (rep->max == UINT_MAX))
Chris@16 689 restart = position;
Chris@16 690 pstate = rep->alt.p;
Chris@16 691 save_pos = position;
Chris@16 692 ++state_count;
Chris@16 693 if(match_all_states())
Chris@16 694 return true;
Chris@16 695 if(count >= rep->max)
Chris@16 696 return false;
Chris@16 697 position = save_pos;
Chris@16 698 if(position == last)
Chris@16 699 return false;
Chris@16 700 if(map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
Chris@16 701 {
Chris@16 702 ++position;
Chris@16 703 ++count;
Chris@16 704 }
Chris@16 705 else
Chris@16 706 {
Chris@16 707 return false;
Chris@16 708 }
Chris@16 709 }while(true);
Chris@16 710 #ifdef __BORLANDC__
Chris@16 711 #pragma option pop
Chris@16 712 #endif
Chris@16 713 #ifdef BOOST_MSVC
Chris@16 714 #pragma warning(pop)
Chris@16 715 #endif
Chris@16 716 }
Chris@16 717
Chris@16 718 template <class BidiIterator, class Allocator, class traits>
Chris@16 719 bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
Chris@16 720 {
Chris@16 721 #ifdef BOOST_MSVC
Chris@16 722 #pragma warning(push)
Chris@16 723 #pragma warning(disable:4127)
Chris@16 724 #endif
Chris@16 725 #ifdef __BORLANDC__
Chris@16 726 #pragma option push -w-8008 -w-8066 -w-8004
Chris@16 727 #endif
Chris@16 728 typedef typename traits::char_class_type char_class_type;
Chris@16 729 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 730 const re_set_long<char_class_type>* set = static_cast<const re_set_long<char_class_type>*>(pstate->next.p);
Chris@16 731 unsigned count = 0;
Chris@16 732 //
Chris@16 733 // start by working out how much we can skip:
Chris@16 734 //
Chris@16 735 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
Chris@16 736 std::size_t desired = greedy ? rep->max : rep->min;
Chris@16 737 if(::boost::is_random_access_iterator<BidiIterator>::value)
Chris@16 738 {
Chris@16 739 BidiIterator end = position;
Chris@16 740 // Move end forward by "desired", preferably without using distance or advance if we can
Chris@16 741 // as these can be slow for some iterator types.
Chris@16 742 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::re_detail::distance(position, last);
Chris@16 743 if(desired >= len)
Chris@16 744 end = last;
Chris@16 745 else
Chris@16 746 std::advance(end, desired);
Chris@16 747 BidiIterator origin(position);
Chris@16 748 while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
Chris@16 749 {
Chris@16 750 ++position;
Chris@16 751 }
Chris@16 752 count = (unsigned)::boost::re_detail::distance(origin, position);
Chris@16 753 }
Chris@16 754 else
Chris@16 755 {
Chris@16 756 while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
Chris@16 757 {
Chris@16 758 ++position;
Chris@16 759 ++count;
Chris@16 760 }
Chris@16 761 }
Chris@16 762 if((rep->leading) && (count < rep->max) && greedy)
Chris@16 763 restart = position;
Chris@16 764 if(count < rep->min)
Chris@16 765 return false;
Chris@16 766
Chris@16 767 if(greedy)
Chris@16 768 return backtrack_till_match(count - rep->min);
Chris@16 769
Chris@16 770 // non-greedy, keep trying till we get a match:
Chris@16 771 BidiIterator save_pos;
Chris@16 772 do
Chris@16 773 {
Chris@16 774 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
Chris@16 775 {
Chris@16 776 if(position != re_is_set_member(position, last, set, re.get_data(), icase))
Chris@16 777 {
Chris@16 778 ++position;
Chris@16 779 ++count;
Chris@16 780 }
Chris@16 781 else
Chris@16 782 return false; // counldn't repeat even though it was the only option
Chris@16 783 }
Chris@16 784 if((rep->leading) && (rep->max == UINT_MAX))
Chris@16 785 restart = position;
Chris@16 786 pstate = rep->alt.p;
Chris@16 787 save_pos = position;
Chris@16 788 ++state_count;
Chris@16 789 if(match_all_states())
Chris@16 790 return true;
Chris@16 791 if(count >= rep->max)
Chris@16 792 return false;
Chris@16 793 position = save_pos;
Chris@16 794 if(position == last)
Chris@16 795 return false;
Chris@16 796 if(position != re_is_set_member(position, last, set, re.get_data(), icase))
Chris@16 797 {
Chris@16 798 ++position;
Chris@16 799 ++count;
Chris@16 800 }
Chris@16 801 else
Chris@16 802 {
Chris@16 803 return false;
Chris@16 804 }
Chris@16 805 }while(true);
Chris@16 806 #ifdef __BORLANDC__
Chris@16 807 #pragma option pop
Chris@16 808 #endif
Chris@16 809 #ifdef BOOST_MSVC
Chris@16 810 #pragma warning(pop)
Chris@16 811 #endif
Chris@16 812 }
Chris@16 813
Chris@16 814 template <class BidiIterator, class Allocator, class traits>
Chris@16 815 bool perl_matcher<BidiIterator, Allocator, traits>::backtrack_till_match(std::size_t count)
Chris@16 816 {
Chris@16 817 #ifdef BOOST_MSVC
Chris@16 818 #pragma warning(push)
Chris@16 819 #pragma warning(disable:4127)
Chris@16 820 #endif
Chris@16 821 if((m_match_flags & match_partial) && (position == last))
Chris@16 822 m_has_partial_match = true;
Chris@16 823
Chris@16 824 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
Chris@16 825 BidiIterator backtrack = position;
Chris@16 826 if(position == last)
Chris@16 827 {
Chris@16 828 if(rep->can_be_null & mask_skip)
Chris@16 829 {
Chris@16 830 pstate = rep->alt.p;
Chris@16 831 if(match_all_states())
Chris@16 832 return true;
Chris@16 833 }
Chris@16 834 if(count)
Chris@16 835 {
Chris@16 836 position = --backtrack;
Chris@16 837 --count;
Chris@16 838 }
Chris@16 839 else
Chris@16 840 return false;
Chris@16 841 }
Chris@16 842 do
Chris@16 843 {
Chris@16 844 while(count && !can_start(*position, rep->_map, mask_skip))
Chris@16 845 {
Chris@16 846 --position;
Chris@16 847 --count;
Chris@16 848 ++state_count;
Chris@16 849 }
Chris@16 850 pstate = rep->alt.p;
Chris@16 851 backtrack = position;
Chris@16 852 if(match_all_states())
Chris@16 853 return true;
Chris@16 854 if(count == 0)
Chris@16 855 return false;
Chris@16 856 position = --backtrack;
Chris@16 857 ++state_count;
Chris@16 858 --count;
Chris@16 859 }while(true);
Chris@16 860 #ifdef BOOST_MSVC
Chris@16 861 #pragma warning(pop)
Chris@16 862 #endif
Chris@16 863 }
Chris@16 864
Chris@16 865 template <class BidiIterator, class Allocator, class traits>
Chris@16 866 bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
Chris@16 867 {
Chris@16 868 BOOST_ASSERT(pstate->type == syntax_element_recurse);
Chris@16 869 //
Chris@16 870 // Set new call stack:
Chris@16 871 //
Chris@16 872 if(recursion_stack.capacity() == 0)
Chris@16 873 {
Chris@16 874 recursion_stack.reserve(50);
Chris@16 875 }
Chris@16 876 recursion_stack.push_back(recursion_info<results_type>());
Chris@16 877 recursion_stack.back().preturn_address = pstate->next.p;
Chris@16 878 recursion_stack.back().results = *m_presult;
Chris@16 879 recursion_stack.back().repeater_stack = next_count;
Chris@16 880 pstate = static_cast<const re_jump*>(pstate)->alt.p;
Chris@16 881 recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
Chris@16 882
Chris@16 883 repeater_count<BidiIterator>* saved = next_count;
Chris@16 884 repeater_count<BidiIterator> r(&next_count); // resets all repeat counts since we're recursing and starting fresh on those
Chris@16 885 next_count = &r;
Chris@16 886 bool result = match_all_states();
Chris@16 887 next_count = saved;
Chris@16 888
Chris@16 889 if(!result)
Chris@16 890 {
Chris@16 891 next_count = recursion_stack.back().repeater_stack;
Chris@16 892 *m_presult = recursion_stack.back().results;
Chris@16 893 recursion_stack.pop_back();
Chris@16 894 return false;
Chris@16 895 }
Chris@16 896 return true;
Chris@16 897 }
Chris@16 898
Chris@16 899 template <class BidiIterator, class Allocator, class traits>
Chris@16 900 bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
Chris@16 901 {
Chris@16 902 int index = static_cast<const re_brace*>(pstate)->index;
Chris@16 903 icase = static_cast<const re_brace*>(pstate)->icase;
Chris@16 904 if(index > 0)
Chris@16 905 {
Chris@16 906 if((m_match_flags & match_nosubs) == 0)
Chris@16 907 {
Chris@16 908 m_presult->set_second(position, index);
Chris@16 909 }
Chris@16 910 if(!recursion_stack.empty())
Chris@16 911 {
Chris@16 912 if(index == recursion_stack.back().idx)
Chris@16 913 {
Chris@16 914 recursion_info<results_type> saved = recursion_stack.back();
Chris@16 915 recursion_stack.pop_back();
Chris@16 916 pstate = saved.preturn_address;
Chris@16 917 repeater_count<BidiIterator>* saved_count = next_count;
Chris@16 918 next_count = saved.repeater_stack;
Chris@16 919 *m_presult = saved.results;
Chris@16 920 if(!match_all_states())
Chris@16 921 {
Chris@16 922 recursion_stack.push_back(saved);
Chris@16 923 next_count = saved_count;
Chris@16 924 return false;
Chris@16 925 }
Chris@16 926 }
Chris@16 927 }
Chris@16 928 }
Chris@16 929 else if((index < 0) && (index != -4))
Chris@16 930 {
Chris@16 931 // matched forward lookahead:
Chris@16 932 pstate = 0;
Chris@16 933 return true;
Chris@16 934 }
Chris@16 935 pstate = pstate ? pstate->next.p : 0;
Chris@16 936 return true;
Chris@16 937 }
Chris@16 938
Chris@16 939 template <class BidiIterator, class Allocator, class traits>
Chris@16 940 bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
Chris@16 941 {
Chris@16 942 if(!recursion_stack.empty())
Chris@16 943 {
Chris@16 944 BOOST_ASSERT(0 == recursion_stack.back().idx);
Chris@16 945 const re_syntax_base* saved_state = pstate = recursion_stack.back().preturn_address;
Chris@16 946 *m_presult = recursion_stack.back().results;
Chris@16 947 recursion_stack.pop_back();
Chris@16 948 if(!match_all_states())
Chris@16 949 {
Chris@16 950 recursion_stack.push_back(recursion_info<results_type>());
Chris@16 951 recursion_stack.back().preturn_address = saved_state;
Chris@16 952 recursion_stack.back().results = *m_presult;
Chris@16 953 return false;
Chris@16 954 }
Chris@16 955 return true;
Chris@16 956 }
Chris@16 957 if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
Chris@16 958 return false;
Chris@16 959 if((m_match_flags & match_all) && (position != last))
Chris@16 960 return false;
Chris@16 961 if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base))
Chris@16 962 return false;
Chris@16 963 m_presult->set_second(position);
Chris@16 964 pstate = 0;
Chris@16 965 m_has_found_match = true;
Chris@16 966 if((m_match_flags & match_posix) == match_posix)
Chris@16 967 {
Chris@16 968 m_result.maybe_assign(*m_presult);
Chris@16 969 if((m_match_flags & match_any) == 0)
Chris@16 970 return false;
Chris@16 971 }
Chris@16 972 #ifdef BOOST_REGEX_MATCH_EXTRA
Chris@16 973 if(match_extra & m_match_flags)
Chris@16 974 {
Chris@16 975 for(unsigned i = 0; i < m_presult->size(); ++i)
Chris@16 976 if((*m_presult)[i].matched)
Chris@16 977 ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]);
Chris@16 978 }
Chris@16 979 #endif
Chris@16 980 return true;
Chris@16 981 }
Chris@16 982
Chris@16 983
Chris@16 984
Chris@16 985 } // namespace re_detail
Chris@16 986 } // namespace boost
Chris@16 987 #ifdef BOOST_MSVC
Chris@16 988 #pragma warning(pop)
Chris@16 989 #endif
Chris@16 990
Chris@16 991 #ifdef BOOST_MSVC
Chris@16 992 #pragma warning(push)
Chris@16 993 #pragma warning(disable: 4103)
Chris@16 994 #endif
Chris@16 995 #ifdef BOOST_HAS_ABI_HEADERS
Chris@16 996 # include BOOST_ABI_SUFFIX
Chris@16 997 #endif
Chris@16 998 #ifdef BOOST_MSVC
Chris@16 999 #pragma warning(pop)
Chris@16 1000 #endif
Chris@16 1001
Chris@16 1002 #endif
Chris@16 1003