diff --git a/include/boost/regex/v4/perl_matcher.hpp b/include/boost/regex/v4/perl_matcher.hpp index 768fd31d..a7298fbd 100644 --- a/include/boost/regex/v4/perl_matcher.hpp +++ b/include/boost/regex/v4/perl_matcher.hpp @@ -509,6 +509,7 @@ private: // Set to false by a (*COMMIT): bool m_can_backtrack; bool m_have_accept; + bool m_have_then; #endif #ifdef BOOST_REGEX_NON_RECURSIVE // diff --git a/include/boost/regex/v4/perl_matcher_recursive.hpp b/include/boost/regex/v4/perl_matcher_recursive.hpp index da9fd61a..1e17d0a2 100644 --- a/include/boost/regex/v4/perl_matcher_recursive.hpp +++ b/include/boost/regex/v4/perl_matcher_recursive.hpp @@ -60,7 +60,7 @@ public: template bool perl_matcher::match_all_states() { - static matcher_proc_type const s_match_vtable[33] = + static matcher_proc_type const s_match_vtable[34] = { (&perl_matcher::match_startmark), &perl_matcher::match_endmark, @@ -99,6 +99,7 @@ bool perl_matcher::match_all_states() &perl_matcher::match_fail, &perl_matcher::match_accept, &perl_matcher::match_commit, + &perl_matcher::match_then, }; if(state_count > max_state_count) @@ -155,7 +156,8 @@ bool perl_matcher::match_startmark() pstate = pstate->next.p->next.p; bool can_backtrack = m_can_backtrack; r = match_all_states(); - m_can_backtrack = can_backtrack; + if(r) + m_can_backtrack = can_backtrack; pstate = next_pstate; m_independent = old_independent; #ifdef BOOST_REGEX_MATCH_EXTRA @@ -287,11 +289,19 @@ bool perl_matcher::match_alt() BidiIterator oldposition(position); const re_syntax_base* old_pstate = jmp->alt.p; pstate = pstate->next.p; + m_have_then = false; if(!match_all_states()) { pstate = old_pstate; position = oldposition; + if(m_have_then) + { + m_can_backtrack = true; + m_have_then = false; + return false; + } } + m_have_then = false; return m_can_backtrack; } pstate = pstate->next.p; @@ -1015,6 +1025,17 @@ bool perl_matcher::match_commit() return true; } +template +bool perl_matcher::match_then() +{ + pstate = pstate->next.p; + if(match_all_states()) + return true; + m_can_backtrack = false; + m_have_then = true; + return false; +} + template bool perl_matcher::skip_until_paren(int index, bool match) { diff --git a/test/regress/test_perl_ex.cpp b/test/regress/test_perl_ex.cpp index a5132d09..4aad26d4 100644 --- a/test/regress/test_perl_ex.cpp +++ b/test/regress/test_perl_ex.cpp @@ -1000,63 +1000,4 @@ void test_verbs() TEST_REGEX_SEARCH("(?:a+(*THEN)\\w{6}|x\\w{3})", perl, "aaaxxxxx", match_default, make_array(3, 7, -2, -2)); TEST_REGEX_SEARCH("(?>(*COMMIT)(?>yes|no)(*THEN)(*F))?", perl, "yes", match_default, make_array(-2, -2)); TEST_REGEX_SEARCH("(?>(*COMMIT)(yes|no)(*THEN)(*F))?", perl, "yes", match_default, make_array(-2, -2)); - - -#if 0 - - -# Check the use of names for failure - -/^(A(*PRUNE:A)B|C(*PRUNE:B)D)/mark - ** Failers - AC - CB - -/(*MARK:A)(*SKIP:B)(C|X)/mark - C - D - -/^(A(*THEN:A)B|C(*THEN:B)D)/mark - ** Failers - CB - -/^(?:A(*THEN:A)B|C(*THEN:B)D)/mark - CB - -/^(?>A(*THEN:A)B|C(*THEN:B)D)/mark - CB - -# This should succeed, as the skip causes bump to offset 1 (the mark). Note -# that we have to have something complicated such as (B|Z) at the end because, -# for Perl, a simple character somehow causes an unwanted optimization to mess -# with the handling of backtracking verbs. - -/A(*MARK:A)A+(*SKIP:A)(B|Z) | AC/x,mark - AAAC - -# Test skipping over a non-matching mark. - -/A(*MARK:A)A+(*MARK:B)(*SKIP:A)(B|Z) | AC/x,mark - AAAC - -# Check shorthand for MARK. - -/A(*:A)A+(*SKIP:A)(B|Z) | AC/x,mark - AAAC - -/(*:A)A+(*SKIP:A)(B|Z)/mark - AAAC - -# This should succeed, as a non-existent skip name disables the skip. - -/A(*MARK:A)A+(*SKIP:B)(B|Z) | AC/x,mark - AAAC - -/A(*MARK:A)A+(*SKIP:B)(B|Z) | AC(*:B)/x,mark - AAAC - - -#endif - - }