diff --git a/include/boost/regex/v4/basic_regex_parser.hpp b/include/boost/regex/v4/basic_regex_parser.hpp index c7a86ac5..8252991c 100644 --- a/include/boost/regex/v4/basic_regex_parser.hpp +++ b/include/boost/regex/v4/basic_regex_parser.hpp @@ -2715,7 +2715,31 @@ bool basic_regex_parser::parse_perl_verb() this->append_state(syntax_element_fail); return true; } - return false; + break; + case 'A': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(match_verb("CCEPT")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + this->append_state(syntax_element_accept); + return true; + } + break; } return false; } diff --git a/include/boost/regex/v4/perl_matcher.hpp b/include/boost/regex/v4/perl_matcher.hpp index b6588978..f165da7e 100644 --- a/include/boost/regex/v4/perl_matcher.hpp +++ b/include/boost/regex/v4/perl_matcher.hpp @@ -444,6 +444,7 @@ private: #endif bool match_recursion(); bool match_fail(); + bool match_accept(); // find procs stored in s_find_vtable: bool find_restart_any(); diff --git a/include/boost/regex/v4/perl_matcher_common.hpp b/include/boost/regex/v4/perl_matcher_common.hpp index ddb8fadd..e4282ca9 100644 --- a/include/boost/regex/v4/perl_matcher_common.hpp +++ b/include/boost/regex/v4/perl_matcher_common.hpp @@ -800,6 +800,20 @@ bool perl_matcher::match_fail() return false; } +template +bool perl_matcher::match_accept() +{ + // Almost the same as match_match, but we need to close any half-open capturing groups: + for(unsigned i = 1; i < m_result.size(); ++i) + { + if((m_result[i].matched == false) && (m_result[i].first != last)) + { + m_result.set_second(position, i); + } + } + return match_match(); +} + template bool perl_matcher::find_restart_any() diff --git a/include/boost/regex/v4/perl_matcher_non_recursive.hpp b/include/boost/regex/v4/perl_matcher_non_recursive.hpp index 1b3363f8..51bf8461 100644 --- a/include/boost/regex/v4/perl_matcher_non_recursive.hpp +++ b/include/boost/regex/v4/perl_matcher_non_recursive.hpp @@ -141,7 +141,7 @@ struct saved_recursion : public saved_state template bool perl_matcher::match_all_states() { - static matcher_proc_type const s_match_vtable[31] = + static matcher_proc_type const s_match_vtable[32] = { (&perl_matcher::match_startmark), &perl_matcher::match_endmark, @@ -178,6 +178,7 @@ bool perl_matcher::match_all_states() &perl_matcher::match_toggle_case, &perl_matcher::match_recursion, &perl_matcher::match_fail, + &perl_matcher::match_accept, }; push_recursion_stopper(); diff --git a/include/boost/regex/v4/perl_matcher_recursive.hpp b/include/boost/regex/v4/perl_matcher_recursive.hpp index f1d2e636..741f596e 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[31] = + static matcher_proc_type const s_match_vtable[32] = { (&perl_matcher::match_startmark), &perl_matcher::match_endmark, @@ -97,6 +97,7 @@ bool perl_matcher::match_all_states() &perl_matcher::match_toggle_case, &perl_matcher::match_recursion, &perl_matcher::match_fail, + &perl_matcher::match_accept, }; if(state_count > max_state_count) diff --git a/include/boost/regex/v4/states.hpp b/include/boost/regex/v4/states.hpp index 2caf2eaf..e6c03d07 100644 --- a/include/boost/regex/v4/states.hpp +++ b/include/boost/regex/v4/states.hpp @@ -123,6 +123,7 @@ enum syntax_element_type syntax_element_recurse = syntax_element_toggle_case + 1, // Verbs: syntax_element_fail = syntax_element_recurse + 1, + syntax_element_accept = syntax_element_fail + 1, }; #ifdef BOOST_REGEX_DEBUG diff --git a/test/regress/test_perl_ex.cpp b/test/regress/test_perl_ex.cpp index c90a1d1e..314d297c 100644 --- a/test/regress/test_perl_ex.cpp +++ b/test/regress/test_perl_ex.cpp @@ -939,4 +939,6 @@ void test_verbs() TEST_INVALID_REGEX("a+(*", perl); TEST_INVALID_REGEX("a+(*FX)", perl); TEST_REGEX_SEARCH("a+(*FAIL)b", perl, "aaaab", match_default, make_array(-2, -2)); -} \ No newline at end of file + TEST_REGEX_SEARCH("(A(A|B(*ACCEPT)|C)D)(E)", perl, "AB", match_default, make_array(0, 2, 0, 2, 1, 2, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("(A(A|B(*ACCEPT)|C)D)(E)", perl, "ACDE", match_default, make_array(0, 4, 0, 3, 1, 2, 3, 4, -2, -2)); +}