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