## include/boost/regex/v5/basic_regex_parser.hpp

88.1% Lines (1582/1796) 83.7% List of functions (200/239)
basic_regex_parser.hpp
f(x) Functions (239)
Function Calls Lines Blocks
boost::re_detail_600::umax(std::integral_constant<bool, false> const&) :42 97680x 100.0% 100.0% boost::re_detail_600::umax() :52 97680x 61.9% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) :65 13390x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) :65 9586x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) :65 10x 66.7% 71.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) :65 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) :65 34258x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) :65 13390x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) :65 9586x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) :65 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::basic_regex_parser(boost::re_detail_600::regex_data<char, boost::c_regex_traits<char> >*) :125 71884x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::basic_regex_parser(boost::re_detail_600::regex_data<char, boost::cpp_regex_traits<char> >*) :125 55500x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::basic_regex_parser(boost::re_detail_600::regex_data<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >*) :125 78x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::basic_regex_parser(boost::re_detail_600::regex_data<char32_t, char32_traits>*) :125 1x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::basic_regex_parser(boost::re_detail_600::regex_data<int, boost::icu_regex_traits>*) :125 152732x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::basic_regex_parser(boost::re_detail_600::regex_data<wchar_t, boost::c_regex_traits<wchar_t> >*) :125 72313x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::basic_regex_parser(boost::re_detail_600::regex_data<wchar_t, boost::cpp_regex_traits<wchar_t> >*) :125 55716x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::basic_regex_parser(boost::re_detail_600::regex_data<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >*) :125 11x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse(char const*, char const*, unsigned int) :132 71884x 91.9% 87.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse(char const*, char const*, unsigned int) :132 55500x 91.9% 87.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse(char const*, char const*, unsigned int) :132 78x 54.1% 26.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse(char32_t const*, char32_t const*, unsigned int) :132 1x 54.1% 21.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse(int const*, int const*, unsigned int) :132 152732x 91.9% 87.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse(wchar_t const*, wchar_t const*, unsigned int) :132 72313x 91.9% 87.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse(wchar_t const*, wchar_t const*, unsigned int) :132 55716x 91.9% 87.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse(wchar_t const*, wchar_t const*, unsigned int) :132 11x 54.1% 21.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::fail(boost::regex_constants::error_type, long) :208 6252x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::fail(boost::regex_constants::error_type, long) :208 4596x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::fail(boost::regex_constants::error_type, long) :208 10x 100.0% 75.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::fail(boost::regex_constants::error_type, long) :208 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::fail(boost::regex_constants::error_type, long) :208 14580x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::fail(boost::regex_constants::error_type, long) :208 6252x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::fail(boost::regex_constants::error_type, long) :208 4596x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::fail(boost::regex_constants::error_type, long) :208 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long) :216 13390x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long) :216 9586x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long) :216 10x 95.2% 69.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long) :216 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long) :216 34258x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long) :216 13390x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long) :216 9586x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::fail(boost::regex_constants::error_type, long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long) :216 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_all() :255 195403x 87.5% 53.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_all() :255 156456x 87.5% 53.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_all() :255 253x 87.5% 53.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_all() :255 1x 87.5% 46.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_all() :255 322630x 87.5% 53.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_all() :255 160549x 87.5% 53.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_all() :255 121056x 87.5% 53.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_all() :255 41x 87.5% 46.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_basic() :276 21312x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_basic() :276 21312x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_basic() :276 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_basic() :276 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_basic() :276 54204x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_basic() :276 21312x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_basic() :276 21312x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_basic() :276 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_extended() :336 1508326x 100.0% 99.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_extended() :336 1365804x 100.0% 99.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_extended() :336 5798x 78.5% 33.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_extended() :336 8x 7.7% 5.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_extended() :336 1078015x 100.0% 99.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_extended() :336 558505x 100.0% 99.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_extended() :336 414276x 100.0% 99.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_extended() :336 160x 60.0% 33.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_literal() :430 879928x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_literal() :430 830100x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_literal() :430 2527x 100.0% 90.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_literal() :430 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_literal() :430 412114x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_literal() :430 211164x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_literal() :430 160956x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_literal() :430 22x 100.0% 70.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_open_paren() :445 128331x 98.0% 99.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_open_paren() :445 104220x 98.0% 99.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_open_paren() :445 183x 80.4% 53.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_open_paren() :445 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_open_paren() :445 177938x 94.1% 74.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_open_paren() :445 92808x 98.0% 99.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_open_paren() :445 68412x 98.0% 99.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_open_paren() :445 30x 78.4% 50.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_basic_escape() :554 6696x 87.3% 82.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_basic_escape() :554 6696x 87.3% 82.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_basic_escape() :554 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_basic_escape() :554 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_basic_escape() :554 17196x 87.3% 82.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_basic_escape() :554 6696x 87.3% 82.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_basic_escape() :554 6696x 87.3% 82.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_basic_escape() :554 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_extended_escape() :700 91357x 89.2% 81.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_extended_escape() :700 81828x 89.2% 81.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_extended_escape() :700 156x 42.7% 16.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_extended_escape() :700 8x 4.3% 3.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_extended_escape() :700 68798x 89.2% 81.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_extended_escape() :700 36720x 89.2% 81.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_extended_escape() :700 26940x 89.2% 81.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_extended_escape() :700 17x 11.4% 6.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_match_any() :958 8989x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_match_any() :958 7020x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_match_any() :958 36x 100.0% 82.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_match_any() :958 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_match_any() :958 17462x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_match_any() :958 8892x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_match_any() :958 6924x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_match_any() :958 5x 100.0% 82.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_repeat(unsigned long, unsigned long) :974 98702x 93.1% 92.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_repeat(unsigned long, unsigned long) :974 82416x 93.1% 92.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_repeat(unsigned long, unsigned long) :974 269x 80.5% 53.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_repeat(unsigned long, unsigned long) :974 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_repeat(unsigned long, unsigned long) :974 133551x 93.1% 92.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_repeat(unsigned long, unsigned long) :974 66888x 93.1% 92.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_repeat(unsigned long, unsigned long) :974 50328x 93.1% 92.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_repeat(unsigned long, unsigned long) :974 35x 36.8% 30.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_repeat_range(bool) :1151 12168x 74.6% 78.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_repeat_range(bool) :1151 9096x 74.6% 78.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_repeat_range(bool) :1151 21x 36.6% 25.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_repeat_range(bool) :1151 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_repeat_range(bool) :1151 23119x 74.6% 78.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_repeat_range(bool) :1151 12156x 74.6% 78.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_repeat_range(bool) :1151 9072x 74.6% 78.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_repeat_range(bool) :1151 1x 29.6% 25.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_alt() :1291 71222x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_alt() :1291 62484x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_alt() :1291 2308x 80.8% 59.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_alt() :1291 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_alt() :1291 64642x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_alt() :1291 33408x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_alt() :1291 24540x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_alt() :1291 7x 69.2% 49.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_set() :1357 78385x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_set() :1357 72852x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_set() :1357 117x 64.8% 50.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_set() :1357 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_set() :1357 55960x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_set() :1357 25812x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_set() :1357 20172x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_set() :1357 3x 37.0% 30.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_inner_set(boost::re_detail_600::basic_char_set<char, boost::c_regex_traits<char> >&) :1449 6756x 97.9% 98.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_inner_set(boost::re_detail_600::basic_char_set<char, boost::cpp_regex_traits<char> >&) :1449 5088x 97.9% 98.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_inner_set(boost::re_detail_600::basic_char_set<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >&) :1449 68x 29.9% 14.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_inner_set(boost::re_detail_600::basic_char_set<char32_t, char32_traits>&) :1449 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_inner_set(boost::re_detail_600::basic_char_set<int, boost::icu_regex_traits>&) :1449 17873x 97.9% 98.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_inner_set(boost::re_detail_600::basic_char_set<wchar_t, boost::c_regex_traits<wchar_t> >&) :1449 6792x 97.9% 98.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_inner_set(boost::re_detail_600::basic_char_set<wchar_t, boost::cpp_regex_traits<wchar_t> >&) :1449 5112x 97.9% 98.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_inner_set(boost::re_detail_600::basic_char_set<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >&) :1449 2x 25.8% 14.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_set_literal(boost::re_detail_600::basic_char_set<char, boost::c_regex_traits<char> >&) :1611 312001x 91.7% 94.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_set_literal(boost::re_detail_600::basic_char_set<char, boost::cpp_regex_traits<char> >&) :1611 303072x 91.7% 94.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_set_literal(boost::re_detail_600::basic_char_set<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >&) :1611 156x 54.2% 56.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_set_literal(boost::re_detail_600::basic_char_set<char32_t, char32_traits>&) :1611 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_set_literal(boost::re_detail_600::basic_char_set<int, boost::icu_regex_traits>&) :1611 88498x 91.7% 94.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_set_literal(boost::re_detail_600::basic_char_set<wchar_t, boost::c_regex_traits<wchar_t> >&) :1611 44400x 91.7% 94.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_set_literal(boost::re_detail_600::basic_char_set<wchar_t, boost::cpp_regex_traits<wchar_t> >&) :1611 34944x 91.7% 94.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_set_literal(boost::re_detail_600::basic_char_set<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >&) :1611 1x 45.8% 50.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::get_next_set_literal(boost::re_detail_600::basic_char_set<char, boost::c_regex_traits<char> >&) :1655 370682x 95.0% 98.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::get_next_set_literal(boost::re_detail_600::basic_char_set<char, boost::cpp_regex_traits<char> >&) :1655 360768x 96.6% 98.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::get_next_set_literal(boost::re_detail_600::basic_char_set<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >&) :1655 159x 40.7% 29.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::get_next_set_literal(boost::re_detail_600::basic_char_set<char32_t, char32_traits>&) :1655 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::get_next_set_literal(boost::re_detail_600::basic_char_set<int, boost::icu_regex_traits>&) :1655 98412x 96.6% 98.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::get_next_set_literal(boost::re_detail_600::basic_char_set<wchar_t, boost::c_regex_traits<wchar_t> >&) :1655 49368x 95.0% 98.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::get_next_set_literal(boost::re_detail_600::basic_char_set<wchar_t, boost::cpp_regex_traits<wchar_t> >&) :1655 38880x 96.6% 98.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::get_next_set_literal(boost::re_detail_600::basic_char_set<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >&) :1655 2x 10.2% 11.0% bool boost::re_detail_600::valid_value<char32_t>(char32_t, long, std::integral_constant<bool, true> const&) :1748 0 0.0% 0.0% bool boost::re_detail_600::valid_value<char>(char, long, std::integral_constant<bool, true> const&) :1748 183864x 100.0% 100.0% bool boost::re_detail_600::valid_value<int>(int, long, std::integral_constant<bool, true> const&) :1748 720x 100.0% 100.0% bool boost::re_detail_600::valid_value<wchar_t>(wchar_t, long, std::integral_constant<bool, true> const&) :1748 696x 100.0% 100.0% bool boost::re_detail_600::valid_value<char32_t>(char32_t, long) :1758 0 0.0% 0.0% bool boost::re_detail_600::valid_value<char>(char, long) :1758 183864x 90.5% 100.0% bool boost::re_detail_600::valid_value<int>(int, long) :1758 720x 100.0% 100.0% bool boost::re_detail_600::valid_value<wchar_t>(wchar_t, long) :1758 696x 90.5% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::unescape_character() :1764 283753x 89.5% 84.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::unescape_character() :1764 280344x 89.5% 84.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::unescape_character() :1764 57x 12.1% 4.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::unescape_character() :1764 8x 14.5% 8.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::unescape_character() :1764 27128x 89.5% 84.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::unescape_character() :1764 14100x 89.5% 84.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::unescape_character() :1764 10560x 89.5% 84.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::unescape_character() :1764 1x 7.3% 3.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_backref() :1953 1752x 78.9% 75.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_backref() :1953 1320x 78.9% 75.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_backref() :1953 1x 68.4% 64.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_backref() :1953 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_backref() :1953 3336x 78.9% 75.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_backref() :1953 1752x 78.9% 75.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_backref() :1953 1320x 78.9% 75.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_backref() :1953 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_QE() :1985 324x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_QE() :1985 264x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_QE() :1985 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_QE() :1985 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_QE() :1985 672x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_QE() :1985 324x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_QE() :1985 264x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_QE() :1985 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_perl_extension() :2037 74772x 82.9% 79.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_perl_extension() :2037 64956x 82.9% 79.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_perl_extension() :2037 44x 34.9% 9.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_perl_extension() :2037 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_perl_extension() :2037 74673x 82.4% 76.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_perl_extension() :2037 39048x 82.9% 79.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_perl_extension() :2037 29028x 82.9% 79.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_perl_extension() :2037 8x 20.0% 8.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::match_verb(char const*) :2732 3096x 69.2% 68.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::match_verb(char const*) :2732 2064x 69.2% 68.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::match_verb(char const*) :2732 8x 46.2% 37.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::match_verb(char const*) :2732 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::match_verb(char const*) :2732 5172x 69.2% 68.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::match_verb(char const*) :2732 3096x 69.2% 68.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::match_verb(char const*) :2732 2064x 69.2% 68.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::match_verb(char const*) :2732 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_perl_verb() :2761 3240x 52.3% 49.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_perl_verb() :2761 2160x 52.3% 49.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_perl_verb() :2761 8x 23.4% 8.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_perl_verb() :2761 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_perl_verb() :2761 5436x 52.3% 49.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_perl_verb() :2761 3240x 52.3% 49.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_perl_verb() :2761 2160x 52.3% 49.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_perl_verb() :2761 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::add_emacs_code(bool) :2933 624x 86.2% 88.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::add_emacs_code(bool) :2933 624x 86.2% 88.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::add_emacs_code(bool) :2933 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::add_emacs_code(bool) :2933 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::add_emacs_code(bool) :2933 1560x 86.2% 88.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::add_emacs_code(bool) :2933 624x 86.2% 88.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::add_emacs_code(bool) :2933 624x 86.2% 88.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::add_emacs_code(bool) :2933 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::parse_options() :3015 6900x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::cpp_regex_traits<char> >::parse_options() :3015 4800x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::parse_options() :3015 2x 26.3% 26.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::parse_options() :3015 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::parse_options() :3015 12876x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::parse_options() :3015 7260x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::cpp_regex_traits<wchar_t> >::parse_options() :3015 5088x 100.0% 100.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::regex_traits<wchar_t, boost::cpp_regex_traits<wchar_t> > >::parse_options() :3015 0 0.0% 0.0% boost::re_detail_600::basic_regex_parser<char, boost::c_regex_traits<char> >::unwind_alts(long) :3100 35614x 78.9% 54.0% boost::re_detail_600::basic_regex_parser<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::unwind_alts(long) :3100 200x 78.9% 54.0% boost::re_detail_600::basic_regex_parser<char32_t, char32_traits>::unwind_alts(long) :3100 1x 26.3% 21.0% boost::re_detail_600::basic_regex_parser<int, boost::icu_regex_traits>::unwind_alts(long) :3100 318198x 89.5% 84.0% boost::re_detail_600::basic_regex_parser<wchar_t, boost::c_regex_traits<wchar_t> >::unwind_alts(long) :3100 36070x 78.9% 54.0%

Line | TLA | Hits | Source Code
--- | --- | --- | ---
1 |  |  | /*
2 |  |  | *
3 |  |  | * Copyright (c) 2004
4 |  |  | * John Maddock
5 |  |  | *
6 |  |  | * Use, modification and distribution are subject to the
7 |  |  | * Boost Software License, Version 1.0. (See accompanying file
8 |  |  | * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 |  |  | *
10 |  |  | */
11 |  |  |
12 |  |  | /*
13 |  |  | * LOCATION: see http://www.boost.org for most recent version.
14 |  |  | * FILE basic_regex_parser.cpp
15 |  |  | * VERSION see <boost/version.hpp>
16 |  |  | * DESCRIPTION: Declares template class basic_regex_parser.
17 |  |  | */
18 |  |  |
19 |  |  | #ifndef BOOST_REGEX_V5_BASIC_REGEX_PARSER_HPP
20 |  |  | #define BOOST_REGEX_V5_BASIC_REGEX_PARSER_HPP
21 |  |  |
22 |  |  | #include <boost/regex/v5/basic_regex_creator.hpp>
23 |  |  |
24 |  |  | #ifndef BOOST_REGEX_AS_MODULE
25 |  |  | #include <climits>
26 |  |  | #include <cstdint>
27 |  |  | #include <limits>
28 |  |  | #include <type_traits>
29 |  |  | #endif
30 |  |  |
31 |  |  | namespace boost{
32 |  |  | namespace BOOST_REGEX_DETAIL_NS{
33 |  |  |
34 |  |  | #ifdef BOOST_REGEX_MSVC
35 |  |  | #pragma warning(push)
36 |  |  | #pragma warning(disable:4244 4459)
37 |  |  | #if BOOST_REGEX_MSVC < 1910
38 |  |  | #pragma warning(disable:4800)
39 |  |  | #endif
40 |  |  | #endif
41 |  |  |
42 |  | 97680x | inline std::intmax_t umax(std::integral_constant<bool, false> const&)
43 |  |  | {
44 |  |  | // Get out clause here, just in case numeric_limits is unspecialized:
45 |  | 97680x | return std::numeric_limits<std::intmax_t>::is_specialized ? (std::numeric_limits<std::intmax_t>::max)() : INT_MAX;
46 |  |  | }
47 |  |  | inline std::intmax_t umax(std::integral_constant<bool, true> const&)
48 |  |  | {
49 |  |  | return (std::numeric_limits<std::size_t>::max)();
50 |  |  | }
51 |  |  |
52 |  | 97680x | inline std::intmax_t umax()
53 |  |  | {
54 |  | 97680x | return umax(std::integral_constant<bool, std::numeric_limits<std::intmax_t>::digits >= std::numeric_limits<std::size_t>::digits>());
55 |  |  | }
56 |  |  |
57 |  |  | template <class charT, class traits>
58 |  |  | class basic_regex_parser : public basic_regex_creator<charT, traits>
59 |  |  | {
60 |  |  | public:
61 |  |  | basic_regex_parser(regex_data<charT, traits>* data);
62 |  |  | void parse(const charT* p1, const charT* p2, unsigned flags);
63 |  |  | void fail(regex_constants::error_type error_code, std::ptrdiff_t position);
64 |  |  | void fail(regex_constants::error_type error_code, std::ptrdiff_t position, std::string message, std::ptrdiff_t start_pos);
65 |  | 80220x | void fail(regex_constants::error_type error_code, std::ptrdiff_t position, const std::string& message)
66 |  |  | {
67 |  | 80220x | fail(error_code, position, message, position);
68 |  | 65690x | }
69 |  |  |
70 |  |  | bool parse_all();
71 |  |  | bool parse_basic();
72 |  |  | bool parse_extended();
73 |  |  | bool parse_literal();
74 |  |  | bool parse_open_paren();
75 |  |  | bool parse_basic_escape();
76 |  |  | bool parse_extended_escape();
77 |  |  | bool parse_match_any();
78 |  |  | bool parse_repeat(std::size_t low = 0, std::size_t high = (std::numeric_limits<std::size_t>::max)());
79 |  |  | bool parse_repeat_range(bool isbasic);
80 |  |  | bool parse_alt();
81 |  |  | bool parse_set();
82 |  |  | bool parse_backref();
83 |  |  | void parse_set_literal(basic_char_set<charT, traits>& char_set);
84 |  |  | bool parse_inner_set(basic_char_set<charT, traits>& char_set);
85 |  |  | bool parse_QE();
86 |  |  | bool parse_perl_extension();
87 |  |  | bool parse_perl_verb();
88 |  |  | bool match_verb(const char*);
89 |  |  | bool add_emacs_code(bool negate);
90 |  |  | bool unwind_alts(std::ptrdiff_t last_paren_start);
91 |  |  | digraph<charT> get_next_set_literal(basic_char_set<charT, traits>& char_set);
92 |  |  | charT unescape_character();
93 |  |  | regex_constants::syntax_option_type parse_options();
94 |  |  |
95 |  |  | private:
96 |  |  | typedef bool (basic_regex_parser::*parser_proc_type)();
97 |  |  | typedef typename traits::string_type string_type;
98 |  |  | typedef typename traits::char_class_type char_class_type;
99 |  |  | parser_proc_type m_parser_proc; // the main parser to use
100 |  |  | const charT* m_base; // the start of the string being parsed
101 |  |  | const charT* m_end; // the end of the string being parsed
102 |  |  | const charT* m_position; // our current parser position
103 |  |  | unsigned m_mark_count; // how many sub-expressions we have
104 |  |  | int m_mark_reset; // used to indicate that we're inside a (?|...) block.
105 |  |  | unsigned m_max_mark; // largest mark count seen inside a (?|...) block.
106 |  |  | std::ptrdiff_t m_paren_start; // where the last seen ')' began (where repeats are inserted).
107 |  |  | std::ptrdiff_t m_alt_insert_point; // where to insert the next alternative
108 |  |  | bool m_has_case_change; // true if somewhere in the current block the case has changed
109 |  |  | unsigned m_recursion_count; // How many times we've called parse_all.
110 |  |  | unsigned m_max_backref; // Largest index of any backref.
111 |  |  | #if defined(BOOST_REGEX_MSVC) && defined(_M_IX86)
112 |  |  | // This is an ugly warning suppression workaround (for warnings *inside* std::vector
113 |  |  | // that can not otherwise be suppressed)...
114 |  |  | static_assert(sizeof(long) >= sizeof(void*), "Long isn't long enough!");
115 |  |  | std::vector<long> m_alt_jumps; // list of alternative in the current scope.
116 |  |  | #else
117 |  |  | std::vector<std::ptrdiff_t> m_alt_jumps; // list of alternative in the current scope.
118 |  |  | #endif
119 |  |  |
120 |  |  | basic_regex_parser& operator=(const basic_regex_parser&);
121 |  |  | basic_regex_parser(const basic_regex_parser&);
122 |  |  | };
123 |  |  |
124 |  |  | template <class charT, class traits>
125 |  | 408235x | basic_regex_parser<charT, traits>::basic_regex_parser(regex_data<charT, traits>* data)
126 |  | 408235x | : basic_regex_creator<charT, traits>(data), m_parser_proc(), m_base(0), m_end(0), m_position(0),
127 |  | 408235x | m_mark_count(0), m_mark_reset(-1), m_max_mark(0), m_paren_start(0), m_alt_insert_point(0), m_has_case_change(false), m_recursion_count(0), m_max_backref(0)
128 |  |  | {
129 |  | 408235x | }
130 |  |  |
131 |  |  | template <class charT, class traits>
132 |  | 408235x | void basic_regex_parser<charT, traits>::parse(const charT* p1, const charT* p2, unsigned l_flags)
133 |  |  | {
134 |  |  | // pass l_flags on to base class:
135 |  | 408235x | this->init(l_flags);
136 |  |  | // set up pointers:
137 |  | 408235x | m_position = m_base = p1;
138 |  | 408235x | m_end = p2;
139 |  |  | // empty strings are errors:
140 |  | 408235x | if((p1 == p2) &&
141 |  |  | (
142 |  | 348x | ((l_flags & regbase::main_option_type) != regbase::perl_syntax_group)
143 |  | 348x | || (l_flags & regbase::no_empty_expressions)
144 |  |  | )
145 |  |  | )
146 |  |  | {
147 |  | 168x | fail(regex_constants::error_empty, 0);
148 |  | 113x | return;
149 |  |  | }
150 |  |  | // select which parser to use:
151 |  | 408067x | switch(l_flags & regbase::main_option_type)
152 |  |  | {
153 |  | 365239x | case regbase::perl_syntax_group:
154 |  |  | {
155 |  | 365239x | m_parser_proc = &basic_regex_parser<charT, traits>::parse_extended;
156 |  |  | //
157 |  |  | // Add a leading paren with index zero to give recursions a target:
158 |  |  | //
159 |  | 365239x | re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_startmark, sizeof(re_brace)));
160 |  | 365239x | br->index = 0;
161 |  | 365239x | br->icase = this->flags() & regbase::icase;
162 |  | 365239x | break;
163 |  |  | }
164 |  | 42300x | case regbase::basic_syntax_group:
165 |  | 42300x | m_parser_proc = &basic_regex_parser<charT, traits>::parse_basic;
166 |  | 42300x | break;
167 |  | 528x | case regbase::literal:
168 |  | 528x | m_parser_proc = &basic_regex_parser<charT, traits>::parse_literal;
169 |  | 528x | break;
170 |  | ✗ | default:
171 |  |  | // Oops, someone has managed to set more than one of the main option flags,
172 |  |  | // so this must be an error:
173 |  | ✗ | fail(regex_constants::error_unknown, 0, "An invalid combination of regular expression syntax flags was used.");
174 |  | ✗ | return;
175 |  |  | }
176 |  |  |
177 |  |  | // parse all our characters:
178 |  | 408067x | bool result = parse_all();
179 |  |  | //
180 |  |  | // Unwind our alternatives:
181 |  |  | //
182 |  | 394472x | unwind_alts(-1);
183 |  |  | // reset l_flags as a global scope (?imsx) may have altered them:
184 |  | 394362x | this->flags(l_flags);
185 |  |  | // if we haven't gobbled up all the characters then we must
186 |  |  | // have had an unexpected ')' :
187 |  | 394362x | if(!result)
188 |  |  | {
189 |  | 57616x | fail(regex_constants::error_paren, std::distance(m_base, m_position), "Found a closing ) with no corresponding opening parenthesis.");
190 |  | 28148x | return;
191 |  |  | }
192 |  |  | // if an error has been set then give up now:
193 |  | 365774x | if(this->m_pdata->m_status)
194 |  | 4613x | return;
195 |  |  | // fill in our sub-expression count:
196 |  | 361161x | this->m_pdata->m_mark_count = 1u + (std::size_t)m_mark_count;
197 |  |  | //
198 |  |  | // Check we don't have backreferences to sub-expressions which don't exist:
199 |  |  | //
200 |  | 361161x | if (m_max_backref > m_mark_count)
201 |  |  | {
202 |  | 3456x | fail(regex_constants::error_backref, std::distance(m_base, m_position), "Found a backreference to a non-existant sub-expression.");
203 |  |  | }
204 |  | 360831x | this->finalize(p1, p2);
205 |  |  | }
206 |  |  |
207 |  |  | template <class charT, class traits>
208 |  | 36286x | void basic_regex_parser<charT, traits>::fail(regex_constants::error_type error_code, std::ptrdiff_t position)
209 |  |  | {
210 |  |  | // get the error message:
211 |  | 36286x | std::string message = this->m_pdata->m_ptraits->error_string(error_code);
212 |  | 36286x | fail(error_code, position, message);
213 |  | 36286x | }
214 |  |  |
215 |  |  | template <class charT, class traits>
216 |  | 80220x | void basic_regex_parser<charT, traits>::fail(regex_constants::error_type error_code, std::ptrdiff_t position, std::string message, std::ptrdiff_t start_pos)
217 |  |  | {
218 |  | 80220x | if(0 == this->m_pdata->m_status) // update the error code if not already set
219 |  | 48226x | this->m_pdata->m_status = error_code;
220 |  | 80220x | m_position = m_end; // don't bother parsing anything else
221 |  |  |
222 |  |  | //
223 |  |  | // Augment error message with the regular expression text:
224 |  |  | //
225 |  | 80220x | if(start_pos == position)
226 |  | 80220x | start_pos = (std::max)(static_cast<std::ptrdiff_t>(0), position - static_cast<std::ptrdiff_t>(10));
227 |  | 80220x | std::ptrdiff_t end_pos = (std::min)(position + static_cast<std::ptrdiff_t>(10), static_cast<std::ptrdiff_t>(m_end - m_base));
228 |  | 80220x | if(error_code != regex_constants::error_empty)
229 |  |  | {
230 |  | 78146x | if((start_pos != 0) || (end_pos != (m_end - m_base)))
231 |  | 8679x | message += " The error occurred while parsing the regular expression fragment: '";
232 |  |  | else
233 |  | 69467x | message += " The error occurred while parsing the regular expression: '";
234 |  | 78146x | if(start_pos != end_pos)
235 |  |  | {
236 |  | 78146x | message += std::string(m_base + start_pos, m_base + position);
237 |  | 78146x | message += ">>>HERE>>>";
238 |  | 156292x | message += std::string(m_base + position, m_base + end_pos);
239 |  |  | }
240 |  | 78146x | message += "'.";
241 |  |  | }
242 |  |  |
243 |  |  | #ifndef BOOST_NO_EXCEPTIONS
244 |  | 72390x | if(0 == (this->flags() & regex_constants::no_except))
245 |  |  | {
246 |  | 14530x | boost::regex_error e(message, error_code, position);
247 |  | 14530x | e.raise();
248 |  | 14530x | }
249 |  |  | #else
250 |  |  | (void)position; // suppress warnings.
251 |  |  | #endif
252 |  | 65690x | }
253 |  |  |
254 |  |  | template <class charT, class traits>
255 |  | 956389x | bool basic_regex_parser<charT, traits>::parse_all()
256 |  |  | {
257 |  | 956389x | if (++m_recursion_count > 400)
258 |  |  | {
259 |  |  | // exceeded internal limits
260 |  | ✗ | fail(boost::regex_constants::error_complexity, m_position - m_base, "Exceeded nested brace limit.");
261 |  |  | }
262 |  | 956389x | bool result = true;
263 |  | 6014326x | while(result && (m_position != m_end))
264 |  |  | {
265 |  | 5072744x | result = (this->*m_parser_proc)();
266 |  |  | }
267 |  | 941582x | --m_recursion_count;
268 |  | 941582x | return result;
269 |  |  | }
270 |  |  |
271 |  |  | #ifdef BOOST_REGEX_MSVC
272 |  |  | #pragma warning(push)
273 |  |  | #pragma warning(disable:4702)
274 |  |  | #endif
275 |  |  | template <class charT, class traits>
276 |  | 139452x | bool basic_regex_parser<charT, traits>::parse_basic()
277 |  |  | {
278 |  | 139452x | switch(this->m_traits.syntax_type(*m_position))
279 |  |  | {
280 |  | 43980x | case regex_constants::syntax_escape:
281 |  | 43980x | return parse_basic_escape();
282 |  | 4056x | case regex_constants::syntax_dot:
283 |  | 4056x | return parse_match_any();
284 |  | 1560x | case regex_constants::syntax_caret:
285 |  | 1560x | ++m_position;
286 |  | 1560x | this->append_state(syntax_element_start_line);
287 |  | 1560x | break;
288 |  | 1884x | case regex_constants::syntax_dollar:
289 |  | 1884x | ++m_position;
290 |  | 1884x | this->append_state(syntax_element_end_line);
291 |  | 1884x | break;
292 |  | 5664x | case regex_constants::syntax_star:
293 |  | 5664x | if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line))
294 |  | 312x | return parse_literal();
295 |  |  | else
296 |  |  | {
297 |  | 5352x | ++m_position;
298 |  | 5352x | return parse_repeat();
299 |  |  | }
300 |  | 8472x | case regex_constants::syntax_plus:
301 |  | 8472x | if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line) || !(this->flags() & regbase::emacs_ex))
302 |  | 312x | return parse_literal();
303 |  |  | else
304 |  |  | {
305 |  | 8160x | ++m_position;
306 |  | 8160x | return parse_repeat(1);
307 |  |  | }
308 |  | 2988x | case regex_constants::syntax_question:
309 |  | 2988x | if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line) || !(this->flags() & regbase::emacs_ex))
310 |  | 312x | return parse_literal();
311 |  |  | else
312 |  |  | {
313 |  | 2676x | ++m_position;
314 |  | 2676x | return parse_repeat(0, 1);
315 |  |  | }
316 |  | 5928x | case regex_constants::syntax_open_set:
317 |  | 5928x | return parse_set();
318 |  | 624x | case regex_constants::syntax_newline:
319 |  | 624x | if(this->flags() & regbase::newline_alt)
320 |  | 312x | return parse_alt();
321 |  |  | else
322 |  | 312x | return parse_literal();
323 |  | 64296x | default:
324 |  | 64296x | return parse_literal();
325 |  |  | }
326 |  | 3444x | return true;
327 |  |  | }
328 |  |  |
329 |  |  | #ifdef BOOST_REGEX_MSVC
330 |  |  | # pragma warning(push)
331 |  |  | #if BOOST_REGEX_MSVC >= 1800
332 |  |  | #pragma warning(disable:26812)
333 |  |  | #endif
334 |  |  | #endif
335 |  |  | template <class charT, class traits>
336 |  | 4930892x | bool basic_regex_parser<charT, traits>::parse_extended()
337 |  |  | {
338 |  | 4930892x | bool result = true;
339 |  | 4930892x | switch(this->m_traits.syntax_type(*m_position))
340 |  |  | {
341 |  | 562634x | case regex_constants::syntax_open_mark:
342 |  | 562634x | return parse_open_paren();
343 |  | 531748x | case regex_constants::syntax_close_mark:
344 |  | 531748x | return false;
345 |  | 305824x | case regex_constants::syntax_escape:
346 |  | 305824x | return parse_extended_escape();
347 |  | 45092x | case regex_constants::syntax_dot:
348 |  | 45092x | return parse_match_any();
349 |  | 32598x | case regex_constants::syntax_caret:
350 |  | 32598x | ++m_position;
351 |  | 32598x | this->append_state(
352 |  | 32598x | (this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_start : syntax_element_start_line));
353 |  | 32598x | break;
354 |  | 43008x | case regex_constants::syntax_dollar:
355 |  | 43008x | ++m_position;
356 |  | 43008x | this->append_state(
357 |  | 43008x | (this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_end : syntax_element_end_line));
358 |  | 43008x | break;
359 |  | 150377x | case regex_constants::syntax_star:
360 |  | 150377x | if(m_position == this->m_base)
361 |  |  | {
362 |  | 247x | fail(regex_constants::error_badrepeat, 0, "The repeat operator \"*\" cannot start a regular expression.");
363 |  | 137x | return false;
364 |  |  | }
365 |  | 150185x | ++m_position;
366 |  | 150185x | return parse_repeat();
367 |  | 30451x | case regex_constants::syntax_question:
368 |  | 30451x | if(m_position == this->m_base)
369 |  |  | {
370 |  | 247x | fail(regex_constants::error_badrepeat, 0, "The repeat operator \"?\" cannot start a regular expression.");
371 |  | 137x | return false;
372 |  |  | }
373 |  | 30259x | ++m_position;
374 |  | 30259x | return parse_repeat(0,1);
375 |  | 171545x | case regex_constants::syntax_plus:
376 |  | 171545x | if(m_position == this->m_base)
377 |  |  | {
378 |  | 247x | fail(regex_constants::error_badrepeat, 0, "The repeat operator \"+\" cannot start a regular expression.");
379 |  | 137x | return false;
380 |  |  | }
381 |  | 171353x | ++m_position;
382 |  | 171353x | return parse_repeat(1);
383 |  | 60941x | case regex_constants::syntax_open_brace:
384 |  | 60941x | ++m_position;
385 |  | 60941x | return parse_repeat_range(false);
386 |  | 349x | case regex_constants::syntax_close_brace:
387 |  | 349x | if((this->flags() & regbase::no_perl_ex) == regbase::no_perl_ex)
388 |  |  | {
389 |  | 223x | fail(regex_constants::error_brace, this->m_position - this->m_base, "Found a closing repetition operator } with no corresponding {.");
390 |  | 113x | return false;
391 |  |  | }
392 |  | 181x | result = parse_literal();
393 |  | 181x | break;
394 |  | 253715x | case regex_constants::syntax_or:
395 |  | 253715x | return parse_alt();
396 |  | 247373x | case regex_constants::syntax_open_set:
397 |  | 247373x | return parse_set();
398 |  | 31752x | case regex_constants::syntax_newline:
399 |  | 31752x | if(this->flags() & regbase::newline_alt)
400 |  | 312x | return parse_alt();
401 |  |  | else
402 |  | 31440x | return parse_literal();
403 |  | 69855x | case regex_constants::syntax_hash:
404 |  |  | //
405 |  |  | // If we have a mod_x flag set, then skip until
406 |  |  | // we get to a newline character:
407 |  |  | //
408 |  | 69855x | if((this->flags()
409 |  | 69855x | & (regbase::no_perl_ex|regbase::mod_x))
410 |  | 69855x | == regbase::mod_x)
411 |  |  | {
412 |  | 1702884x | while((m_position != m_end) && !is_separator(*m_position++)){}
413 |  | 68292x | return true;
414 |  |  | }
415 |  |  | BOOST_REGEX_FALLTHROUGH;
416 |  |  | default:
417 |  | 2395193x | result = parse_literal();
418 |  | 2395193x | break;
419 |  |  | }
420 |  | 2470980x | return result;
421 |  |  | }
422 |  |  | #ifdef BOOST_REGEX_MSVC
423 |  |  | # pragma warning(pop)
424 |  |  | #endif
425 |  |  | #ifdef BOOST_REGEX_MSVC
426 |  |  | #pragma warning(pop)
427 |  |  | #endif
428 |  |  |
429 |  |  | template <class charT, class traits>
430 |  | 2496811x | bool basic_regex_parser<charT, traits>::parse_literal()
431 |  |  | {
432 |  |  | // append this as a literal provided it's not a space character
433 |  |  | // or the perl option regbase::mod_x is not set:
434 |  | 2496811x | if(
435 |  | 2496811x | ((this->flags()
436 |  | 2496811x | & (regbase::main_option_type|regbase::mod_x|regbase::no_perl_ex))
437 |  |  | != regbase::mod_x)
438 |  | 2496811x | || !this->m_traits.isctype(*m_position, this->m_mask_space))
439 |  | 1055911x | this->append_literal(*m_position);
440 |  | 2496811x | ++m_position;
441 |  | 2496811x | return true;
442 |  |  | }
443 |  |  |
444 |  |  | template <class charT, class traits>
445 |  | 571922x | bool basic_regex_parser<charT, traits>::parse_open_paren()
446 |  |  | {
447 |  |  | //
448 |  |  | // skip the '(' and error check:
449 |  |  | //
450 |  | 571922x | if(++m_position == m_end)
451 |  |  | {
452 |  | 360x | fail(regex_constants::error_paren, m_position - m_base);
453 |  | 250x | return false;
454 |  |  | }
455 |  |  | //
456 |  |  | // begin by checking for a perl-style (?...) extension:
457 |  |  | //
458 |  | 571562x | if(
459 |  | 571562x | ((this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) == 0)
460 |  | 571562x | || ((this->flags() & (regbase::main_option_type | regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex))
461 |  |  | )
462 |  |  | {
463 |  | 542402x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question)
464 |  | 282529x | return parse_perl_extension();
465 |  | 259873x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_star)
466 |  | 16244x | return parse_perl_verb();
467 |  |  | }
468 |  |  | //
469 |  |  | // update our mark count, and append the required state:
470 |  |  | //
471 |  | 272789x | unsigned markid = 0;
472 |  | 272789x | if(0 == (this->flags() & regbase::nosubs))
473 |  |  | {
474 |  | 267029x | markid = ++m_mark_count;
475 |  | 267029x | if(this->flags() & regbase::save_subexpression_location)
476 |  | 133008x | this->m_pdata->m_subs.push_back(std::pair<std::size_t, std::size_t>(std::distance(m_base, m_position) - 1, 0));
477 |  |  | }
478 |  | 272789x | re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_startmark, sizeof(re_brace)));
479 |  | 272789x | pb->index = markid;
480 |  | 272789x | pb->icase = this->flags() & regbase::icase;
481 |  | 272789x | std::ptrdiff_t last_paren_start = this->getoffset(pb);
482 |  |  | // back up insertion point for alternations, and set new point:
483 |  | 272789x | std::ptrdiff_t last_alt_point = m_alt_insert_point;
484 |  | 272789x | this->m_pdata->m_data.align();
485 |  | 272789x | m_alt_insert_point = this->m_pdata->m_data.size();
486 |  |  | //
487 |  |  | // back up the current flags in case we have a nested (?imsx) group:
488 |  |  | //
489 |  | 272789x | regex_constants::syntax_option_type opts = this->flags();
490 |  | 272789x | bool old_case_change = m_has_case_change;
491 |  | 272789x | m_has_case_change = false; // no changes to this scope as yet...
492 |  |  | //
493 |  |  | // Back up branch reset data in case we have a nested (?|...)
494 |  |  | //
495 |  | 272789x | int mark_reset = m_mark_reset;
496 |  | 272789x | m_mark_reset = -1;
497 |  |  | //
498 |  |  | // now recursively add more states, this will terminate when we get to a
499 |  |  | // matching ')' :
500 |  |  | //
501 |  | 272789x | parse_all();
502 |  |  | //
503 |  |  | // Unwind pushed alternatives:
504 |  |  | //
505 |  | 271799x | if(0 == unwind_alts(last_paren_start))
506 |  | 226x | return false;
507 |  |  | //
508 |  |  | // restore flags:
509 |  |  | //
510 |  | 271463x | if(m_has_case_change)
511 |  |  | {
512 |  |  | // the case has changed in one or more of the alternatives
513 |  |  | // within the scoped (...) block: we have to add a state
514 |  |  | // to reset the case sensitivity:
515 |  |  | static_cast<re_case*>(
516 |  | 7935x | this->append_state(syntax_element_toggle_case, sizeof(re_case))
517 |  | 4140x | )->icase = opts & regbase::icase;
518 |  |  | }
519 |  | 271463x | this->flags(opts);
520 |  | 271463x | m_has_case_change = old_case_change;
521 |  |  | //
522 |  |  | // restore branch reset:
523 |  |  | //
524 |  | 271463x | m_mark_reset = mark_reset;
525 |  |  | //
526 |  |  | // we either have a ')' or we have run out of characters prematurely:
527 |  |  | //
528 |  | 271463x | if(m_position == m_end)
529 |  |  | {
530 |  | 6180x | this->fail(regex_constants::error_paren, std::distance(m_base, m_end));
531 |  | 2815x | return false;
532 |  |  | }
533 |  | 268373x | if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
534 |  | ✗ | return false;
535 |  | 268373x | if(markid && (this->flags() & regbase::save_subexpression_location))
536 |  | 133008x | this->m_pdata->m_subs.at(markid - 1).second = std::distance(m_base, m_position);
537 |  | 268373x | ++m_position;
538 |  |  | //
539 |  |  | // append closing parenthesis state:
540 |  |  | //
541 |  | 268373x | pb = static_cast<re_brace*>(this->append_state(syntax_element_endmark, sizeof(re_brace)));
542 |  | 268373x | pb->index = markid;
543 |  | 268373x | pb->icase = this->flags() & regbase::icase;
544 |  | 268373x | this->m_paren_start = last_paren_start;
545 |  |  | //
546 |  |  | // restore the alternate insertion point:
547 |  |  | //
548 |  | 268373x | this->m_alt_insert_point = last_alt_point;
549 |  |  |
550 |  | 268373x | return true;
551 |  |  | }
552 |  |  |
553 |  |  | template <class charT, class traits>
554 |  | 43980x | bool basic_regex_parser<charT, traits>::parse_basic_escape()
555 |  |  | {
556 |  | 43980x | if(++m_position == m_end)
557 |  |  | {
558 |  | 168x | fail(regex_constants::error_paren, m_position - m_base);
559 |  | 113x | return false;
560 |  |  | }
561 |  | 43812x | bool result = true;
562 |  | 43812x | switch(this->m_traits.escape_syntax_type(*m_position))
563 |  |  | {
564 |  | 9288x | case regex_constants::syntax_open_mark:
565 |  | 9288x | return parse_open_paren();
566 |  | 8628x | case regex_constants::syntax_close_mark:
567 |  | 8628x | return false;
568 |  | 948x | case regex_constants::syntax_plus:
569 |  | 948x | if(this->flags() & regex_constants::bk_plus_qm)
570 |  |  | {
571 |  | 324x | ++m_position;
572 |  | 324x | return parse_repeat(1);
573 |  |  | }
574 |  |  | else
575 |  | 624x | return parse_literal();
576 |  | 1260x | case regex_constants::syntax_question:
577 |  | 1260x | if(this->flags() & regex_constants::bk_plus_qm)
578 |  |  | {
579 |  | 636x | ++m_position;
580 |  | 636x | return parse_repeat(0, 1);
581 |  |  | }
582 |  |  | else
583 |  | 624x | return parse_literal();
584 |  | 4848x | case regex_constants::syntax_open_brace:
585 |  | 4848x | if(this->flags() & regbase::no_intervals)
586 |  | 156x | return parse_literal();
587 |  | 4692x | ++m_position;
588 |  | 4692x | return parse_repeat_range(true);
589 |  | 324x | case regex_constants::syntax_close_brace:
590 |  | 324x | if(this->flags() & regbase::no_intervals)
591 |  | 156x | return parse_literal();
592 |  | 223x | fail(regex_constants::error_brace, this->m_position - this->m_base, "Found a closing repetition operator } with no corresponding {.");
593 |  | 113x | return false;
594 |  | 4428x | case regex_constants::syntax_or:
595 |  | 4428x | if(this->flags() & regbase::bk_vbar)
596 |  | 4272x | return parse_alt();
597 |  |  | else
598 |  | 156x | result = parse_literal();
599 |  | 156x | break;
600 |  | 2652x | case regex_constants::syntax_digit:
601 |  | 2652x | return parse_backref();
602 |  | 468x | case regex_constants::escape_type_start_buffer:
603 |  | 468x | if(this->flags() & regbase::emacs_ex)
604 |  |  | {
605 |  | 468x | ++m_position;
606 |  | 468x | this->append_state(syntax_element_buffer_start);
607 |  |  | }
608 |  |  | else
609 |  | ✗ | result = parse_literal();
610 |  | 468x | break;
611 |  | 468x | case regex_constants::escape_type_end_buffer:
612 |  | 468x | if(this->flags() & regbase::emacs_ex)
613 |  |  | {
614 |  | 468x | ++m_position;
615 |  | 468x | this->append_state(syntax_element_buffer_end);
616 |  |  | }
617 |  |  | else
618 |  | ✗ | result = parse_literal();
619 |  | 468x | break;
620 |  | 1404x | case regex_constants::escape_type_word_assert:
621 |  | 1404x | if(this->flags() & regbase::emacs_ex)
622 |  |  | {
623 |  | 1404x | ++m_position;
624 |  | 1404x | this->append_state(syntax_element_word_boundary);
625 |  |  | }
626 |  |  | else
627 |  | ✗ | result = parse_literal();
628 |  | 1404x | break;
629 |  | 780x | case regex_constants::escape_type_not_word_assert:
630 |  | 780x | if(this->flags() & regbase::emacs_ex)
631 |  |  | {
632 |  | 780x | ++m_position;
633 |  | 780x | this->append_state(syntax_element_within_word);
634 |  |  | }
635 |  |  | else
636 |  | ✗ | result = parse_literal();
637 |  | 780x | break;
638 |  | 1740x | case regex_constants::escape_type_left_word:
639 |  | 1740x | if(this->flags() & regbase::emacs_ex)
640 |  |  | {
641 |  | 1740x | ++m_position;
642 |  | 1740x | this->append_state(syntax_element_word_start);
643 |  |  | }
644 |  |  | else
645 |  | ✗ | result = parse_literal();
646 |  | 1740x | break;
647 |  | 1584x | case regex_constants::escape_type_right_word:
648 |  | 1584x | if(this->flags() & regbase::emacs_ex)
649 |  |  | {
650 |  | 1584x | ++m_position;
651 |  | 1584x | this->append_state(syntax_element_word_end);
652 |  |  | }
653 |  |  | else
654 |  | ✗ | result = parse_literal();
655 |  | 1584x | break;
656 |  | 4992x | default:
657 |  | 4992x | if(this->flags() & regbase::emacs_ex)
658 |  |  | {
659 |  | 4836x | bool negate = true;
660 |  | 4836x | switch(*m_position)
661 |  |  | {
662 |  | 624x | case 'w':
663 |  | 624x | negate = false;
664 |  |  | BOOST_REGEX_FALLTHROUGH;
665 |  | 780x | case 'W':
666 |  |  | {
667 |  | 780x | basic_char_set<charT, traits> char_set;
668 |  | 780x | if(negate)
669 |  | 156x | char_set.negate();
670 |  | 780x | char_set.add_class(this->m_word_mask);
671 |  | 780x | if(0 == this->append_set(char_set))
672 |  |  | {
673 |  | ✗ | fail(regex_constants::error_ctype, m_position - m_base);
674 |  | ✗ | return false;
675 |  |  | }
676 |  | 780x | ++m_position;
677 |  | 780x | return true;
678 |  | 780x | }
679 |  | 2496x | case 's':
680 |  | 2496x | negate = false;
681 |  |  | BOOST_REGEX_FALLTHROUGH;
682 |  | 4056x | case 'S':
683 |  | 4056x | return add_emacs_code(negate);
684 |  | ✗ | case 'c':
685 |  |  | case 'C':
686 |  |  | // not supported yet:
687 |  | ✗ | fail(regex_constants::error_escape, m_position - m_base, "The \\c and \\C escape sequences are not supported by POSIX basic regular expressions: try the Perl syntax instead.");
688 |  | ✗ | return false;
689 |  | ✗ | default:
690 |  | ✗ | break;
691 |  |  | }
692 |  |  | }
693 |  | 156x | result = parse_literal();
694 |  | 156x | break;
695 |  |  | }
696 |  | 6756x | return result;
697 |  |  | }
698 |  |  |
699 |  |  | template <class charT, class traits>
700 |  | 305824x | bool basic_regex_parser<charT, traits>::parse_extended_escape()
701 |  |  | {
702 |  | 305824x | ++m_position;
703 |  | 305824x | if(m_position == m_end)
704 |  |  | {
705 |  | 247x | fail(regex_constants::error_escape, m_position - m_base, "Incomplete escape sequence found.");
706 |  | 137x | return false;
707 |  |  | }
708 |  | 305632x | bool negate = false; // in case this is a character class escape: \w \d etc
709 |  | 305632x | switch(this->m_traits.escape_syntax_type(*m_position))
710 |  |  | {
711 |  | 6331x | case regex_constants::escape_type_not_class:
712 |  | 6331x | negate = true;
713 |  |  | BOOST_REGEX_FALLTHROUGH;
714 |  |  | case regex_constants::escape_type_class:
715 |  |  | {
716 |  | 63479x | escape_type_class_jump:
717 |  |  | typedef typename traits::char_class_type m_type;
718 |  | 63479x | m_type m = this->m_traits.lookup_classname(m_position, m_position+1);
719 |  | 63479x | if(m != 0)
720 |  |  | {
721 |  | 63323x | basic_char_set<charT, traits> char_set;
722 |  | 63323x | if(negate)
723 |  | 6331x | char_set.negate();
724 |  | 63323x | char_set.add_class(m);
725 |  | 63323x | if(0 == this->append_set(char_set))
726 |  |  | {
727 |  | ✗ | fail(regex_constants::error_ctype, m_position - m_base);
728 |  | ✗ | return false;
729 |  |  | }
730 |  | 63323x | ++m_position;
731 |  | 63323x | return true;
732 |  | 63323x | }
733 |  |  | //
734 |  |  | // not a class, just a regular unknown escape:
735 |  |  | //
736 |  | 156x | this->append_literal(unescape_character());
737 |  | 156x | break;
738 |  |  | }
739 |  | 6829x | case regex_constants::syntax_digit:
740 |  | 6829x | return parse_backref();
741 |  | 4646x | case regex_constants::escape_type_left_word:
742 |  | 4646x | ++m_position;
743 |  | 4646x | this->append_state(syntax_element_word_start);
744 |  | 4646x | break;
745 |  | 3614x | case regex_constants::escape_type_right_word:
746 |  | 3614x | ++m_position;
747 |  | 3614x | this->append_state(syntax_element_word_end);
748 |  | 3614x | break;
749 |  | 3521x | case regex_constants::escape_type_start_buffer:
750 |  | 3521x | ++m_position;
751 |  | 3521x | this->append_state(syntax_element_buffer_start);
752 |  | 3521x | break;
753 |  | 2727x | case regex_constants::escape_type_end_buffer:
754 |  | 2727x | ++m_position;
755 |  | 2727x | this->append_state(syntax_element_buffer_end);
756 |  | 2727x | break;
757 |  | 7200x | case regex_constants::escape_type_word_assert:
758 |  | 7200x | ++m_position;
759 |  | 7200x | this->append_state(syntax_element_word_boundary);
760 |  | 7200x | break;
761 |  | 2568x | case regex_constants::escape_type_not_word_assert:
762 |  | 2568x | ++m_position;
763 |  | 2568x | this->append_state(syntax_element_within_word);
764 |  | 2568x | break;
765 |  | 1644x | case regex_constants::escape_type_Z:
766 |  | 1644x | ++m_position;
767 |  | 1644x | this->append_state(syntax_element_soft_buffer_end);
768 |  | 1644x | break;
769 |  | 1848x | case regex_constants::escape_type_Q:
770 |  | 1848x | return parse_QE();
771 |  | 180x | case regex_constants::escape_type_C:
772 |  | 180x | return parse_match_any();
773 |  | 492x | case regex_constants::escape_type_X:
774 |  | 492x | ++m_position;
775 |  | 492x | this->append_state(syntax_element_combining);
776 |  | 492x | break;
777 |  | 900x | case regex_constants::escape_type_G:
778 |  | 900x | ++m_position;
779 |  | 900x | this->append_state(syntax_element_restart_continue);
780 |  | 900x | break;
781 |  | 6816x | case regex_constants::escape_type_not_property:
782 |  | 6816x | negate = true;
783 |  |  | BOOST_REGEX_FALLTHROUGH;
784 |  | 13632x | case regex_constants::escape_type_property:
785 |  |  | {
786 |  | 13632x | ++m_position;
787 |  |  | char_class_type m;
788 |  | 13632x | if(m_position == m_end)
789 |  |  | {
790 |  | 940x | fail(regex_constants::error_escape, m_position - m_base, "Incomplete property escape found.");
791 |  | 500x | return false;
792 |  |  | }
793 |  |  | // maybe have \p{ddd}
794 |  | 12912x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace)
795 |  |  | {
796 |  | 10224x | const charT* base = m_position;
797 |  |  | // skip forward until we find enclosing brace:
798 |  | 74400x | while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
799 |  | 64176x | ++m_position;
800 |  | 10224x | if(m_position == m_end)
801 |  |  | {
802 |  | 1880x | fail(regex_constants::error_escape, m_position - m_base, "Closing } missing from property escape sequence.");
803 |  | 1000x | return false;
804 |  |  | }
805 |  | 8784x | m = this->m_traits.lookup_classname(++base, m_position++);
806 |  |  | }
807 |  |  | else
808 |  |  | {
809 |  | 2688x | m = this->m_traits.lookup_classname(m_position, m_position+1);
810 |  | 2688x | ++m_position;
811 |  |  | }
812 |  | 11472x | if(m != 0)
813 |  |  | {
814 |  | 10752x | basic_char_set<charT, traits> char_set;
815 |  | 10752x | if(negate)
816 |  | 5376x | char_set.negate();
817 |  | 10752x | char_set.add_class(m);
818 |  | 10752x | if(0 == this->append_set(char_set))
819 |  |  | {
820 |  | ✗ | fail(regex_constants::error_ctype, m_position - m_base);
821 |  | ✗ | return false;
822 |  |  | }
823 |  | 10752x | return true;
824 |  | 10752x | }
825 |  | 940x | fail(regex_constants::error_ctype, m_position - m_base, "Escape sequence was neither a valid property nor a valid character class name.");
826 |  | 500x | return false;
827 |  |  | }
828 |  | 726x | case regex_constants::escape_type_reset_start_mark:
829 |  | 726x | if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex)))
830 |  |  | {
831 |  | 726x | re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_startmark, sizeof(re_brace)));
832 |  | 726x | pb->index = -5;
833 |  | 726x | pb->icase = this->flags() & regbase::icase;
834 |  | 726x | this->m_pdata->m_data.align();
835 |  | 726x | ++m_position;
836 |  | 726x | return true;
837 |  |  | }
838 |  | ✗ | goto escape_type_class_jump;
839 |  | 3600x | case regex_constants::escape_type_line_ending:
840 |  | 3600x | if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex)))
841 |  |  | {
842 |  | 3600x | const charT* e = get_escape_R_string<charT>();
843 |  | 3600x | const charT* old_position = m_position;
844 |  | 3600x | const charT* old_end = m_end;
845 |  | 3600x | const charT* old_base = m_base;
846 |  | 3600x | m_position = e;
847 |  | 3600x | m_base = e;
848 |  | 3600x | m_end = e + traits::length(e);
849 |  | 3600x | bool r = parse_all();
850 |  | 3600x | m_position = ++old_position;
851 |  | 3600x | m_end = old_end;
852 |  | 3600x | m_base = old_base;
853 |  | 3600x | return r;
854 |  |  | }
855 |  | ✗ | goto escape_type_class_jump;
856 |  | 8384x | case regex_constants::escape_type_extended_backref:
857 |  | 8384x | if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex)))
858 |  |  | {
859 |  | 8384x | bool have_brace = false;
860 |  | 8384x | bool negative = false;
861 |  |  | static const char incomplete_message[] = "Incomplete \\g escape found.";
862 |  | 8384x | if(++m_position == m_end)
863 |  |  | {
864 |  | ✗ | fail(regex_constants::error_escape, m_position - m_base, incomplete_message);
865 |  | ✗ | return false;
866 |  |  | }
867 |  |  | // maybe have \g{ddd}
868 |  | 8384x | regex_constants::syntax_type syn = this->m_traits.syntax_type(*m_position);
869 |  | 8384x | regex_constants::syntax_type syn_end = 0;
870 |  | 8384x | if((syn == regex_constants::syntax_open_brace)
871 |  | 3472x | || (syn == regex_constants::escape_type_left_word)
872 |  | 2572x | || (syn == regex_constants::escape_type_end_buffer))
873 |  |  | {
874 |  | 5812x | if(++m_position == m_end)
875 |  |  | {
876 |  | ✗ | fail(regex_constants::error_escape, m_position - m_base, incomplete_message);
877 |  | ✗ | return false;
878 |  |  | }
879 |  | 5812x | have_brace = true;
880 |  | 5812x | switch(syn)
881 |  |  | {
882 |  | 4912x | case regex_constants::syntax_open_brace:
883 |  | 4912x | syn_end = regex_constants::syntax_close_brace;
884 |  | 4912x | break;
885 |  | 900x | case regex_constants::escape_type_left_word:
886 |  | 900x | syn_end = regex_constants::escape_type_right_word;
887 |  | 900x | break;
888 |  | ✗ | default:
889 |  | ✗ | syn_end = regex_constants::escape_type_end_buffer;
890 |  | ✗ | break;
891 |  |  | }
892 |  |  | }
893 |  | 8384x | negative = (*m_position == static_cast<charT>('-'));
894 |  | 8384x | if((negative) && (++m_position == m_end))
895 |  |  | {
896 |  | ✗ | fail(regex_constants::error_escape, m_position - m_base, incomplete_message);
897 |  | ✗ | return false;
898 |  |  | }
899 |  | 8384x | const charT* pc = m_position;
900 |  | 8384x | std::intmax_t i = this->m_traits.toi(pc, m_end, 10);
901 |  | 8384x | if(i < 0 && !syn_end)
902 |  |  | {
903 |  | 2x | fail(regex_constants::error_backref, m_position - m_base);
904 |  | ✗ | return false;
905 |  |  | }
906 |  | 8382x | if((i < 0) && syn_end)
907 |  |  | {
908 |  |  | // Check for a named capture, get the leftmost one if there is more than one:
909 |  | 2702x | const charT* base = m_position;
910 |  | 9082x | while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != syn_end))
911 |  |  | {
912 |  | 6380x | ++m_position;
913 |  |  | }
914 |  | 2702x | i = hash_value_from_capture_name(base, m_position);
915 |  | 2702x | pc = m_position;
916 |  |  | }
917 |  | 8382x | if(negative)
918 |  | 2380x | i = 1 + (static_cast<std::intmax_t>(m_mark_count) - i);
919 |  | 8382x | if(((i < hash_value_mask) && (i > 0)) || ((i >= hash_value_mask) && (this->m_pdata->get_id((int)i) > 0)))
920 |  |  | {
921 |  | 7608x | m_position = pc;
922 |  | 7608x | re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace)));
923 |  | 7608x | pb->index = (int)i;
924 |  | 7608x | pb->icase = this->flags() & regbase::icase;
925 |  | 7608x | if ((i > m_max_backref) && (i < hash_value_mask))
926 |  | 4908x | m_max_backref = i;
927 |  |  | }
928 |  |  | else
929 |  |  | {
930 |  | 774x | fail(regex_constants::error_backref, m_position - m_base);
931 |  | 548x | return false;
932 |  |  | }
933 |  | 7608x | m_position = pc;
934 |  | 7608x | if(have_brace)
935 |  |  | {
936 |  | 5424x | if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != syn_end))
937 |  |  | {
938 |  | ✗ | fail(regex_constants::error_escape, m_position - m_base, incomplete_message);
939 |  | ✗ | return false;
940 |  |  | }
941 |  | 5424x | ++m_position;
942 |  |  | }
943 |  | 7608x | return true;
944 |  |  | }
945 |  | ✗ | goto escape_type_class_jump;
946 |  | 360x | case regex_constants::escape_type_control_v:
947 |  | 360x | if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex)))
948 |  | 360x | goto escape_type_class_jump;
949 |  |  | BOOST_REGEX_FALLTHROUGH;
950 |  |  | default:
951 |  | 179642x | this->append_literal(unescape_character());
952 |  | 178707x | break;
953 |  |  | }
954 |  | 206175x | return true;
955 |  |  | }
956 |  |  |
957 |  |  | template <class charT, class traits>
958 |  | 49328x | bool basic_regex_parser<charT, traits>::parse_match_any()
959 |  |  | {
960 |  |  | //
961 |  |  | // we have a '.' that can match any character:
962 |  |  | //
963 |  | 49328x | ++m_position;
964 |  |  | static_cast<re_dot*>(
965 |  | 94550x | this->append_state(syntax_element_wild, sizeof(re_dot))
966 |  | 97048x | )->mask = static_cast<unsigned char>(this->flags() & regbase::no_mod_s
967 |  |  | ? BOOST_REGEX_DETAIL_NS::force_not_newline
968 |  | 47720x | : this->flags() & regbase::mod_s ?
969 |  |  | BOOST_REGEX_DETAIL_NS::force_newline : BOOST_REGEX_DETAIL_NS::dont_care);
970 |  | 49328x | return true;
971 |  |  | }
972 |  |  |
973 |  |  | template <class charT, class traits>
974 |  | 432189x | bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_t high)
975 |  |  | {
976 |  | 432189x | bool greedy = true;
977 |  | 432189x | bool possessive = false;
978 |  |  | std::size_t insert_point;
979 |  |  | //
980 |  |  | // when we get to here we may have a non-greedy ? mark still to come:
981 |  |  | //
982 |  | 864378x | if((m_position != m_end)
983 |  | 782419x | && (
984 |  | 350230x | (0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex)))
985 |  | 26364x | || ((regbase::basic_syntax_group|regbase::emacs_ex) == (this->flags() & (regbase::main_option_type | regbase::emacs_ex)))
986 |  |  | )
987 |  |  | )
988 |  |  | {
989 |  |  | // OK we have a perl or emacs regex, check for a '?':
990 |  | 330454x | if ((this->flags() & (regbase::main_option_type | regbase::mod_x | regbase::no_perl_ex)) == regbase::mod_x)
991 |  |  | {
992 |  |  | // whitespace skip:
993 |  | 260690x | while ((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
994 |  | 169944x | ++m_position;
995 |  |  | }
996 |  | 330454x | if((m_position != m_end) && (this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question))
997 |  |  | {
998 |  | 27954x | greedy = false;
999 |  | 27954x | ++m_position;
1000 |  |  | }
1001 |  |  | // for perl regexes only check for possessive ++ repeats.
1002 |  | 660908x | if((m_position != m_end)
1003 |  | 324034x | && (0 == (this->flags() & regbase::main_option_type))
1004 |  | 654488x | && (this->m_traits.syntax_type(*m_position) == regex_constants::syntax_plus))
1005 |  |  | {
1006 |  | 9955x | possessive = true;
1007 |  | 9955x | ++m_position;
1008 |  |  | }
1009 |  |  | }
1010 |  | 432189x | if(0 == this->m_last_state)
1011 |  |  | {
1012 |  | 1173x | fail(regex_constants::error_badrepeat, std::distance(m_base, m_position), "Nothing to repeat.");
1013 |  | 339x | return false;
1014 |  |  | }
1015 |  | 431685x | if(this->m_last_state->type == syntax_element_endmark)
1016 |  |  | {
1017 |  |  | // insert a repeat before the '(' matching the last ')':
1018 |  | 155972x | insert_point = this->m_paren_start;
1019 |  |  | }
1020 |  | 275713x | else if((this->m_last_state->type == syntax_element_literal) && (static_cast<re_literal*>(this->m_last_state)->length > 1))
1021 |  |  | {
1022 |  |  | // the last state was a literal with more than one character, split it in two:
1023 |  | 24997x | re_literal* lit = static_cast<re_literal*>(this->m_last_state);
1024 |  | 24997x | charT c = (static_cast<charT*>(static_cast<void*>(lit+1)))[lit->length - 1];
1025 |  | 24997x | lit->length -= 1;
1026 |  |  | // now append new state:
1027 |  | 24997x | lit = static_cast<re_literal*>(this->append_state(syntax_element_literal, sizeof(re_literal) + sizeof(charT)));
1028 |  | 24997x | lit->length = 1;
1029 |  | 24997x | (static_cast<charT*>(static_cast<void*>(lit+1)))[0] = c;
1030 |  | 24997x | insert_point = this->getoffset(this->m_last_state);
1031 |  | 24997x | }
1032 |  |  | else
1033 |  |  | {
1034 |  |  | // repeat the last state whatever it was, need to add some error checking here:
1035 |  | 250716x | switch(this->m_last_state->type)
1036 |  |  | {
1037 |  | 14832x | case syntax_element_start_line:
1038 |  |  | case syntax_element_end_line:
1039 |  |  | case syntax_element_word_boundary:
1040 |  |  | case syntax_element_within_word:
1041 |  |  | case syntax_element_word_start:
1042 |  |  | case syntax_element_word_end:
1043 |  |  | case syntax_element_buffer_start:
1044 |  |  | case syntax_element_buffer_end:
1045 |  |  | case syntax_element_alt:
1046 |  |  | case syntax_element_soft_buffer_end:
1047 |  |  | case syntax_element_restart_continue:
1048 |  |  | case syntax_element_jump:
1049 |  |  | case syntax_element_startmark:
1050 |  |  | case syntax_element_backstep:
1051 |  |  | case syntax_element_toggle_case:
1052 |  |  | // can't legally repeat any of the above:
1053 |  | 14832x | fail(regex_constants::error_badrepeat, m_position - m_base);
1054 |  | 10377x | return false;
1055 |  | 235884x | default:
1056 |  |  | // do nothing...
1057 |  | 235884x | break;
1058 |  |  | }
1059 |  | 235884x | insert_point = this->getoffset(this->m_last_state);
1060 |  |  | }
1061 |  |  | //
1062 |  |  | // OK we now know what to repeat, so insert the repeat around it:
1063 |  |  | //
1064 |  | 416853x | re_repeat* rep = static_cast<re_repeat*>(this->insert_state(insert_point, syntax_element_rep, re_repeater_size));
1065 |  | 416853x | rep->min = low;
1066 |  | 416853x | rep->max = high;
1067 |  | 416853x | rep->greedy = greedy;
1068 |  | 416853x | rep->leading = false;
1069 |  |  | // store our repeater position for later:
1070 |  | 416853x | std::ptrdiff_t rep_off = this->getoffset(rep);
1071 |  |  | // and append a back jump to the repeat:
1072 |  | 416853x | re_jump* jmp = static_cast<re_jump*>(this->append_state(syntax_element_jump, sizeof(re_jump)));
1073 |  | 416853x | jmp->alt.i = rep_off - this->getoffset(jmp);
1074 |  | 416853x | this->m_pdata->m_data.align();
1075 |  |  | // now fill in the alt jump for the repeat:
1076 |  | 416853x | rep = static_cast<re_repeat*>(this->getaddress(rep_off));
1077 |  | 416853x | rep->alt.i = this->m_pdata->m_data.size() - rep_off;
1078 |  |  | //
1079 |  |  | // If the repeat is possessive then bracket the repeat with a (?>...)
1080 |  |  | // independent sub-expression construct:
1081 |  |  | //
1082 |  | 416853x | if(possessive)
1083 |  |  | {
1084 |  | 9451x | if(m_position != m_end)
1085 |  |  | {
1086 |  |  | //
1087 |  |  | // Check for illegal following quantifier, we have to do this here, because
1088 |  |  | // the extra states we insert below circumvents our usual error checking :-(
1089 |  |  | //
1090 |  | 9448x | bool contin = false;
1091 |  | 7972x | do
1092 |  |  | {
1093 |  | 10782x | if ((this->flags() & (regbase::main_option_type | regbase::mod_x | regbase::no_perl_ex)) == regbase::mod_x)
1094 |  |  | {
1095 |  |  | // whitespace skip:
1096 |  | 5526x | while ((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
1097 |  | 2522x | ++m_position;
1098 |  |  | }
1099 |  | 10782x | if (m_position != m_end)
1100 |  |  | {
1101 |  | 10782x | switch (this->m_traits.syntax_type(*m_position))
1102 |  |  | {
1103 |  | 2810x | case regex_constants::syntax_star:
1104 |  |  | case regex_constants::syntax_plus:
1105 |  |  | case regex_constants::syntax_question:
1106 |  |  | case regex_constants::syntax_open_brace:
1107 |  | 2810x | fail(regex_constants::error_badrepeat, m_position - m_base);
1108 |  | 1983x | return false;
1109 |  | 1512x | case regex_constants::syntax_open_mark:
1110 |  |  | // Do we have a comment? If so we need to skip it here...
1111 |  | 1512x | if ((m_position + 2 < m_end) && this->m_traits.syntax_type(*(m_position + 1)) == regex_constants::syntax_question
1112 |  | 3024x | && this->m_traits.syntax_type(*(m_position + 2)) == regex_constants::syntax_hash)
1113 |  |  | {
1114 |  | 1332x | while ((m_position != m_end)
1115 |  | 8976x | && (this->m_traits.syntax_type(*m_position++) != regex_constants::syntax_close_mark)) {
1116 |  |  | }
1117 |  | 1332x | contin = true;
1118 |  |  | }
1119 |  |  | else
1120 |  | 180x | contin = false;
1121 |  | 1512x | break;
1122 |  | 2x | case regex_constants::syntax_hash:
1123 |  | 2x | if (this->flags() & regex_constants::mod_x) {
1124 |  | 15x | while((m_position != m_end) && !is_separator(*m_position++)){}
1125 |  | 2x | contin = true;
1126 |  | 2x | break;
1127 |  |  | }
1128 |  |  | BOOST_REGEX_FALLTHROUGH;
1129 |  |  | default:
1130 |  | 6458x | contin = false;
1131 |  |  | }
1132 |  |  | }
1133 |  |  | else
1134 |  | ✗ | contin = false;
1135 |  |  | } while (contin);
1136 |  |  | }
1137 |  | 6641x | re_brace* pb = static_cast<re_brace*>(this->insert_state(insert_point, syntax_element_startmark, sizeof(re_brace)));
1138 |  | 6641x | pb->index = -3;
1139 |  | 6641x | pb->icase = this->flags() & regbase::icase;
1140 |  | 6641x | jmp = static_cast<re_jump*>(this->insert_state(insert_point + sizeof(re_brace), syntax_element_jump, sizeof(re_jump)));
1141 |  | 6641x | this->m_pdata->m_data.align();
1142 |  | 6641x | jmp->alt.i = this->m_pdata->m_data.size() - this->getoffset(jmp);
1143 |  | 6641x | pb = static_cast<re_brace*>(this->append_state(syntax_element_endmark, sizeof(re_brace)));
1144 |  | 6641x | pb->index = -3;
1145 |  | 6641x | pb->icase = this->flags() & regbase::icase;
1146 |  |  | }
1147 |  | 414043x | return true;
1148 |  |  | }
1149 |  |  |
1150 |  |  | template <class charT, class traits>
1151 |  | 65633x | bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
1152 |  |  | {
1153 |  |  | static const char incomplete_message[] = "Missing } in quantified repetition.";
1154 |  |  | //
1155 |  |  | // parse a repeat-range:
1156 |  |  | //
1157 |  |  | std::size_t min, max;
1158 |  |  | std::intmax_t v;
1159 |  |  | // skip whitespace:
1160 |  | 66809x | while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
1161 |  | 1176x | ++m_position;
1162 |  | 65633x | if(this->m_position == this->m_end)
1163 |  |  | {
1164 |  | 168x | if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex))
1165 |  |  | {
1166 |  | 223x | fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
1167 |  | 113x | return false;
1168 |  |  | }
1169 |  |  | // Treat the opening '{' as a literal character, rewind to start of error:
1170 |  | ✗ | --m_position;
1171 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
1172 |  | ✗ | return parse_literal();
1173 |  |  | }
1174 |  |  | // get min:
1175 |  | 65465x | v = this->m_traits.toi(m_position, m_end, 10);
1176 |  |  | // skip whitespace:
1177 |  | 65465x | if((v < 0) || (v > umax()))
1178 |  |  | {
1179 |  | 673x | if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex))
1180 |  |  | {
1181 |  | 892x | fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
1182 |  | 452x | return false;
1183 |  |  | }
1184 |  |  | // Treat the opening '{' as a literal character, rewind to start of error:
1185 |  | 1x | --m_position;
1186 |  | 1x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
1187 |  | 1x | return parse_literal();
1188 |  |  | }
1189 |  | 65800x | while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
1190 |  | 1008x | ++m_position;
1191 |  | 64792x | if(this->m_position == this->m_end)
1192 |  |  | {
1193 |  | 168x | if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex))
1194 |  |  | {
1195 |  | 223x | fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
1196 |  | 113x | return false;
1197 |  |  | }
1198 |  |  | // Treat the opening '{' as a literal character, rewind to start of error:
1199 |  | ✗ | --m_position;
1200 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
1201 |  | ✗ | return parse_literal();
1202 |  |  | }
1203 |  | 64624x | min = static_cast<std::size_t>(v);
1204 |  |  | // see if we have a comma:
1205 |  | 64624x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_comma)
1206 |  |  | {
1207 |  |  | // move on and error check:
1208 |  | 38698x | ++m_position;
1209 |  |  | // skip whitespace:
1210 |  | 39370x | while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
1211 |  | 672x | ++m_position;
1212 |  | 38698x | if(this->m_position == this->m_end)
1213 |  |  | {
1214 |  | 168x | if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex))
1215 |  |  | {
1216 |  | 223x | fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
1217 |  | 113x | return false;
1218 |  |  | }
1219 |  |  | // Treat the opening '{' as a literal character, rewind to start of error:
1220 |  | ✗ | --m_position;
1221 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
1222 |  | ✗ | return parse_literal();
1223 |  |  | }
1224 |  |  | // get the value if any:
1225 |  | 38530x | v = this->m_traits.toi(m_position, m_end, 10);
1226 |  | 38530x | max = ((v >= 0) && (v < umax())) ? (std::size_t)v : (std::numeric_limits<std::size_t>::max)();
1227 |  |  | }
1228 |  |  | else
1229 |  |  | {
1230 |  |  | // no comma, max = min:
1231 |  | 25926x | max = min;
1232 |  |  | }
1233 |  |  | // skip whitespace:
1234 |  | 64792x | while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
1235 |  | 336x | ++m_position;
1236 |  |  | // OK now check trailing }:
1237 |  | 64456x | if(this->m_position == this->m_end)
1238 |  |  | {
1239 |  | ✗ | if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex))
1240 |  |  | {
1241 |  | ✗ | fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
1242 |  | ✗ | return false;
1243 |  |  | }
1244 |  |  | // Treat the opening '{' as a literal character, rewind to start of error:
1245 |  | ✗ | --m_position;
1246 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
1247 |  | ✗ | return parse_literal();
1248 |  |  | }
1249 |  | 64456x | if(isbasic)
1250 |  |  | {
1251 |  | 3684x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_escape)
1252 |  |  | {
1253 |  | 3180x | ++m_position;
1254 |  | 3180x | if(this->m_position == this->m_end)
1255 |  |  | {
1256 |  | 223x | fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
1257 |  | 113x | return false;
1258 |  |  | }
1259 |  |  | }
1260 |  |  | else
1261 |  |  | {
1262 |  | 669x | fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message);
1263 |  | 339x | return false;
1264 |  |  | }
1265 |  |  | }
1266 |  | 63784x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_brace)
1267 |  | 63604x | ++m_position;
1268 |  |  | else
1269 |  |  | {
1270 |  |  | // Treat the opening '{' as a literal character, rewind to start of error:
1271 |  | 180x | --m_position;
1272 |  | 540x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position;
1273 |  | 180x | return parse_literal();
1274 |  |  | }
1275 |  |  | //
1276 |  |  | // finally go and add the repeat, unless error:
1277 |  |  | //
1278 |  | 63604x | if(min > max)
1279 |  |  | {
1280 |  |  | // Backtrack to error location:
1281 |  | 360x | m_position -= 2;
1282 |  | 552x | while(this->m_traits.isctype(*m_position, this->m_word_mask)) --m_position;
1283 |  | 360x | ++m_position;
1284 |  | 360x | fail(regex_constants::error_badbrace, m_position - m_base);
1285 |  | 250x | return false;
1286 |  |  | }
1287 |  | 63244x | return parse_repeat(min, max);
1288 |  |  | }
1289 |  |  |
1290 |  |  | template <class charT, class traits>
1291 |  | 258611x | bool basic_regex_parser<charT, traits>::parse_alt()
1292 |  |  | {
1293 |  |  | //
1294 |  |  | // error check: if there have been no previous states,
1295 |  |  | // or if the last state was a '(' then error:
1296 |  |  | //
1297 |  | 258611x | if(
1298 |  | 258443x | ((this->m_last_state == 0) || (this->m_last_state->type == syntax_element_startmark))
1299 |  | 517222x | &&
1300 |  |  | !(
1301 |  | 1744x | ((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group)
1302 |  | 1240x | &&
1303 |  | 1240x | ((this->flags() & regbase::no_empty_expressions) == 0)
1304 |  |  | )
1305 |  |  | )
1306 |  |  | {
1307 |  | 1338x | fail(regex_constants::error_empty, this->m_position - this->m_base, "A regular expression cannot start with the alternation operator |.");
1308 |  | 678x | return false;
1309 |  |  | }
1310 |  |  | //
1311 |  |  | // Reset mark count if required:
1312 |  |  | //
1313 |  | 257603x | if(m_max_mark < m_mark_count)
1314 |  | 79704x | m_max_mark = m_mark_count;
1315 |  | 257603x | if(m_mark_reset >= 0)
1316 |  | 9876x | m_mark_count = m_mark_reset;
1317 |  |  |
1318 |  | 257603x | ++m_position;
1319 |  |  | //
1320 |  |  | // we need to append a trailing jump:
1321 |  |  | //
1322 |  | 257603x | re_syntax_base* pj = this->append_state(BOOST_REGEX_DETAIL_NS::syntax_element_jump, sizeof(re_jump));
1323 |  | 257603x | std::ptrdiff_t jump_offset = this->getoffset(pj);
1324 |  |  | //
1325 |  |  | // now insert the alternative:
1326 |  |  | //
1327 |  | 257603x | re_alt* palt = static_cast<re_alt*>(this->insert_state(this->m_alt_insert_point, syntax_element_alt, re_alt_size));
1328 |  | 257603x | jump_offset += re_alt_size;
1329 |  | 257603x | this->m_pdata->m_data.align();
1330 |  | 257603x | palt->alt.i = this->m_pdata->m_data.size() - this->getoffset(palt);
1331 |  |  | //
1332 |  |  | // update m_alt_insert_point so that the next alternate gets
1333 |  |  | // inserted at the start of the second of the two we've just created:
1334 |  |  | //
1335 |  | 257603x | this->m_alt_insert_point = this->m_pdata->m_data.size();
1336 |  |  | //
1337 |  |  | // the start of this alternative must have a case changes state
1338 |  |  | // if the current block has messed around with case changes:
1339 |  |  | //
1340 |  | 257603x | if(m_has_case_change)
1341 |  |  | {
1342 |  |  | static_cast<re_case*>(
1343 |  | 6808x | this->append_state(syntax_element_toggle_case, sizeof(re_case))
1344 |  | 3552x | )->icase = this->m_icase;
1345 |  |  | }
1346 |  |  | //
1347 |  |  | // push the alternative onto our stack, a recursive
1348 |  |  | // implementation here is easier to understand (and faster
1349 |  |  | // as it happens), but causes all kinds of stack overflow problems
1350 |  |  | // on programs with small stacks (COM+).
1351 |  |  | //
1352 |  | 257603x | m_alt_jumps.push_back(jump_offset);
1353 |  | 257603x | return true;
1354 |  |  | }
1355 |  |  |
1356 |  |  | template <class charT, class traits>
1357 |  | 253301x | bool basic_regex_parser<charT, traits>::parse_set()
1358 |  |  | {
1359 |  |  | static const char incomplete_message[] = "Character set declaration starting with [ terminated prematurely - either no ] was found or the set had no content.";
1360 |  | 253301x | ++m_position;
1361 |  | 253301x | if(m_position == m_end)
1362 |  |  | {
1363 |  | 223x | fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
1364 |  | 113x | return false;
1365 |  |  | }
1366 |  | 253133x | basic_char_set<charT, traits> char_set;
1367 |  |  |
1368 |  | 253133x | const charT* base = m_position; // where the '[' was
1369 |  | 253133x | const charT* item_base = m_position; // where the '[' or '^' was
1370 |  |  |
1371 |  | 1180458x | while(m_position != m_end)
1372 |  |  | {
1373 |  | 1178300x | switch(this->m_traits.syntax_type(*m_position))
1374 |  |  | {
1375 |  | 122943x | case regex_constants::syntax_caret:
1376 |  | 122943x | if(m_position == base)
1377 |  |  | {
1378 |  | 122787x | char_set.negate();
1379 |  | 122787x | ++m_position;
1380 |  | 122787x | item_base = m_position;
1381 |  |  | }
1382 |  |  | else
1383 |  | 156x | parse_set_literal(char_set);
1384 |  | 122943x | break;
1385 |  | 247985x | case regex_constants::syntax_close_set:
1386 |  | 247985x | if(m_position == item_base)
1387 |  |  | {
1388 |  | 2388x | parse_set_literal(char_set);
1389 |  | 2333x | break;
1390 |  |  | }
1391 |  |  | else
1392 |  |  | {
1393 |  | 245597x | ++m_position;
1394 |  | 245597x | if(0 == this->append_set(char_set))
1395 |  |  | {
1396 |  | 528x | fail(regex_constants::error_ctype, m_position - m_base);
1397 |  | 363x | return false;
1398 |  |  | }
1399 |  |  | }
1400 |  | 245069x | return true;
1401 |  | 41691x | case regex_constants::syntax_open_set:
1402 |  | 41691x | if(parse_inner_set(char_set))
1403 |  | 36698x | break;
1404 |  | 3618x | return true;
1405 |  | 329363x | case regex_constants::syntax_escape:
1406 |  |  | {
1407 |  |  | //
1408 |  |  | // look ahead and see if this is a character class shortcut
1409 |  |  | // \d \w \s etc...
1410 |  |  | //
1411 |  | 329363x | ++m_position;
1412 |  | 329363x | if(this->m_traits.escape_syntax_type(*m_position)
1413 |  | 329363x | == regex_constants::escape_type_class)
1414 |  |  | {
1415 |  | 1380x | char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1);
1416 |  | 1380x | if(m != 0)
1417 |  |  | {
1418 |  | 1380x | char_set.add_class(m);
1419 |  | 1380x | ++m_position;
1420 |  | 1380x | break;
1421 |  |  | }
1422 |  |  | }
1423 |  | 327983x | else if(this->m_traits.escape_syntax_type(*m_position)
1424 |  | 327983x | == regex_constants::escape_type_not_class)
1425 |  |  | {
1426 |  |  | // negated character class:
1427 |  | 900x | char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1);
1428 |  | 900x | if(m != 0)
1429 |  |  | {
1430 |  | 900x | char_set.add_negated_class(m);
1431 |  | 900x | ++m_position;
1432 |  | 900x | break;
1433 |  |  | }
1434 |  |  | }
1435 |  |  | // not a character class, just a regular escape:
1436 |  | 327083x | --m_position;
1437 |  | 327083x | parse_set_literal(char_set);
1438 |  | 327028x | break;
1439 |  |  | }
1440 |  | 436318x | default:
1441 |  | 436318x | parse_set_literal(char_set);
1442 |  | 436043x | break;
1443 |  |  | }
1444 |  |  | }
1445 |  | 2158x | return m_position != m_end;
1446 |  | 253133x | }
1447 |  |  |
1448 |  |  | template <class charT, class traits>
1449 |  | 41691x | bool basic_regex_parser<charT, traits>::parse_inner_set(basic_char_set<charT, traits>& char_set)
1450 |  |  | {
1451 |  |  | static const char incomplete_message[] = "Character class declaration starting with [ terminated prematurely - either no ] was found or the set had no content.";
1452 |  |  | //
1453 |  |  | // we have either a character class [:name:]
1454 |  |  | // a collating element [.name.]
1455 |  |  | // or an equivalence class [=name=]
1456 |  |  | //
1457 |  | 41691x | if(m_end == ++m_position)
1458 |  |  | {
1459 |  | 223x | fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
1460 |  | 113x | return false;
1461 |  |  | }
1462 |  | 41523x | switch(this->m_traits.syntax_type(*m_position))
1463 |  |  | {
1464 |  | 16500x | case regex_constants::syntax_dot:
1465 |  |  | //
1466 |  |  | // a collating element is treated as a literal:
1467 |  |  | //
1468 |  | 16500x | --m_position;
1469 |  | 16500x | parse_set_literal(char_set);
1470 |  | 16115x | return true;
1471 |  | 22784x | case regex_constants::syntax_colon:
1472 |  |  | {
1473 |  |  | // check that character classes are actually enabled:
1474 |  | 22784x | if((this->flags() & (regbase::main_option_type | regbase::no_char_classes))
1475 |  | 22784x | == (regbase::basic_syntax_group | regbase::no_char_classes))
1476 |  |  | {
1477 |  | 468x | --m_position;
1478 |  | 468x | parse_set_literal(char_set);
1479 |  | 468x | return true;
1480 |  |  | }
1481 |  |  | // skip the ':'
1482 |  | 22316x | if(m_end == ++m_position)
1483 |  |  | {
1484 |  | 223x | fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
1485 |  | 113x | return false;
1486 |  |  | }
1487 |  | 22148x | const charT* name_first = m_position;
1488 |  |  | // skip at least one character, then find the matching ':]'
1489 |  | 22148x | if(m_end == ++m_position)
1490 |  |  | {
1491 |  | 223x | fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
1492 |  | 113x | return false;
1493 |  |  | }
1494 |  | 21980x | while((m_position != m_end)
1495 |  | 115559x | && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_colon))
1496 |  | 93579x | ++m_position;
1497 |  | 21980x | const charT* name_last = m_position;
1498 |  | 21980x | if(m_end == m_position)
1499 |  |  | {
1500 |  | 223x | fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
1501 |  | 113x | return false;
1502 |  |  | }
1503 |  | 43624x | if((m_end == ++m_position)
1504 |  | 21812x | || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set))
1505 |  |  | {
1506 |  | 446x | fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
1507 |  | 226x | return false;
1508 |  |  | }
1509 |  |  | //
1510 |  |  | // check for negated class:
1511 |  |  | //
1512 |  | 21476x | bool negated = false;
1513 |  | 21476x | if(this->m_traits.syntax_type(*name_first) == regex_constants::syntax_caret)
1514 |  |  | {
1515 |  | 900x | ++name_first;
1516 |  | 900x | negated = true;
1517 |  |  | }
1518 |  |  | typedef typename traits::char_class_type m_type;
1519 |  | 21476x | m_type m = this->m_traits.lookup_classname(name_first, name_last);
1520 |  | 21476x | if(m == 0)
1521 |  |  | {
1522 |  | 2832x | if(char_set.empty() && (name_last - name_first == 1))
1523 |  |  | {
1524 |  |  | // maybe a special case:
1525 |  | 1968x | ++m_position;
1526 |  | 3936x | if( (m_position != m_end)
1527 |  | 1968x | && (this->m_traits.syntax_type(*m_position)
1528 |  |  | == regex_constants::syntax_close_set))
1529 |  |  | {
1530 |  | 1776x | if(this->m_traits.escape_syntax_type(*name_first)
1531 |  | 1776x | == regex_constants::escape_type_left_word)
1532 |  |  | {
1533 |  | 720x | ++m_position;
1534 |  | 720x | this->append_state(syntax_element_word_start);
1535 |  | 720x | return false;
1536 |  |  | }
1537 |  | 1056x | if(this->m_traits.escape_syntax_type(*name_first)
1538 |  | 1056x | == regex_constants::escape_type_right_word)
1539 |  |  | {
1540 |  | 720x | ++m_position;
1541 |  | 720x | this->append_state(syntax_element_word_end);
1542 |  | 720x | return false;
1543 |  |  | }
1544 |  |  | }
1545 |  |  | }
1546 |  | 1392x | fail(regex_constants::error_ctype, name_first - m_base);
1547 |  | 952x | return false;
1548 |  |  | }
1549 |  | 18644x | if(!negated)
1550 |  | 17744x | char_set.add_class(m);
1551 |  |  | else
1552 |  | 900x | char_set.add_negated_class(m);
1553 |  | 18644x | ++m_position;
1554 |  | 18644x | break;
1555 |  |  | }
1556 |  | 2080x | case regex_constants::syntax_equal:
1557 |  |  | {
1558 |  |  | // skip the '='
1559 |  | 2080x | if(m_end == ++m_position)
1560 |  |  | {
1561 |  | 247x | fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
1562 |  | 548x | return false;
1563 |  |  | }
1564 |  | 1888x | const charT* name_first = m_position;
1565 |  |  | // skip at least one character, then find the matching '=]'
1566 |  | 1888x | if(m_end == ++m_position)
1567 |  |  | {
1568 |  | 247x | fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
1569 |  | 137x | return false;
1570 |  |  | }
1571 |  | 1696x | while((m_position != m_end)
1572 |  | 5860x | && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal))
1573 |  | 4164x | ++m_position;
1574 |  | 1696x | const charT* name_last = m_position;
1575 |  | 1696x | if(m_end == m_position)
1576 |  |  | {
1577 |  | 247x | fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
1578 |  | 137x | return false;
1579 |  |  | }
1580 |  | 3008x | if((m_end == ++m_position)
1581 |  | 1504x | || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set))
1582 |  |  | {
1583 |  | 247x | fail(regex_constants::error_brack, m_position - m_base, incomplete_message);
1584 |  | 137x | return false;
1585 |  |  | }
1586 |  | 1312x | string_type m = this->m_traits.lookup_collatename(name_first, name_last);
1587 |  | 1312x | if(m.empty() || (m.size() > 2))
1588 |  |  | {
1589 |  | ✗ | fail(regex_constants::error_collate, name_first - m_base);
1590 |  | ✗ | return false;
1591 |  |  | }
1592 |  | 1312x | digraph<charT> d;
1593 |  | 1312x | d.first = m[0];
1594 |  | 1312x | if(m.size() > 1)
1595 |  | 348x | d.second = m[1];
1596 |  |  | else
1597 |  | 964x | d.second = 0;
1598 |  | 1312x | char_set.add_equivalent(d);
1599 |  | 1312x | ++m_position;
1600 |  | 1312x | break;
1601 |  | 1312x | }
1602 |  | 159x | default:
1603 |  | 159x | --m_position;
1604 |  | 159x | parse_set_literal(char_set);
1605 |  | 159x | break;
1606 |  |  | }
1607 |  | 20115x | return true;
1608 |  |  | }
1609 |  |  |
1610 |  |  | template <class charT, class traits>
1611 |  | 783072x | void basic_regex_parser<charT, traits>::parse_set_literal(basic_char_set<charT, traits>& char_set)
1612 |  |  | {
1613 |  | 783072x | digraph<charT> start_range(get_next_set_literal(char_set));
1614 |  | 782577x | if(m_end == m_position)
1615 |  |  | {
1616 |  | 1737x | fail(regex_constants::error_brack, m_position - m_base);
1617 |  | 136829x | return;
1618 |  |  | }
1619 |  | 780840x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash)
1620 |  |  | {
1621 |  |  | // we have a range:
1622 |  | 136943x | if(m_end == ++m_position)
1623 |  |  | {
1624 |  | 168x | fail(regex_constants::error_brack, m_position - m_base);
1625 |  | 113x | return;
1626 |  |  | }
1627 |  | 136775x | if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)
1628 |  |  | {
1629 |  | 135199x | digraph<charT> end_range = get_next_set_literal(char_set);
1630 |  | 135199x | char_set.add_range(start_range, end_range);
1631 |  | 135199x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash)
1632 |  |  | {
1633 |  | 480x | if(m_end == ++m_position)
1634 |  |  | {
1635 |  | ✗ | fail(regex_constants::error_brack, m_position - m_base);
1636 |  | ✗ | return;
1637 |  |  | }
1638 |  | 480x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_set)
1639 |  |  | {
1640 |  |  | // trailing - :
1641 |  | 312x | --m_position;
1642 |  | 312x | return;
1643 |  |  | }
1644 |  | 168x | fail(regex_constants::error_range, m_position - m_base);
1645 |  | 113x | return;
1646 |  |  | }
1647 |  | 134719x | return;
1648 |  |  | }
1649 |  | 1576x | --m_position;
1650 |  |  | }
1651 |  | 645473x | char_set.add_single(start_range);
1652 |  |  | }
1653 |  |  |
1654 |  |  | template <class charT, class traits>
1655 |  | 918271x | digraph<charT> basic_regex_parser<charT, traits>::get_next_set_literal(basic_char_set<charT, traits>& char_set)
1656 |  |  | {
1657 |  | 918271x | digraph<charT> result;
1658 |  | 918271x | switch(this->m_traits.syntax_type(*m_position))
1659 |  |  | {
1660 |  | 3354x | case regex_constants::syntax_dash:
1661 |  | 3354x | if(!char_set.empty())
1662 |  |  | {
1663 |  |  | // see if we are at the end of the set:
1664 |  | 2248x | if((++m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set))
1665 |  |  | {
1666 |  | 360x | fail(regex_constants::error_range, m_position - m_base);
1667 |  | 250x | return result;
1668 |  |  | }
1669 |  | 1888x | --m_position;
1670 |  |  | }
1671 |  | 2994x | result.first = *m_position++;
1672 |  | 2994x | return result;
1673 |  | 435793x | case regex_constants::syntax_escape:
1674 |  |  | // check to see if escapes are supported first:
1675 |  | 435793x | if(this->flags() & regex_constants::no_escape_in_lists)
1676 |  |  | {
1677 |  | 312x | result = *m_position++;
1678 |  | 312x | break;
1679 |  |  | }
1680 |  | 435481x | ++m_position;
1681 |  | 435481x | result = unescape_character();
1682 |  | 435426x | break;
1683 |  | 19299x | case regex_constants::syntax_open_set:
1684 |  |  | {
1685 |  | 19299x | if(m_end == ++m_position)
1686 |  |  | {
1687 |  | ✗ | fail(regex_constants::error_collate, m_position - m_base);
1688 |  | ✗ | return result;
1689 |  |  | }
1690 |  | 19299x | if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_dot)
1691 |  |  | {
1692 |  | 795x | --m_position;
1693 |  | 795x | result.first = *m_position;
1694 |  | 795x | ++m_position;
1695 |  | 795x | return result;
1696 |  |  | }
1697 |  | 18504x | if(m_end == ++m_position)
1698 |  |  | {
1699 |  | 192x | fail(regex_constants::error_collate, m_position - m_base);
1700 |  | 137x | return result;
1701 |  |  | }
1702 |  | 18312x | const charT* name_first = m_position;
1703 |  |  | // skip at least one character, then find the matching ':]'
1704 |  | 18312x | if(m_end == ++m_position)
1705 |  |  | {
1706 |  | 192x | fail(regex_constants::error_collate, name_first - m_base);
1707 |  | 137x | return result;
1708 |  |  | }
1709 |  | 18120x | while((m_position != m_end)
1710 |  | 45384x | && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_dot))
1711 |  | 27264x | ++m_position;
1712 |  | 18120x | const charT* name_last = m_position;
1713 |  | 18120x | if(m_end == m_position)
1714 |  |  | {
1715 |  | 384x | fail(regex_constants::error_collate, name_first - m_base);
1716 |  | 274x | return result;
1717 |  |  | }
1718 |  | 35472x | if((m_end == ++m_position)
1719 |  | 17736x | || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set))
1720 |  |  | {
1721 |  | 192x | fail(regex_constants::error_collate, name_first - m_base);
1722 |  | 137x | return result;
1723 |  |  | }
1724 |  | 17544x | ++m_position;
1725 |  | 17544x | string_type s = this->m_traits.lookup_collatename(name_first, name_last);
1726 |  | 17544x | if(s.empty() || (s.size() > 2))
1727 |  |  | {
1728 |  | 192x | fail(regex_constants::error_collate, name_first - m_base);
1729 |  | 137x | return result;
1730 |  |  | }
1731 |  | 17352x | result.first = s[0];
1732 |  | 17352x | if(s.size() > 1)
1733 |  | 13020x | result.second = s[1];
1734 |  |  | else
1735 |  | 4332x | result.second = 0;
1736 |  | 17352x | return result;
1737 |  | 17544x | }
1738 |  | 459825x | default:
1739 |  | 459825x | result = *m_position++;
1740 |  |  | }
1741 |  | 895563x | return result;
1742 |  |  | }
1743 |  |  |
1744 |  |  | //
1745 |  |  | // does a value fit in the specified charT type?
1746 |  |  | //
1747 |  |  | template <class charT>
1748 |  | 185280x | bool valid_value(charT, std::intmax_t v, const std::integral_constant<bool, true>&)
1749 |  |  | {
1750 |  | 185280x | return (v >> (sizeof(charT) * CHAR_BIT)) == 0;
1751 |  |  | }
1752 |  |  | template <class charT>
1753 |  |  | bool valid_value(charT, std::intmax_t, const std::integral_constant<bool, false>&)
1754 |  |  | {
1755 |  |  | return true; // v will alsways fit in a charT
1756 |  |  | }
1757 |  |  | template <class charT>
1758 |  | 185280x | bool valid_value(charT c, std::intmax_t v)
1759 |  |  | {
1760 |  | 185280x | return valid_value(c, v, std::integral_constant<bool, (sizeof(charT) < sizeof(std::intmax_t))>());
1761 |  |  | }
1762 |  |  |
1763 |  |  | template <class charT, class traits>
1764 |  | 615951x | charT basic_regex_parser<charT, traits>::unescape_character()
1765 |  |  | {
1766 |  |  | #ifdef BOOST_REGEX_MSVC
1767 |  |  | #pragma warning(push)
1768 |  |  | #pragma warning(disable:4127)
1769 |  |  | #endif
1770 |  | 615951x | charT result(0);
1771 |  | 615951x | if(m_position == m_end)
1772 |  |  | {
1773 |  | ✗ | fail(regex_constants::error_escape, m_position - m_base, "Escape sequence terminated prematurely.");
1774 |  | ✗ | return false;
1775 |  |  | }
1776 |  | 615951x | switch(this->m_traits.escape_syntax_type(*m_position))
1777 |  |  | {
1778 |  | 180x | case regex_constants::escape_type_control_a:
1779 |  | 180x | result = charT('\a');
1780 |  | 180x | break;
1781 |  | 180x | case regex_constants::escape_type_e:
1782 |  | 180x | result = charT(27);
1783 |  | 180x | break;
1784 |  | 180x | case regex_constants::escape_type_control_f:
1785 |  | 180x | result = charT('\f');
1786 |  | 180x | break;
1787 |  | 41648x | case regex_constants::escape_type_control_n:
1788 |  | 41648x | result = charT('\n');
1789 |  | 41648x | break;
1790 |  | 375x | case regex_constants::escape_type_control_r:
1791 |  | 375x | result = charT('\r');
1792 |  | 375x | break;
1793 |  | 14580x | case regex_constants::escape_type_control_t:
1794 |  | 14580x | result = charT('\t');
1795 |  | 14580x | break;
1796 |  | ✗ | case regex_constants::escape_type_control_v:
1797 |  | ✗ | result = charT('\v');
1798 |  | ✗ | break;
1799 |  | 180x | case regex_constants::escape_type_word_assert:
1800 |  | 180x | result = charT('\b');
1801 |  | 180x | break;
1802 |  | 528x | case regex_constants::escape_type_ascii_control:
1803 |  | 528x | ++m_position;
1804 |  | 528x | if(m_position == m_end)
1805 |  |  | {
1806 |  |  | // Rewind to start of escape:
1807 |  | 192x | --m_position;
1808 |  | 384x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1809 |  | 247x | fail(regex_constants::error_escape, m_position - m_base, "ASCII escape sequence terminated prematurely.");
1810 |  | 137x | return result;
1811 |  |  | }
1812 |  | 336x | result = static_cast<charT>(*m_position % 32);
1813 |  | 336x | break;
1814 |  | 187944x | case regex_constants::escape_type_hex:
1815 |  | 187944x | ++m_position;
1816 |  | 187944x | if(m_position == m_end)
1817 |  |  | {
1818 |  |  | // Rewind to start of escape:
1819 |  | 192x | --m_position;
1820 |  | 384x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1821 |  | 247x | fail(regex_constants::error_escape, m_position - m_base, "Hexadecimal escape sequence terminated prematurely.");
1822 |  | 137x | return result;
1823 |  |  | }
1824 |  |  | // maybe have \x{ddd}
1825 |  | 187752x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace)
1826 |  |  | {
1827 |  | 2280x | ++m_position;
1828 |  | 2280x | if(m_position == m_end)
1829 |  |  | {
1830 |  |  | // Rewind to start of escape:
1831 |  | 192x | --m_position;
1832 |  | 576x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1833 |  | 247x | fail(regex_constants::error_escape, m_position - m_base, "Missing } in hexadecimal escape sequence.");
1834 |  | 137x | return result;
1835 |  |  | }
1836 |  | 2088x | std::intmax_t i = this->m_traits.toi(m_position, m_end, 16);
1837 |  | 4176x | if((m_position == m_end)
1838 |  | 1896x | || (i < 0)
1839 |  | 1512x | || ((std::numeric_limits<charT>::is_specialized) && (i > (std::intmax_t)(std::numeric_limits<charT>::max)()))
1840 |  | 3984x | || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
1841 |  |  | {
1842 |  |  | // Rewind to start of escape:
1843 |  | 576x | --m_position;
1844 |  | 2112x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1845 |  | 741x | fail(regex_constants::error_badbrace, m_position - m_base, "Hexadecimal escape sequence was invalid.");
1846 |  | 411x | return result;
1847 |  |  | }
1848 |  | 1512x | ++m_position;
1849 |  | 1512x | result = charT(i);
1850 |  |  | }
1851 |  |  | else
1852 |  |  | {
1853 |  | 185472x | std::ptrdiff_t len = (std::min)(static_cast<std::ptrdiff_t>(2), static_cast<std::ptrdiff_t>(m_end - m_position));
1854 |  | 185472x | std::intmax_t i = this->m_traits.toi(m_position, m_position + len, 16);
1855 |  | 185472x | if((i < 0)
1856 |  | 185472x | || !valid_value(charT(0), i))
1857 |  |  | {
1858 |  |  | // Rewind to start of escape:
1859 |  | 192x | --m_position;
1860 |  | 384x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1861 |  | 247x | fail(regex_constants::error_escape, m_position - m_base, "Escape sequence did not encode a valid character.");
1862 |  | 137x | return result;
1863 |  |  | }
1864 |  | 185280x | result = charT(i);
1865 |  |  | }
1866 |  | 186792x | return result;
1867 |  | 100512x | case regex_constants::syntax_digit:
1868 |  |  | {
1869 |  |  | // an octal escape sequence, the first character must be a zero
1870 |  |  | // followed by up to 3 octal digits:
1871 |  | 201024x | std::ptrdiff_t len = (std::min)(std::distance(m_position, m_end), static_cast<std::ptrdiff_t>(4));
1872 |  | 100512x | const charT* bp = m_position;
1873 |  | 100512x | std::intmax_t val = this->m_traits.toi(bp, bp + 1, 8);
1874 |  | 100512x | if(val != 0)
1875 |  |  | {
1876 |  |  | // Rewind to start of escape:
1877 |  | 192x | --m_position;
1878 |  | 192x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1879 |  |  | // Oops not an octal escape after all:
1880 |  | 247x | fail(regex_constants::error_escape, m_position - m_base, "Invalid octal escape sequence.");
1881 |  | 137x | return result;
1882 |  |  | }
1883 |  | 100320x | val = this->m_traits.toi(m_position, m_position + len, 8);
1884 |  | 100320x | if((val < 0) || (val > (std::intmax_t)(std::numeric_limits<charT>::max)()))
1885 |  |  | {
1886 |  |  | // Rewind to start of escape:
1887 |  | ✗ | --m_position;
1888 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1889 |  | ✗ | fail(regex_constants::error_escape, m_position - m_base, "Octal escape sequence is invalid.");
1890 |  | ✗ | return result;
1891 |  |  | }
1892 |  | 100320x | return static_cast<charT>(val);
1893 |  |  | }
1894 |  | 5244x | case regex_constants::escape_type_named_char:
1895 |  |  | {
1896 |  | 5244x | ++m_position;
1897 |  | 5244x | if(m_position == m_end)
1898 |  |  | {
1899 |  |  | // Rewind to start of escape:
1900 |  | 360x | --m_position;
1901 |  | 720x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1902 |  | 360x | fail(regex_constants::error_escape, m_position - m_base);
1903 |  | 250x | return false;
1904 |  |  | }
1905 |  |  | // maybe have \N{name}
1906 |  | 4884x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace)
1907 |  |  | {
1908 |  | 4884x | const charT* base = m_position;
1909 |  |  | // skip forward until we find enclosing brace:
1910 |  | 39000x | while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
1911 |  | 34116x | ++m_position;
1912 |  | 4884x | if(m_position == m_end)
1913 |  |  | {
1914 |  |  | // Rewind to start of escape:
1915 |  | 720x | --m_position;
1916 |  | 3600x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1917 |  | 720x | fail(regex_constants::error_escape, m_position - m_base);
1918 |  | 4444x | return false;
1919 |  |  | }
1920 |  | 4164x | string_type s = this->m_traits.lookup_collatename(++base, m_position++);
1921 |  | 4164x | if(s.empty())
1922 |  |  | {
1923 |  |  | // Rewind to start of escape:
1924 |  | 720x | --m_position;
1925 |  | 7200x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1926 |  | 720x | fail(regex_constants::error_collate, m_position - m_base);
1927 |  | 500x | return false;
1928 |  |  | }
1929 |  | 3444x | if(s.size() == 1)
1930 |  |  | {
1931 |  | 3444x | return s[0];
1932 |  |  | }
1933 |  | 4164x | }
1934 |  |  | // fall through is a failure:
1935 |  |  | // Rewind to start of escape:
1936 |  | ✗ | --m_position;
1937 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1938 |  | ✗ | fail(regex_constants::error_escape, m_position - m_base);
1939 |  | ✗ | return false;
1940 |  |  | }
1941 |  | 264400x | default:
1942 |  | 264400x | result = *m_position;
1943 |  | 264400x | break;
1944 |  |  | }
1945 |  | 322059x | ++m_position;
1946 |  | 322059x | return result;
1947 |  |  | #ifdef BOOST_REGEX_MSVC
1948 |  |  | #pragma warning(pop)
1949 |  |  | #endif
1950 |  |  | }
1951 |  |  |
1952 |  |  | template <class charT, class traits>
1953 |  | 9481x | bool basic_regex_parser<charT, traits>::parse_backref()
1954 |  |  | {
1955 |  | 9481x | BOOST_REGEX_ASSERT(m_position != m_end);
1956 |  | 9481x | const charT* pc = m_position;
1957 |  | 9481x | std::intmax_t i = this->m_traits.toi(pc, pc + 1, 10);
1958 |  | 9481x | if((i == 0) || (((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) && (this->flags() & regbase::no_bk_refs)))
1959 |  |  | {
1960 |  |  | // not a backref at all but an octal escape sequence:
1961 |  | 672x | charT c = unescape_character();
1962 |  | 672x | this->append_literal(c);
1963 |  |  | }
1964 |  | 8809x | else if((i > 0))
1965 |  |  | {
1966 |  | 8809x | m_position = pc;
1967 |  | 8809x | re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace)));
1968 |  | 8809x | pb->index = (int)i;
1969 |  | 8809x | pb->icase = this->flags() & regbase::icase;
1970 |  | 8809x | if(i > m_max_backref)
1971 |  | 8809x | m_max_backref = i;
1972 |  |  | }
1973 |  |  | else
1974 |  |  | {
1975 |  |  | // Rewind to start of escape:
1976 |  | ✗ | --m_position;
1977 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
1978 |  | ✗ | fail(regex_constants::error_backref, m_position - m_base);
1979 |  | ✗ | return false;
1980 |  |  | }
1981 |  | 9481x | return true;
1982 |  |  | }
1983 |  |  |
1984 |  |  | template <class charT, class traits>
1985 |  | 1848x | bool basic_regex_parser<charT, traits>::parse_QE()
1986 |  |  | {
1987 |  |  | #ifdef BOOST_REGEX_MSVC
1988 |  |  | #pragma warning(push)
1989 |  |  | #pragma warning(disable:4127)
1990 |  |  | #endif
1991 |  |  | //
1992 |  |  | // parse a \Q...\E sequence:
1993 |  |  | //
1994 |  | 1848x | ++m_position; // skip the Q
1995 |  | 1848x | const charT* start = m_position;
1996 |  |  | const charT* end;
1997 |  |  | do
1998 |  |  | {
1999 |  | 2208x | while((m_position != m_end)
2000 |  | 21168x | && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape))
2001 |  | 18960x | ++m_position;
2002 |  | 2208x | if(m_position == m_end)
2003 |  |  | {
2004 |  |  | // a \Q...\E sequence may terminate with the end of the expression:
2005 |  | 156x | end = m_position;
2006 |  | 156x | break;
2007 |  |  | }
2008 |  | 2052x | if(++m_position == m_end) // skip the escape
2009 |  |  | {
2010 |  | 247x | fail(regex_constants::error_escape, m_position - m_base, "Unterminated \\Q...\\E sequence.");
2011 |  | 137x | return false;
2012 |  |  | }
2013 |  |  | // check to see if it's a \E:
2014 |  | 1860x | if(this->m_traits.escape_syntax_type(*m_position) == regex_constants::escape_type_E)
2015 |  |  | {
2016 |  | 1500x | ++m_position;
2017 |  | 1500x | end = m_position - 2;
2018 |  | 1500x | break;
2019 |  |  | }
2020 |  |  | // otherwise go round again:
2021 |  |  | }while(true);
2022 |  |  | //
2023 |  |  | // now add all the character between the two escapes as literals:
2024 |  |  | //
2025 |  | 20400x | while(start != end)
2026 |  |  | {
2027 |  | 18744x | this->append_literal(*start);
2028 |  | 18744x | ++start;
2029 |  |  | }
2030 |  | 1656x | return true;
2031 |  |  | #ifdef BOOST_REGEX_MSVC
2032 |  |  | #pragma warning(pop)
2033 |  |  | #endif
2034 |  |  | }
2035 |  |  |
2036 |  |  | template <class charT, class traits>
2037 |  | 282529x | bool basic_regex_parser<charT, traits>::parse_perl_extension()
2038 |  |  | {
2039 |  | 282529x | if(++m_position == m_end)
2040 |  |  | {
2041 |  |  | // Rewind to start of (? sequence:
2042 |  | 192x | --m_position;
2043 |  | 384x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2044 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2045 |  | 137x | return false;
2046 |  |  | }
2047 |  |  | //
2048 |  |  | // treat comments as a special case, as these
2049 |  |  | // are the only ones that don't start with a leading
2050 |  |  | // startmark state:
2051 |  |  | //
2052 |  | 282337x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_hash)
2053 |  |  | {
2054 |  | 5988x | while((m_position != m_end)
2055 |  | 67944x | && (this->m_traits.syntax_type(*m_position++) != regex_constants::syntax_close_mark))
2056 |  |  | {}
2057 |  | 5988x | return true;
2058 |  |  | }
2059 |  |  | //
2060 |  |  | // backup some state, and prepare the way:
2061 |  |  | //
2062 |  | 276349x | int markid = 0;
2063 |  | 276349x | std::ptrdiff_t jump_offset = 0;
2064 |  | 276349x | re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_startmark, sizeof(re_brace)));
2065 |  | 276349x | pb->icase = this->flags() & regbase::icase;
2066 |  | 276349x | std::ptrdiff_t last_paren_start = this->getoffset(pb);
2067 |  |  | // back up insertion point for alternations, and set new point:
2068 |  | 276349x | std::ptrdiff_t last_alt_point = m_alt_insert_point;
2069 |  | 276349x | this->m_pdata->m_data.align();
2070 |  | 276349x | m_alt_insert_point = this->m_pdata->m_data.size();
2071 |  | 276349x | std::ptrdiff_t expected_alt_point = m_alt_insert_point;
2072 |  | 276349x | bool restore_flags = true;
2073 |  | 276349x | regex_constants::syntax_option_type old_flags = this->flags();
2074 |  | 276349x | bool old_case_change = m_has_case_change;
2075 |  | 276349x | m_has_case_change = false;
2076 |  |  | charT name_delim;
2077 |  | 276349x | int mark_reset = m_mark_reset;
2078 |  | 276349x | int max_mark = m_max_mark;
2079 |  | 276349x | m_mark_reset = -1;
2080 |  | 276349x | m_max_mark = m_mark_count;
2081 |  |  | std::intmax_t v;
2082 |  |  | //
2083 |  |  | // select the actual extension used:
2084 |  |  | //
2085 |  | 276349x | switch(this->m_traits.syntax_type(*m_position))
2086 |  |  | {
2087 |  | 7716x | case regex_constants::syntax_or:
2088 |  | 7716x | m_mark_reset = m_mark_count;
2089 |  |  | BOOST_REGEX_FALLTHROUGH;
2090 |  | 105923x | case regex_constants::syntax_colon:
2091 |  |  | //
2092 |  |  | // a non-capturing mark:
2093 |  |  | //
2094 |  | 105923x | pb->index = markid = 0;
2095 |  | 105923x | ++m_position;
2096 |  | 105923x | break;
2097 |  | 21014x | case regex_constants::syntax_digit:
2098 |  |  | {
2099 |  |  | //
2100 |  |  | // a recursive subexpression:
2101 |  |  | //
2102 |  | 21014x | v = this->m_traits.toi(m_position, m_end, 10);
2103 |  | 21014x | if((v < 0) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
2104 |  |  | {
2105 |  |  | // Rewind to start of (? sequence:
2106 |  | 192x | --m_position;
2107 |  | 576x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2108 |  | 247x | fail(regex_constants::error_perl_extension, m_position - m_base, "The recursive sub-expression refers to an invalid marking group, or is unterminated.");
2109 |  | 137x | return false;
2110 |  |  | }
2111 |  | 20822x | insert_recursion:
2112 |  | 39818x | pb->index = markid = 0;
2113 |  | 39818x | re_recurse* pr = static_cast<re_recurse*>(this->append_state(syntax_element_recurse, sizeof(re_recurse)));
2114 |  | 39818x | pr->alt.i = (std::ptrdiff_t)v;
2115 |  | 39818x | pr->state_id = 0;
2116 |  |  | static_cast<re_case*>(
2117 |  | 76318x | this->append_state(syntax_element_toggle_case, sizeof(re_case))
2118 |  | 39818x | )->icase = this->flags() & regbase::icase;
2119 |  | 39818x | break;
2120 |  |  | }
2121 |  | 1284x | case regex_constants::syntax_plus:
2122 |  |  | //
2123 |  |  | // A forward-relative recursive subexpression:
2124 |  |  | //
2125 |  | 1284x | ++m_position;
2126 |  | 1284x | v = this->m_traits.toi(m_position, m_end, 10);
2127 |  | 1284x | if((v <= 0) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
2128 |  |  | {
2129 |  |  | // Rewind to start of (? sequence:
2130 |  | 192x | --m_position;
2131 |  | 768x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2132 |  | 247x | fail(regex_constants::error_perl_extension, m_position - m_base, "An invalid or unterminated recursive sub-expression.");
2133 |  | 137x | return false;
2134 |  |  | }
2135 |  | 1092x | if ((std::numeric_limits<std::intmax_t>::max)() - m_mark_count < v)
2136 |  |  | {
2137 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base, "An invalid or unterminated recursive sub-expression.");
2138 |  | ✗ | return false;
2139 |  |  | }
2140 |  | 1092x | v += m_mark_count;
2141 |  | 1092x | goto insert_recursion;
2142 |  | 12948x | case regex_constants::syntax_dash:
2143 |  |  | //
2144 |  |  | // Possibly a backward-relative recursive subexpression:
2145 |  |  | //
2146 |  | 12948x | ++m_position;
2147 |  | 12948x | v = this->m_traits.toi(m_position, m_end, 10);
2148 |  | 12948x | if(v <= 0)
2149 |  |  | {
2150 |  | 12576x | --m_position;
2151 |  |  | // Oops not a relative recursion at all, but a (?-imsx) group:
2152 |  | 12576x | goto option_group_jump;
2153 |  |  | }
2154 |  | 372x | v = static_cast<std::intmax_t>(m_mark_count) + 1 - v;
2155 |  | 372x | if(v <= 0)
2156 |  |  | {
2157 |  |  | // Rewind to start of (? sequence:
2158 |  | 192x | --m_position;
2159 |  | 768x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2160 |  | 247x | fail(regex_constants::error_perl_extension, m_position - m_base, "An invalid or unterminated recursive sub-expression.");
2161 |  | 137x | return false;
2162 |  |  | }
2163 |  | 180x | goto insert_recursion;
2164 |  | 7698x | case regex_constants::syntax_equal:
2165 |  | 7698x | pb->index = markid = -1;
2166 |  | 7698x | ++m_position;
2167 |  | 7698x | jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump)));
2168 |  | 7698x | this->m_pdata->m_data.align();
2169 |  | 7698x | m_alt_insert_point = this->m_pdata->m_data.size();
2170 |  | 7698x | break;
2171 |  | 13621x | case regex_constants::syntax_not:
2172 |  | 13621x | pb->index = markid = -2;
2173 |  | 13621x | ++m_position;
2174 |  | 13621x | jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump)));
2175 |  | 13621x | this->m_pdata->m_data.align();
2176 |  | 13621x | m_alt_insert_point = this->m_pdata->m_data.size();
2177 |  | 13621x | break;
2178 |  | 26824x | case regex_constants::escape_type_left_word:
2179 |  |  | {
2180 |  |  | // a lookbehind assertion:
2181 |  | 26824x | if(++m_position == m_end)
2182 |  |  | {
2183 |  |  | // Rewind to start of (? sequence:
2184 |  | 192x | --m_position;
2185 |  | 576x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2186 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2187 |  | 137x | return false;
2188 |  |  | }
2189 |  | 26632x | regex_constants::syntax_type t = this->m_traits.syntax_type(*m_position);
2190 |  | 26632x | if(t == regex_constants::syntax_not)
2191 |  | 1836x | pb->index = markid = -2;
2192 |  | 24796x | else if(t == regex_constants::syntax_equal)
2193 |  | 8054x | pb->index = markid = -1;
2194 |  |  | else
2195 |  |  | {
2196 |  |  | // Probably a named capture which also starts (?< :
2197 |  | 16742x | name_delim = '>';
2198 |  | 16742x | --m_position;
2199 |  | 16742x | goto named_capture_jump;
2200 |  |  | }
2201 |  | 9890x | ++m_position;
2202 |  | 9890x | jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump)));
2203 |  | 9890x | this->append_state(syntax_element_backstep, sizeof(re_brace));
2204 |  | 9890x | this->m_pdata->m_data.align();
2205 |  | 9890x | m_alt_insert_point = this->m_pdata->m_data.size();
2206 |  | 9890x | break;
2207 |  |  | }
2208 |  | 22624x | case regex_constants::escape_type_right_word:
2209 |  |  | //
2210 |  |  | // an independent sub-expression:
2211 |  |  | //
2212 |  | 22624x | pb->index = markid = -3;
2213 |  | 22624x | ++m_position;
2214 |  | 22624x | jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump)));
2215 |  | 22624x | this->m_pdata->m_data.align();
2216 |  | 22624x | m_alt_insert_point = this->m_pdata->m_data.size();
2217 |  | 22624x | break;
2218 |  | 17849x | case regex_constants::syntax_open_mark:
2219 |  |  | {
2220 |  |  | // a conditional expression:
2221 |  | 17849x | pb->index = markid = -4;
2222 |  | 17849x | if(++m_position == m_end)
2223 |  |  | {
2224 |  |  | // Rewind to start of (? sequence:
2225 |  | 192x | --m_position;
2226 |  | 192x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2227 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2228 |  | 137x | return false;
2229 |  |  | }
2230 |  | 17657x | v = this->m_traits.toi(m_position, m_end, 10);
2231 |  | 17657x | if(m_position == m_end)
2232 |  |  | {
2233 |  |  | // Rewind to start of (? sequence:
2234 |  | 192x | --m_position;
2235 |  | 384x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2236 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2237 |  | 137x | return false;
2238 |  |  | }
2239 |  | 17465x | if(*m_position == charT('R'))
2240 |  |  | {
2241 |  | 3000x | if(++m_position == m_end)
2242 |  |  | {
2243 |  |  | // Rewind to start of (? sequence:
2244 |  | ✗ | --m_position;
2245 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2246 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2247 |  | ✗ | return false;
2248 |  |  | }
2249 |  | 3000x | if(*m_position == charT('&'))
2250 |  |  | {
2251 |  | 960x | const charT* base = ++m_position;
2252 |  | 1920x | while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
2253 |  | 960x | ++m_position;
2254 |  | 960x | if(m_position == m_end)
2255 |  |  | {
2256 |  |  | // Rewind to start of (? sequence:
2257 |  | ✗ | --m_position;
2258 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2259 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2260 |  | ✗ | return false;
2261 |  |  | }
2262 |  | 960x | v = -static_cast<int>(hash_value_from_capture_name(base, m_position));
2263 |  |  | }
2264 |  |  | else
2265 |  |  | {
2266 |  | 2040x | v = -this->m_traits.toi(m_position, m_end, 10);
2267 |  |  | }
2268 |  | 3000x | re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_assert_backref, sizeof(re_brace)));
2269 |  | 3000x | br->index = v < 0 ? (int)(v - 1) : 0;
2270 |  | 3000x | if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
2271 |  |  | {
2272 |  |  | // Rewind to start of (? sequence:
2273 |  | ✗ | --m_position;
2274 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2275 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2276 |  | ✗ | return false;
2277 |  |  | }
2278 |  | 3000x | if(++m_position == m_end)
2279 |  |  | {
2280 |  |  | // Rewind to start of (? sequence:
2281 |  | ✗ | --m_position;
2282 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2283 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2284 |  | ✗ | return false;
2285 |  |  | }
2286 |  |  | }
2287 |  | 14465x | else if((*m_position == charT('\'')) || (*m_position == charT('<')))
2288 |  |  | {
2289 |  | 624x | const charT* base = ++m_position;
2290 |  | 1872x | while((m_position != m_end) && (*m_position != charT('>')) && (*m_position != charT('\'')))
2291 |  | 1248x | ++m_position;
2292 |  | 624x | if(m_position == m_end)
2293 |  |  | {
2294 |  |  | // Rewind to start of (? sequence:
2295 |  | ✗ | --m_position;
2296 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2297 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2298 |  | ✗ | return false;
2299 |  |  | }
2300 |  | 624x | v = static_cast<int>(hash_value_from_capture_name(base, m_position));
2301 |  | 624x | re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_assert_backref, sizeof(re_brace)));
2302 |  | 624x | br->index = (int)v;
2303 |  | 624x | if(((*m_position != charT('>')) && (*m_position != charT('\''))) || (++m_position == m_end))
2304 |  |  | {
2305 |  |  | // Rewind to start of (? sequence:
2306 |  | ✗ | --m_position;
2307 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2308 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base, "Unterminated named capture.");
2309 |  | ✗ | return false;
2310 |  |  | }
2311 |  | 624x | if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
2312 |  |  | {
2313 |  |  | // Rewind to start of (? sequence:
2314 |  | ✗ | --m_position;
2315 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2316 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2317 |  | ✗ | return false;
2318 |  |  | }
2319 |  | 624x | if(++m_position == m_end)
2320 |  |  | {
2321 |  |  | // Rewind to start of (? sequence:
2322 |  | ✗ | --m_position;
2323 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2324 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2325 |  | ✗ | return false;
2326 |  |  | }
2327 |  | 624x | }
2328 |  | 13841x | else if(*m_position == charT('D'))
2329 |  |  | {
2330 |  | 2220x | const char* def = "DEFINE";
2331 |  | 15540x | while(*def && (m_position != m_end) && (*m_position == charT(*def)))
2332 |  | 13320x | ++m_position, ++def;
2333 |  | 2220x | if((m_position == m_end) || *def)
2334 |  |  | {
2335 |  |  | // Rewind to start of (? sequence:
2336 |  | ✗ | --m_position;
2337 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2338 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2339 |  | ✗ | return false;
2340 |  |  | }
2341 |  | 2220x | re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_assert_backref, sizeof(re_brace)));
2342 |  | 2220x | br->index = 9999; // special magic value!
2343 |  | 2220x | if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
2344 |  |  | {
2345 |  |  | // Rewind to start of (? sequence:
2346 |  | ✗ | --m_position;
2347 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2348 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2349 |  | ✗ | return false;
2350 |  |  | }
2351 |  | 2220x | if(++m_position == m_end)
2352 |  |  | {
2353 |  |  | // Rewind to start of (? sequence:
2354 |  | ✗ | --m_position;
2355 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2356 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2357 |  | ✗ | return false;
2358 |  |  | }
2359 |  |  | }
2360 |  | 11621x | else if(v > 0)
2361 |  |  | {
2362 |  | 5993x | re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_assert_backref, sizeof(re_brace)));
2363 |  | 5993x | br->index = (int)v;
2364 |  | 5993x | if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
2365 |  |  | {
2366 |  |  | // Rewind to start of (? sequence:
2367 |  | 192x | --m_position;
2368 |  | 384x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2369 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2370 |  | 137x | return false;
2371 |  |  | }
2372 |  | 5801x | if(++m_position == m_end)
2373 |  |  | {
2374 |  |  | // Rewind to start of (? sequence:
2375 |  | 192x | --m_position;
2376 |  | 576x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2377 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2378 |  | 137x | return false;
2379 |  |  | }
2380 |  |  | }
2381 |  |  | else
2382 |  |  | {
2383 |  |  | // verify that we have a lookahead or lookbehind assert:
2384 |  | 5628x | if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_question)
2385 |  |  | {
2386 |  |  | // Rewind to start of (? sequence:
2387 |  | 192x | --m_position;
2388 |  | 192x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2389 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2390 |  | 137x | return false;
2391 |  |  | }
2392 |  | 5436x | if(++m_position == m_end)
2393 |  |  | {
2394 |  |  | // Rewind to start of (? sequence:
2395 |  | 192x | --m_position;
2396 |  | 384x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2397 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2398 |  | 137x | return false;
2399 |  |  | }
2400 |  | 5244x | if(this->m_traits.syntax_type(*m_position) == regex_constants::escape_type_left_word)
2401 |  |  | {
2402 |  | 2568x | if(++m_position == m_end)
2403 |  |  | {
2404 |  |  | // Rewind to start of (? sequence:
2405 |  | 192x | --m_position;
2406 |  | 576x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2407 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2408 |  | 137x | return false;
2409 |  |  | }
2410 |  | 2376x | if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal)
2411 |  | 2376x | && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not))
2412 |  |  | {
2413 |  |  | // Rewind to start of (? sequence:
2414 |  | 192x | --m_position;
2415 |  | 576x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2416 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2417 |  | 137x | return false;
2418 |  |  | }
2419 |  | 2184x | m_position -= 3;
2420 |  |  | }
2421 |  |  | else
2422 |  |  | {
2423 |  | 2676x | if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal)
2424 |  | 2676x | && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not))
2425 |  |  | {
2426 |  |  | // Rewind to start of (? sequence:
2427 |  | 192x | --m_position;
2428 |  | 384x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2429 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2430 |  | 137x | return false;
2431 |  |  | }
2432 |  | 2484x | m_position -= 2;
2433 |  |  | }
2434 |  |  | }
2435 |  | 16121x | break;
2436 |  |  | }
2437 |  | 192x | case regex_constants::syntax_close_mark:
2438 |  |  | // Rewind to start of (? sequence:
2439 |  | 192x | --m_position;
2440 |  | 384x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2441 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2442 |  | 137x | return false;
2443 |  | 4298x | case regex_constants::escape_type_end_buffer:
2444 |  |  | {
2445 |  | 4298x | name_delim = *m_position;
2446 |  | 21040x | named_capture_jump:
2447 |  | 21040x | markid = 0;
2448 |  | 21040x | if(0 == (this->flags() & regbase::nosubs))
2449 |  |  | {
2450 |  | 21040x | markid = ++m_mark_count;
2451 |  | 21040x | if(this->flags() & regbase::save_subexpression_location)
2452 |  | 9312x | this->m_pdata->m_subs.push_back(std::pair<std::size_t, std::size_t>(std::distance(m_base, m_position) - 2, 0));
2453 |  |  | }
2454 |  | 21040x | pb->index = markid;
2455 |  | 21040x | const charT* base = ++m_position;
2456 |  | 21040x | if(m_position == m_end)
2457 |  |  | {
2458 |  |  | // Rewind to start of (? sequence:
2459 |  | ✗ | --m_position;
2460 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2461 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2462 |  | ✗ | return false;
2463 |  |  | }
2464 |  | 72100x | while((m_position != m_end) && (*m_position != name_delim))
2465 |  | 51060x | ++m_position;
2466 |  | 21040x | if(m_position == m_end)
2467 |  |  | {
2468 |  |  | // Rewind to start of (? sequence:
2469 |  | 192x | --m_position;
2470 |  | 768x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2471 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2472 |  | 137x | return false;
2473 |  |  | }
2474 |  | 20848x | this->m_pdata->set_name(base, m_position, markid);
2475 |  | 20848x | ++m_position;
2476 |  | 20848x | break;
2477 |  |  | }
2478 |  | 42074x | default:
2479 |  | 42074x | if(*m_position == charT('R'))
2480 |  |  | {
2481 |  | 7896x | ++m_position;
2482 |  | 7896x | v = 0;
2483 |  | 7896x | if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
2484 |  |  | {
2485 |  |  | // Rewind to start of (? sequence:
2486 |  | ✗ | --m_position;
2487 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2488 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2489 |  | ✗ | return false;
2490 |  |  | }
2491 |  | 7896x | goto insert_recursion;
2492 |  |  | }
2493 |  | 34178x | if(*m_position == charT('&'))
2494 |  |  | {
2495 |  | 7416x | ++m_position;
2496 |  | 7416x | const charT* base = m_position;
2497 |  | 32868x | while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
2498 |  | 25452x | ++m_position;
2499 |  | 7416x | if(m_position == m_end)
2500 |  |  | {
2501 |  |  | // Rewind to start of (? sequence:
2502 |  | ✗ | --m_position;
2503 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2504 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2505 |  | ✗ | return false;
2506 |  |  | }
2507 |  | 7416x | v = static_cast<int>(hash_value_from_capture_name(base, m_position));
2508 |  | 7416x | goto insert_recursion;
2509 |  |  | }
2510 |  | 26762x | if(*m_position == charT('P'))
2511 |  |  | {
2512 |  | 2412x | ++m_position;
2513 |  | 2412x | if(m_position == m_end)
2514 |  |  | {
2515 |  |  | // Rewind to start of (? sequence:
2516 |  | ✗ | --m_position;
2517 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2518 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2519 |  | ✗ | return false;
2520 |  |  | }
2521 |  | 2412x | if(*m_position == charT('>'))
2522 |  |  | {
2523 |  | 2412x | ++m_position;
2524 |  | 2412x | const charT* base = m_position;
2525 |  | 10848x | while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
2526 |  | 8436x | ++m_position;
2527 |  | 2412x | if(m_position == m_end)
2528 |  |  | {
2529 |  |  | // Rewind to start of (? sequence:
2530 |  | ✗ | --m_position;
2531 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2532 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2533 |  | ✗ | return false;
2534 |  |  | }
2535 |  | 2412x | v = static_cast<int>(hash_value_from_capture_name(base, m_position));
2536 |  | 2412x | goto insert_recursion;
2537 |  |  | }
2538 |  |  | }
2539 |  |  | //
2540 |  |  | // lets assume that we have a (?imsx) group and try and parse it:
2541 |  |  | //
2542 |  | 24350x | option_group_jump:
2543 |  | 36926x | regex_constants::syntax_option_type opts = parse_options();
2544 |  | 36706x | if(m_position == m_end)
2545 |  |  | {
2546 |  |  | // Rewind to start of (? sequence:
2547 |  | 548x | --m_position;
2548 |  | 3014x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2549 |  | 548x | fail(regex_constants::error_perl_extension, m_position - m_base);
2550 |  | 548x | return false;
2551 |  |  | }
2552 |  |  | // make a note of whether we have a case change:
2553 |  | 36158x | m_has_case_change = ((opts & regbase::icase) != (this->flags() & regbase::icase));
2554 |  | 36158x | pb->index = markid = 0;
2555 |  | 36158x | if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark)
2556 |  |  | {
2557 |  |  | // update flags and carry on as normal:
2558 |  | 25140x | this->flags(opts);
2559 |  | 25140x | restore_flags = false;
2560 |  | 25140x | old_case_change |= m_has_case_change; // defer end of scope by one ')'
2561 |  |  | }
2562 |  | 11018x | else if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_colon)
2563 |  |  | {
2564 |  |  | // update flags and carry on until the matching ')' is found:
2565 |  | 10250x | this->flags(opts);
2566 |  | 10250x | ++m_position;
2567 |  |  | }
2568 |  |  | else
2569 |  |  | {
2570 |  |  | // Rewind to start of (? sequence:
2571 |  | 768x | --m_position;
2572 |  | 2496x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2573 |  | 768x | fail(regex_constants::error_perl_extension, m_position - m_base);
2574 |  | 548x | return false;
2575 |  |  | }
2576 |  |  |
2577 |  |  | // finally append a case change state if we need it:
2578 |  | 35390x | if(m_has_case_change)
2579 |  |  | {
2580 |  |  | static_cast<re_case*>(
2581 |  | 43309x | this->append_state(syntax_element_toggle_case, sizeof(re_case))
2582 |  | 22596x | )->icase = opts & regbase::icase;
2583 |  |  | }
2584 |  |  |
2585 |  |  | }
2586 |  |  | //
2587 |  |  | // now recursively add more states, this will terminate when we get to a
2588 |  |  | // matching ')' :
2589 |  |  | //
2590 |  | 271933x | parse_all();
2591 |  |  | //
2592 |  |  | // Unwind alternatives:
2593 |  |  | //
2594 |  | 271711x | if(0 == unwind_alts(last_paren_start))
2595 |  |  | {
2596 |  |  | // Rewind to start of (? sequence:
2597 |  | ✗ | --m_position;
2598 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2599 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base, "Invalid alternation operators within (?...) block.");
2600 |  | ✗ | return false;
2601 |  |  | }
2602 |  |  | //
2603 |  |  | // we either have a ')' or we have run out of characters prematurely:
2604 |  |  | //
2605 |  | 271711x | if(m_position == m_end)
2606 |  |  | {
2607 |  |  | // Rewind to start of (? sequence:
2608 |  | 1124x | --m_position;
2609 |  | 8553x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2610 |  | 2248x | this->fail(regex_constants::error_paren, std::distance(m_base, m_end));
2611 |  | 959x | return false;
2612 |  |  | }
2613 |  | 270587x | BOOST_REGEX_ASSERT(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark);
2614 |  | 270587x | ++m_position;
2615 |  |  | //
2616 |  |  | // restore the flags:
2617 |  |  | //
2618 |  | 270587x | if(restore_flags)
2619 |  |  | {
2620 |  |  | // append a case change state if we need it:
2621 |  | 245447x | if(m_has_case_change)
2622 |  |  | {
2623 |  |  | static_cast<re_case*>(
2624 |  | 25438x | this->append_state(syntax_element_toggle_case, sizeof(re_case))
2625 |  | 13272x | )->icase = old_flags & regbase::icase;
2626 |  |  | }
2627 |  | 245447x | this->flags(old_flags);
2628 |  |  | }
2629 |  |  | //
2630 |  |  | // set up the jump pointer if we have one:
2631 |  |  | //
2632 |  | 270587x | if(jump_offset)
2633 |  |  | {
2634 |  | 52681x | this->m_pdata->m_data.align();
2635 |  | 52681x | re_jump* jmp = static_cast<re_jump*>(this->getaddress(jump_offset));
2636 |  | 52681x | jmp->alt.i = this->m_pdata->m_data.size() - this->getoffset(jmp);
2637 |  | 52681x | if((this->m_last_state == jmp) && (markid != -2))
2638 |  |  | {
2639 |  |  | // Oops... we didn't have anything inside the assertion.
2640 |  |  | // Note we don't get here for negated forward lookahead as (?!)
2641 |  |  | // does have some uses.
2642 |  |  | // Rewind to start of (? sequence:
2643 |  | 192x | --m_position;
2644 |  | 768x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2645 |  | 247x | fail(regex_constants::error_perl_extension, m_position - m_base, "Invalid or empty zero width assertion.");
2646 |  | 137x | return false;
2647 |  |  | }
2648 |  |  | }
2649 |  |  | //
2650 |  |  | // verify that if this is conditional expression, that we do have
2651 |  |  | // an alternative, if not add one:
2652 |  |  | //
2653 |  | 270395x | if(markid == -4)
2654 |  |  | {
2655 |  | 16121x | re_syntax_base* b = this->getaddress(expected_alt_point);
2656 |  |  | // Make sure we have exactly one alternative following this state:
2657 |  | 16121x | if(b->type != syntax_element_alt)
2658 |  |  | {
2659 |  | 5366x | re_alt* alt = static_cast<re_alt*>(this->insert_state(expected_alt_point, syntax_element_alt, sizeof(re_alt)));
2660 |  | 5366x | alt->alt.i = this->m_pdata->m_data.size() - this->getoffset(alt);
2661 |  |  | }
2662 |  | 10755x | else if(((std::ptrdiff_t)this->m_pdata->m_data.size() > (static_cast<re_alt*>(b)->alt.i + this->getoffset(b))) && (static_cast<re_alt*>(b)->alt.i > 0) && this->getaddress(static_cast<re_alt*>(b)->alt.i, b)->type == syntax_element_alt)
2663 |  |  | {
2664 |  |  | // Can't have seen more than one alternative:
2665 |  |  | // Rewind to start of (? sequence:
2666 |  | 384x | --m_position;
2667 |  | 3840x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2668 |  | 494x | fail(regex_constants::error_bad_pattern, m_position - m_base, "More than one alternation operator | was encountered inside a conditional expression.");
2669 |  | 274x | return false;
2670 |  |  | }
2671 |  |  | else
2672 |  |  | {
2673 |  |  | // We must *not* have seen an alternative inside a (DEFINE) block:
2674 |  | 10371x | b = this->getaddress(b->next.i, b);
2675 |  | 10371x | if((b->type == syntax_element_assert_backref) && (static_cast<re_brace*>(b)->index == 9999))
2676 |  |  | {
2677 |  |  | // Rewind to start of (? sequence:
2678 |  | 168x | --m_position;
2679 |  | 3360x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2680 |  | 223x | fail(regex_constants::error_bad_pattern, m_position - m_base, "Alternation operators are not allowed inside a DEFINE block.");
2681 |  | 113x | return false;
2682 |  |  | }
2683 |  |  | }
2684 |  |  | // check for invalid repetition of next state:
2685 |  | 15569x | b = this->getaddress(expected_alt_point);
2686 |  | 15569x | b = this->getaddress(static_cast<re_alt*>(b)->next.i, b);
2687 |  | 15569x | if((b->type != syntax_element_assert_backref)
2688 |  | 4668x | && (b->type != syntax_element_startmark))
2689 |  |  | {
2690 |  |  | // Rewind to start of (? sequence:
2691 |  | 960x | --m_position;
2692 |  | 8256x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2693 |  | 1235x | fail(regex_constants::error_badrepeat, m_position - m_base, "A repetition operator cannot be applied to a zero-width assertion.");
2694 |  | 685x | return false;
2695 |  |  | }
2696 |  |  | }
2697 |  |  | //
2698 |  |  | // append closing parenthesis state:
2699 |  |  | //
2700 |  | 268883x | pb = static_cast<re_brace*>(this->append_state(syntax_element_endmark, sizeof(re_brace)));
2701 |  | 268883x | pb->index = markid;
2702 |  | 268883x | pb->icase = this->flags() & regbase::icase;
2703 |  | 268883x | this->m_paren_start = last_paren_start;
2704 |  |  | //
2705 |  |  | // restore the alternate insertion point:
2706 |  |  | //
2707 |  | 268883x | this->m_alt_insert_point = last_alt_point;
2708 |  |  | //
2709 |  |  | // and the case change data:
2710 |  |  | //
2711 |  | 268883x | m_has_case_change = old_case_change;
2712 |  |  | //
2713 |  |  | // And the mark_reset data:
2714 |  |  | //
2715 |  | 268883x | if(m_max_mark > m_mark_count)
2716 |  |  | {
2717 |  | 2340x | m_mark_count = m_max_mark;
2718 |  |  | }
2719 |  | 268883x | m_mark_reset = mark_reset;
2720 |  | 268883x | m_max_mark = max_mark;
2721 |  |  |
2722 |  |  |
2723 |  | 268883x | if(markid > 0)
2724 |  |  | {
2725 |  | 20848x | if(this->flags() & regbase::save_subexpression_location)
2726 |  | 9312x | this->m_pdata->m_subs.at((std::size_t)markid - 1).second = std::distance(m_base, m_position) - 1;
2727 |  |  | }
2728 |  | 268883x | return true;
2729 |  |  | }
2730 |  |  |
2731 |  |  | template <class charT, class traits>
2732 |  | 15500x | bool basic_regex_parser<charT, traits>::match_verb(const char* verb)
2733 |  |  | {
2734 |  | 70438x | while(*verb)
2735 |  |  | {
2736 |  | 55130x | if(static_cast<charT>(*verb) != *m_position)
2737 |  |  | {
2738 |  | 768x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2739 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2740 |  | 137x | return false;
2741 |  |  | }
2742 |  | 54938x | if(++m_position == m_end)
2743 |  |  | {
2744 |  | ✗ | --m_position;
2745 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2746 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2747 |  | ✗ | return false;
2748 |  |  | }
2749 |  | 54938x | ++verb;
2750 |  |  | }
2751 |  | 15308x | return true;
2752 |  |  | }
2753 |  |  |
2754 |  |  | #ifdef BOOST_REGEX_MSVC
2755 |  |  | # pragma warning(push)
2756 |  |  | #if BOOST_REGEX_MSVC >= 1800
2757 |  |  | #pragma warning(disable:26812)
2758 |  |  | #endif
2759 |  |  | #endif
2760 |  |  | template <class charT, class traits>
2761 |  | 16244x | bool basic_regex_parser<charT, traits>::parse_perl_verb()
2762 |  |  | {
2763 |  | 16244x | if(++m_position == m_end)
2764 |  |  | {
2765 |  |  | // Rewind to start of (* sequence:
2766 |  | 192x | --m_position;
2767 |  | 384x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2768 |  | 192x | fail(regex_constants::error_perl_extension, m_position - m_base);
2769 |  | 137x | return false;
2770 |  |  | }
2771 |  | 16052x | switch(*m_position)
2772 |  |  | {
2773 |  | 1632x | case 'F':
2774 |  | 1632x | if(++m_position == m_end)
2775 |  |  | {
2776 |  |  | // Rewind to start of (* sequence:
2777 |  | ✗ | --m_position;
2778 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2779 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2780 |  | ✗ | return false;
2781 |  |  | }
2782 |  | 1632x | if((this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark) || match_verb("AIL"))
2783 |  |  | {
2784 |  | 1440x | if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
2785 |  |  | {
2786 |  |  | // Rewind to start of (* sequence:
2787 |  | ✗ | --m_position;
2788 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2789 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2790 |  | ✗ | return false;
2791 |  |  | }
2792 |  | 1440x | ++m_position;
2793 |  | 1440x | this->append_state(syntax_element_fail);
2794 |  | 1440x | return true;
2795 |  |  | }
2796 |  | 137x | break;
2797 |  | 2702x | case 'A':
2798 |  | 2702x | if(++m_position == m_end)
2799 |  |  | {
2800 |  |  | // Rewind to start of (* sequence:
2801 |  | ✗ | --m_position;
2802 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2803 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2804 |  | ✗ | return false;
2805 |  |  | }
2806 |  | 2702x | if(match_verb("CCEPT"))
2807 |  |  | {
2808 |  | 2702x | if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
2809 |  |  | {
2810 |  |  | // Rewind to start of (* sequence:
2811 |  | ✗ | --m_position;
2812 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2813 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2814 |  | ✗ | return false;
2815 |  |  | }
2816 |  | 2702x | ++m_position;
2817 |  | 2702x | this->append_state(syntax_element_accept);
2818 |  | 2702x | return true;
2819 |  |  | }
2820 |  | ✗ | break;
2821 |  | 1445x | case 'C':
2822 |  | 1445x | if(++m_position == m_end)
2823 |  |  | {
2824 |  |  | // Rewind to start of (* sequence:
2825 |  | ✗ | --m_position;
2826 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2827 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2828 |  | ✗ | return false;
2829 |  |  | }
2830 |  | 1445x | if(match_verb("OMMIT"))
2831 |  |  | {
2832 |  | 1445x | if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
2833 |  |  | {
2834 |  |  | // Rewind to start of (* sequence:
2835 |  | ✗ | --m_position;
2836 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2837 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2838 |  | ✗ | return false;
2839 |  |  | }
2840 |  | 1445x | ++m_position;
2841 |  | 1445x | static_cast<re_commit*>(this->append_state(syntax_element_commit, sizeof(re_commit)))->action = commit_commit;
2842 |  | 1445x | this->m_pdata->m_disable_match_any = true;
2843 |  | 1445x | return true;
2844 |  |  | }
2845 |  | ✗ | break;
2846 |  | 720x | case 'P':
2847 |  | 720x | if(++m_position == m_end)
2848 |  |  | {
2849 |  |  | // Rewind to start of (* sequence:
2850 |  | ✗ | --m_position;
2851 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2852 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2853 |  | ✗ | return false;
2854 |  |  | }
2855 |  | 720x | if(match_verb("RUNE"))
2856 |  |  | {
2857 |  | 720x | if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
2858 |  |  | {
2859 |  |  | // Rewind to start of (* sequence:
2860 |  | ✗ | --m_position;
2861 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2862 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2863 |  | ✗ | return false;
2864 |  |  | }
2865 |  | 720x | ++m_position;
2866 |  | 720x | static_cast<re_commit*>(this->append_state(syntax_element_commit, sizeof(re_commit)))->action = commit_prune;
2867 |  | 720x | this->m_pdata->m_disable_match_any = true;
2868 |  | 720x | return true;
2869 |  |  | }
2870 |  | ✗ | break;
2871 |  | 1261x | case 'S':
2872 |  | 1261x | if(++m_position == m_end)
2873 |  |  | {
2874 |  |  | // Rewind to start of (* sequence:
2875 |  | ✗ | --m_position;
2876 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2877 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2878 |  | ✗ | return false;
2879 |  |  | }
2880 |  | 1261x | if(match_verb("KIP"))
2881 |  |  | {
2882 |  | 1261x | if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
2883 |  |  | {
2884 |  |  | // Rewind to start of (* sequence:
2885 |  | ✗ | --m_position;
2886 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2887 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2888 |  | ✗ | return false;
2889 |  |  | }
2890 |  | 1261x | ++m_position;
2891 |  | 1261x | static_cast<re_commit*>(this->append_state(syntax_element_commit, sizeof(re_commit)))->action = commit_skip;
2892 |  | 1261x | this->m_pdata->m_disable_match_any = true;
2893 |  | 1261x | return true;
2894 |  |  | }
2895 |  | ✗ | break;
2896 |  | 8100x | case 'T':
2897 |  | 8100x | if(++m_position == m_end)
2898 |  |  | {
2899 |  |  | // Rewind to start of (* sequence:
2900 |  | ✗ | --m_position;
2901 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2902 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2903 |  | ✗ | return false;
2904 |  |  | }
2905 |  | 8100x | if(match_verb("HEN"))
2906 |  |  | {
2907 |  | 8100x | if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark))
2908 |  |  | {
2909 |  |  | // Rewind to start of (* sequence:
2910 |  | ✗ | --m_position;
2911 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2912 |  | ✗ | fail(regex_constants::error_perl_extension, m_position - m_base);
2913 |  | ✗ | return false;
2914 |  |  | }
2915 |  | 8100x | ++m_position;
2916 |  | 8100x | this->append_state(syntax_element_then);
2917 |  | 8100x | this->m_pdata->m_disable_match_any = true;
2918 |  | 8100x | return true;
2919 |  |  | }
2920 |  | ✗ | break;
2921 |  |  | }
2922 |  |  | // Rewind to start of (* sequence:
2923 |  | 329x | --m_position;
2924 |  | 1069x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
2925 |  | 329x | fail(regex_constants::error_perl_extension, m_position - m_base);
2926 |  | 274x | return false;
2927 |  |  | }
2928 |  |  | #ifdef BOOST_REGEX_MSVC
2929 |  |  | # pragma warning(pop)
2930 |  |  | #endif
2931 |  |  |
2932 |  |  | template <class charT, class traits>
2933 |  | 4056x | bool basic_regex_parser<charT, traits>::add_emacs_code(bool negate)
2934 |  |  | {
2935 |  |  | //
2936 |  |  | // parses an emacs style \sx or \Sx construct.
2937 |  |  | //
2938 |  | 4056x | if(++m_position == m_end)
2939 |  |  | {
2940 |  |  | // Rewind to start of sequence:
2941 |  | ✗ | --m_position;
2942 |  | ✗ | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position;
2943 |  | ✗ | fail(regex_constants::error_escape, m_position - m_base);
2944 |  | ✗ | return false;
2945 |  |  | }
2946 |  | 4056x | basic_char_set<charT, traits> char_set;
2947 |  | 4056x | if(negate)
2948 |  | 1560x | char_set.negate();
2949 |  |  |
2950 |  |  | static const charT s_punct[5] = { 'p', 'u', 'n', 'c', 't', };
2951 |  |  |
2952 |  | 4056x | switch(*m_position)
2953 |  |  | {
2954 |  | 1248x | case 's':
2955 |  |  | case ' ':
2956 |  | 1248x | char_set.add_class(this->m_mask_space);
2957 |  | 1248x | break;
2958 |  | 312x | case 'w':
2959 |  | 312x | char_set.add_class(this->m_word_mask);
2960 |  | 312x | break;
2961 |  | 312x | case '_':
2962 |  | 312x | char_set.add_single(digraph<charT>(charT('$')));
2963 |  | 312x | char_set.add_single(digraph<charT>(charT('&')));
2964 |  | 312x | char_set.add_single(digraph<charT>(charT('*')));
2965 |  | 312x | char_set.add_single(digraph<charT>(charT('+')));
2966 |  | 312x | char_set.add_single(digraph<charT>(charT('-')));
2967 |  | 312x | char_set.add_single(digraph<charT>(charT('_')));
2968 |  | 312x | char_set.add_single(digraph<charT>(charT('<')));
2969 |  | 312x | char_set.add_single(digraph<charT>(charT('>')));
2970 |  | 312x | break;
2971 |  | 312x | case '.':
2972 |  | 312x | char_set.add_class(this->m_traits.lookup_classname(s_punct, s_punct+5));
2973 |  | 312x | break;
2974 |  | 312x | case '(':
2975 |  | 312x | char_set.add_single(digraph<charT>(charT('(')));
2976 |  | 312x | char_set.add_single(digraph<charT>(charT('[')));
2977 |  | 312x | char_set.add_single(digraph<charT>(charT('{')));
2978 |  | 312x | break;
2979 |  | 312x | case ')':
2980 |  | 312x | char_set.add_single(digraph<charT>(charT(')')));
2981 |  | 312x | char_set.add_single(digraph<charT>(charT(']')));
2982 |  | 312x | char_set.add_single(digraph<charT>(charT('}')));
2983 |  | 312x | break;
2984 |  | 312x | case '"':
2985 |  | 312x | char_set.add_single(digraph<charT>(charT('"')));
2986 |  | 312x | char_set.add_single(digraph<charT>(charT('\'')));
2987 |  | 312x | char_set.add_single(digraph<charT>(charT('`')));
2988 |  | 312x | break;
2989 |  | 312x | case '\'':
2990 |  | 312x | char_set.add_single(digraph<charT>(charT('\'')));
2991 |  | 312x | char_set.add_single(digraph<charT>(charT(',')));
2992 |  | 312x | char_set.add_single(digraph<charT>(charT('#')));
2993 |  | 312x | break;
2994 |  | 312x | case '<':
2995 |  | 312x | char_set.add_single(digraph<charT>(charT(';')));
2996 |  | 312x | break;
2997 |  | 312x | case '>':
2998 |  | 312x | char_set.add_single(digraph<charT>(charT('\n')));
2999 |  | 312x | char_set.add_single(digraph<charT>(charT('\f')));
3000 |  | 312x | break;
3001 |  | ✗ | default:
3002 |  | ✗ | fail(regex_constants::error_ctype, m_position - m_base);
3003 |  | ✗ | return false;
3004 |  |  | }
3005 |  | 4056x | if(0 == this->append_set(char_set))
3006 |  |  | {
3007 |  | ✗ | fail(regex_constants::error_ctype, m_position - m_base);
3008 |  | ✗ | return false;
3009 |  |  | }
3010 |  | 4056x | ++m_position;
3011 |  | 4056x | return true;
3012 |  | 4056x | }
3013 |  |  |
3014 |  |  | template <class charT, class traits>
3015 |  | 36926x | regex_constants::syntax_option_type basic_regex_parser<charT, traits>::parse_options()
3016 |  |  | {
3017 |  |  | // we have a (?imsx-imsx) group, convert it into a set of flags:
3018 |  | 36926x | regex_constants::syntax_option_type f = this->flags();
3019 |  | 36926x | bool breakout = false;
3020 |  |  | do
3021 |  |  | {
3022 |  | 62524x | switch(*m_position)
3023 |  |  | {
3024 |  | 2796x | case 's':
3025 |  | 2796x | f |= regex_constants::mod_s;
3026 |  | 2796x | f &= ~regex_constants::no_mod_s;
3027 |  | 2796x | break;
3028 |  | 888x | case 'm':
3029 |  | 888x | f &= ~regex_constants::no_mod_m;
3030 |  | 888x | break;
3031 |  | 15144x | case 'i':
3032 |  | 15144x | f |= regex_constants::icase;
3033 |  | 15144x | break;
3034 |  | 6962x | case 'x':
3035 |  | 6962x | f |= regex_constants::mod_x;
3036 |  | 6962x | break;
3037 |  | 36734x | default:
3038 |  | 36734x | breakout = true;
3039 |  | 36734x | continue;
3040 |  |  | }
3041 |  | 25790x | if(++m_position == m_end)
3042 |  |  | {
3043 |  |  | // Rewind to start of (? sequence:
3044 |  | 192x | --m_position;
3045 |  | 1152x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
3046 |  | 192x | fail(regex_constants::error_paren, m_position - m_base);
3047 |  | 137x | return false;
3048 |  |  | }
3049 |  |  | }
3050 |  | 62332x | while(!breakout);
3051 |  |  |
3052 |  | 36734x | breakout = false;
3053 |  |  |
3054 |  | 36734x | if(*m_position == static_cast<charT>('-'))
3055 |  |  | {
3056 |  | 15276x | if(++m_position == m_end)
3057 |  |  | {
3058 |  |  | // Rewind to start of (? sequence:
3059 |  | 192x | --m_position;
3060 |  | 768x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
3061 |  | 192x | fail(regex_constants::error_paren, m_position - m_base);
3062 |  | 137x | return false;
3063 |  |  | }
3064 |  |  | do
3065 |  |  | {
3066 |  | 30516x | switch(*m_position)
3067 |  |  | {
3068 |  | 1620x | case 's':
3069 |  | 1620x | f &= ~regex_constants::mod_s;
3070 |  | 1620x | f |= regex_constants::no_mod_s;
3071 |  | 1620x | break;
3072 |  | 540x | case 'm':
3073 |  | 540x | f |= regex_constants::no_mod_m;
3074 |  | 540x | break;
3075 |  | 8772x | case 'i':
3076 |  | 8772x | f &= ~regex_constants::icase;
3077 |  | 8772x | break;
3078 |  | 4884x | case 'x':
3079 |  | 4884x | f &= ~regex_constants::mod_x;
3080 |  | 4884x | break;
3081 |  | 14700x | default:
3082 |  | 14700x | breakout = true;
3083 |  | 14700x | continue;
3084 |  |  | }
3085 |  | 15816x | if(++m_position == m_end)
3086 |  |  | {
3087 |  |  | // Rewind to start of (? sequence:
3088 |  | 384x | --m_position;
3089 |  | 2304x | while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position;
3090 |  | 384x | fail(regex_constants::error_paren, m_position - m_base);
3091 |  | 274x | return false;
3092 |  |  | }
3093 |  |  | }
3094 |  | 30132x | while(!breakout);
3095 |  |  | }
3096 |  | 36158x | return f;
3097 |  |  | }
3098 |  |  |
3099 |  |  | template <class charT, class traits>
3100 |  | 937982x | bool basic_regex_parser<charT, traits>::unwind_alts(std::ptrdiff_t last_paren_start)
3101 |  |  | {
3102 |  |  | //
3103 |  |  | // If we didn't actually add any states after the last
3104 |  |  | // alternative then that's an error:
3105 |  |  | //
3106 |  | 937982x | if((this->m_alt_insert_point == static_cast<std::ptrdiff_t>(this->m_pdata->m_data.size()))
3107 |  | 25537x | && (!m_alt_jumps.empty()) && (m_alt_jumps.back() > last_paren_start)
3108 |  | 963519x | &&
3109 |  |  | !(
3110 |  | 2912x | ((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group)
3111 |  | 2463x | &&
3112 |  | 2463x | ((this->flags() & regbase::no_empty_expressions) == 0)
3113 |  |  | )
3114 |  |  | )
3115 |  |  | {
3116 |  | 1118x | fail(regex_constants::error_empty, this->m_position - this->m_base, "Can't terminate a sub-expression with an alternation operator |.");
3117 |  | 678x | return false;
3118 |  |  | }
3119 |  |  | //
3120 |  |  | // Fix up our alternatives:
3121 |  |  | //
3122 |  | 1193300x | while((!m_alt_jumps.empty()) && (m_alt_jumps.back() > last_paren_start))
3123 |  |  | {
3124 |  |  | //
3125 |  |  | // fix up the jump to point to the end of the states
3126 |  |  | // that we've just added:
3127 |  |  | //
3128 |  | 256216x | std::ptrdiff_t jump_offset = m_alt_jumps.back();
3129 |  | 256216x | m_alt_jumps.pop_back();
3130 |  | 256216x | this->m_pdata->m_data.align();
3131 |  | 256216x | re_jump* jmp = static_cast<re_jump*>(this->getaddress(jump_offset));
3132 |  | 256216x | if (jmp->type != syntax_element_jump)
3133 |  |  | {
3134 |  |  | // Something really bad happened, this used to be an assert,
3135 |  |  | // but we'll make it an error just in case we should ever get here.
3136 |  | ✗ | fail(regex_constants::error_unknown, this->m_position - this->m_base, "Internal logic failed while compiling the expression, probably you added a repeat to something non-repeatable!");
3137 |  | ✗ | return false;
3138 |  |  | }
3139 |  | 256216x | jmp->alt.i = this->m_pdata->m_data.size() - jump_offset;
3140 |  |  | }
3141 |  | 937084x | return true;
3142 |  |  | }
3143 |  |  |
3144 |  |  | #ifdef BOOST_REGEX_MSVC
3145 |  |  | #pragma warning(pop)
3146 |  |  | #endif
3147 |  |  |
3148 |  |  | } // namespace BOOST_REGEX_DETAIL_NS
3149 |  |  | } // namespace boost
3150 |  |  |
3151 |  |  | #endif
3152 |  |  |