|
9 | 9 | #include "return_type.hpp"
|
10 | 10 | #include "find_captures.hpp"
|
11 | 11 | #include "first.hpp"
|
| 12 | +#include "regex_count.hpp" |
12 | 13 | #include <iterator>
|
13 | 14 |
|
14 | 15 | // remove me when MSVC fix the constexpr bug
|
@@ -286,6 +287,37 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
|
286 | 287 | return evaluate(begin, current, end, f, captures, ctll::list<Tail...>());
|
287 | 288 | }
|
288 | 289 |
|
| 290 | +//check if unrollable |
| 291 | +template<typename Iterator, typename R, typename... Content, typename... Tail> |
| 292 | +constexpr auto may_unroll(ctll::list<sequence<Content...>, Tail...>, R) { |
| 293 | + return may_unroll<Iterator>(ctll::list<Content..., Tail...>{}, R{}); |
| 294 | +} |
| 295 | + |
| 296 | +template<typename Iterator, typename R, typename A, typename... Content, typename... Tail> |
| 297 | +constexpr auto may_unroll(ctll::list<select<A, Content...>, Tail...>, R) { |
| 298 | + constexpr auto length = ctre::pattern_length<Iterator>(sequence<select<Content...>, Tail...>{}, R{}); |
| 299 | + if constexpr (atomic_pattern_length(length) && !collides(calculate_first(sequence<A,Tail...>{}), calculate_first(sequence<select<Content...>, Tail...>{}))) { |
| 300 | + if constexpr (sizeof...(Content) == 1) { |
| 301 | + if constexpr (sizeof...(Tail)) |
| 302 | + return ctll::list_pop_triple<star<sequence<A,Tail...>>, sequence<Content..., Tail...>, ::std::true_type>{}; |
| 303 | + else |
| 304 | + return ctll::list_pop_triple<star<A>, sequence<Content...>, ::std::true_type>{}; |
| 305 | + } else { |
| 306 | + if constexpr (sizeof...(Tail)) |
| 307 | + return ctll::list_pop_triple<star<sequence<A,Tail...>>, sequence<select<Content...>, Tail...>, ::std::true_type>{}; |
| 308 | + else |
| 309 | + return ctll::list_pop_triple<star<A>, select<Content...>, ::std::true_type>{}; |
| 310 | + } |
| 311 | + } else { |
| 312 | + return ctll::list_pop_triple<ctll::_nothing, ctll::_nothing, ::std::false_type>{}; |
| 313 | + } |
| 314 | +} |
| 315 | + |
| 316 | +template<typename Iterator, typename R, typename T> |
| 317 | +constexpr auto may_unroll(T, R) { |
| 318 | + return ctll::list_pop_triple<ctll::_nothing, ctll::_nothing, ::std::false_type>{}; |
| 319 | +} |
| 320 | + |
289 | 321 | // lazy repeat
|
290 | 322 | template <typename R, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail>
|
291 | 323 | constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, [[maybe_unused]] const flags & f, R captures, ctll::list<lazy_repeat<A,B,Content...>, Tail...>) noexcept {
|
@@ -409,30 +441,40 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
|
409 | 441 | }
|
410 | 442 |
|
411 | 443 | #ifndef CTRE_DISABLE_GREEDY_OPT
|
412 |
| - if constexpr (!collides(calculate_first(Content{}...), calculate_first(Tail{}...))) { |
| 444 | + using unroll_t = decltype(may_unroll<Iterator>(ctll::list<Content...>{}, R{})); |
| 445 | + if constexpr (B == 0 && unroll_t{}.other) { |
| 446 | + if constexpr (A > 0) { |
| 447 | + return evaluate(begin, current, end, f, captures, ctll::list<repeat<A,A,Content...>,star<decltype(unroll_t{}.front)>, star<decltype(unroll_t{}.tail), star<decltype(unroll_t{}.front)>>, Tail...>{}); |
| 448 | + } else { |
| 449 | + return evaluate(begin, current, end, f, captures, ctll::list<star<decltype(unroll_t{}.front)>, star<decltype(unroll_t{}.tail), star<decltype(unroll_t{}.front)>>, Tail...>{}); |
| 450 | + } |
| 451 | + } else if constexpr (!collides(calculate_first(Content{}...), calculate_first(Tail{}...))) { |
413 | 452 | return evaluate(begin, current, end, f, captures, ctll::list<possessive_repeat<A,B,Content...>, Tail...>());
|
414 |
| - } |
| 453 | + } else { |
415 | 454 | #endif
|
416 |
| - |
417 |
| - // A..B |
418 |
| - size_t i{0}; |
419 |
| - while (less_than<A>(i)) { |
420 |
| - auto inner_result = evaluate(begin, current, end, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>()); |
421 |
| - |
422 |
| - if (!inner_result) return not_matched; |
423 |
| - |
424 |
| - captures = inner_result.unmatch(); |
425 |
| - current = inner_result.get_end_position(); |
426 |
| - |
427 |
| - ++i; |
428 |
| - } |
429 |
| - |
| 455 | + |
| 456 | + // A..B |
| 457 | + size_t i{ 0 }; |
| 458 | + while (less_than<A>(i)) { |
| 459 | + auto inner_result = evaluate(begin, current, end, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>()); |
| 460 | + |
| 461 | + if (!inner_result) return not_matched; |
| 462 | + |
| 463 | + captures = inner_result.unmatch(); |
| 464 | + current = inner_result.get_end_position(); |
| 465 | + |
| 466 | + ++i; |
| 467 | + } |
| 468 | + |
430 | 469 | #ifdef CTRE_MSVC_GREEDY_WORKAROUND
|
431 |
| - R result; |
432 |
| - evaluate_recursive(result, i, begin, current, end, f, captures, stack); |
433 |
| - return result; |
| 470 | + R result; |
| 471 | + evaluate_recursive(result, i, begin, current, end, f, captures, stack); |
| 472 | + return result; |
434 | 473 | #else
|
435 |
| - return evaluate_recursive(i, begin, current, end, f, captures, stack); |
| 474 | + return evaluate_recursive(i, begin, current, end, f, captures, stack); |
| 475 | +#endif |
| 476 | +#ifndef CTRE_DISABLE_GREEDY_OPT |
| 477 | + } |
436 | 478 | #endif
|
437 | 479 |
|
438 | 480 | }
|
|
0 commit comments