#ifndef CPP2REGEX_H_CPP2 #define CPP2REGEX_H_CPP2 //=== Cpp2 type declarations ==================================================== #include "cpp2util.h" #line 1 "cpp2regex.h2" #line 22 "cpp2regex.h2" namespace cpp2 { namespace regex { #line 38 "cpp2regex.h2" template class match_group; #line 48 "cpp2regex.h2" template class match_return; #line 56 "cpp2regex.h2" template class match_context; #line 117 "cpp2regex.h2" class true_end_func; #line 125 "cpp2regex.h2" class no_reset; #line 132 "cpp2regex.h2" template class on_return; #line 159 "cpp2regex.h2" template class single_class_entry; #line 168 "cpp2regex.h2" template class range_class_entry; #line 177 "cpp2regex.h2" template class combined_class_entry; #line 186 "cpp2regex.h2" template class list_class_entry; #line 195 "cpp2regex.h2" template class named_class_entry; #line 202 "cpp2regex.h2" template class negated_class_entry; #line 211 "cpp2regex.h2" template class shorthand_class_entry; #line 259 "cpp2regex.h2" template class alternative_token_matcher; #line 337 "cpp2regex.h2" template class class_token_matcher; #line 492 "cpp2regex.h2" class range_flags; #line 501 "cpp2regex.h2" template class range_token_matcher; #line 673 "cpp2regex.h2" template class regular_expression; #line 756 "cpp2regex.h2" } } //=== Cpp2 type definitions and function declarations =========================== #line 1 "cpp2regex.h2" // Copyright 2022-2024 Herb Sutter // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // Part of the Cppfront Project, under the Apache License v2.0 with LLVM Exceptions. // See https://github.com/hsutter/cppfront/blob/main/LICENSE for license information. //=========================================================================== // Regex support //=========================================================================== #ifndef CPP2_CPP2REGEX_H #define CPP2_CPP2REGEX_H template using matcher_wrapper_type = typename matcher_wrapper::template wrap; template using matcher_context_type = typename matcher::context; #line 22 "cpp2regex.h2" namespace cpp2 { namespace regex { template using bstring = std::basic_string; template using bview = std::basic_string_view; //----------------------------------------------------------------------- // // Helper structures for the expression matching. // //----------------------------------------------------------------------- // // Structure for storing group information. // template class match_group { public: Iter start {}; public: Iter end {}; public: bool matched {false}; public: match_group(auto const& start_, auto const& end_, auto const& matched_); public: match_group(); #line 44 "cpp2regex.h2" }; // Return value for every matcher. // template class match_return { public: bool matched {false}; public: Iter pos {}; public: match_return(auto const& matched_, auto const& pos_); public: match_return(); #line 52 "cpp2regex.h2" }; // Modifiable state during matching. // template class match_context { public: Iter begin; public: Iter end; private: std::array,max_groups> groups {}; public: match_context(Iter const& begin_, Iter const& end_); #line 68 "cpp2regex.h2" public: match_context(match_context const& that); #line 68 "cpp2regex.h2" public: auto operator=(match_context const& that) -> match_context& ; #line 68 "cpp2regex.h2" public: match_context(match_context&& that) noexcept; #line 68 "cpp2regex.h2" public: auto operator=(match_context&& that) noexcept -> match_context& ; // Getter and setter for groups // public: [[nodiscard]] auto get_group(auto const& group) const& -> decltype(auto); public: [[nodiscard]] auto get_group_end(auto const& group) const& -> int; #line 80 "cpp2regex.h2" public: [[nodiscard]] auto get_group_start(auto const& group) const& -> int; #line 86 "cpp2regex.h2" public: [[nodiscard]] auto get_group_string(auto const& group) const& -> std::string; #line 93 "cpp2regex.h2" public: auto set_group_end(auto const& group, auto const& pos) & -> void; #line 98 "cpp2regex.h2" public: auto set_group_invalid(auto const& group) & -> void; #line 102 "cpp2regex.h2" public: auto set_group_start(auto const& group, auto const& pos) & -> void; #line 106 "cpp2regex.h2" public: [[nodiscard]] auto size() const& -> decltype(auto); // Misc functions // public: [[nodiscard]] auto fail() const& -> decltype(auto); public: [[nodiscard]] auto pass(cpp2::impl::in cur) const& -> decltype(auto); }; #line 115 "cpp2regex.h2" // End function that returns a valid match. // class true_end_func { public: [[nodiscard]] auto operator()(auto const& cur, auto& ctx) const& -> decltype(auto); }; #line 123 "cpp2regex.h2" // Empty group reset function. // class no_reset { public: auto operator()([[maybe_unused]] auto& unnamed_param_2) const& -> void; }; #line 131 "cpp2regex.h2" // Evaluate func on destruction of the handle. template class on_return { private: Func func; public: on_return(Func const& f); #line 136 "cpp2regex.h2" public: auto operator=(Func const& f) -> on_return& ; #line 140 "cpp2regex.h2" public: ~on_return() noexcept; public: on_return(on_return const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(on_return const&) -> void = delete; #line 143 "cpp2regex.h2" }; #line 146 "cpp2regex.h2" // Helper for auto deduction of the Func type. template [[nodiscard]] auto make_on_return(Func const& func) -> decltype(auto); #line 150 "cpp2regex.h2" //----------------------------------------------------------------------- // // Character classes for regular expressions. // //----------------------------------------------------------------------- // // Class syntax: Example: a // template class single_class_entry { public: [[nodiscard]] static auto includes(cpp2::impl::in c) -> decltype(auto); public: [[nodiscard]] static auto to_string() -> decltype(auto); public: single_class_entry() = default; public: single_class_entry(single_class_entry const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(single_class_entry const&) -> void = delete; #line 163 "cpp2regex.h2" }; #line 166 "cpp2regex.h2" // Class syntax: - Example: a-c // template class range_class_entry { public: [[nodiscard]] static auto includes(cpp2::impl::in c) -> decltype(auto); public: [[nodiscard]] static auto to_string() -> decltype(auto); public: range_class_entry() = default; public: range_class_entry(range_class_entry const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(range_class_entry const&) -> void = delete; #line 172 "cpp2regex.h2" }; #line 175 "cpp2regex.h2" // Helper for combining two character classes // template class combined_class_entry { public: [[nodiscard]] static auto includes(cpp2::impl::in c) -> decltype(auto); public: [[nodiscard]] static auto to_string() -> decltype(auto); public: combined_class_entry() = default; public: combined_class_entry(combined_class_entry const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(combined_class_entry const&) -> void = delete; #line 181 "cpp2regex.h2" }; #line 184 "cpp2regex.h2" // Class syntax: Example: abcd // template class list_class_entry { public: [[nodiscard]] static auto includes(cpp2::impl::in c) -> decltype(auto); public: [[nodiscard]] static auto to_string() -> decltype(auto); public: list_class_entry() = default; public: list_class_entry(list_class_entry const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(list_class_entry const&) -> void = delete; #line 190 "cpp2regex.h2" }; #line 193 "cpp2regex.h2" // Class syntax: [: class named_class_entry { public: [[nodiscard]] static auto includes(cpp2::impl::in c) -> decltype(auto); public: [[nodiscard]] static auto to_string() -> decltype(auto); public: named_class_entry() = default; public: named_class_entry(named_class_entry const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(named_class_entry const&) -> void = delete; #line 199 "cpp2regex.h2" }; #line 202 "cpp2regex.h2" template class negated_class_entry : public Inner { public: [[nodiscard]] static auto includes(cpp2::impl::in c) -> decltype(auto); public: negated_class_entry() = default; public: negated_class_entry(negated_class_entry const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(negated_class_entry const&) -> void = delete; #line 206 "cpp2regex.h2" }; #line 209 "cpp2regex.h2" // Short class syntax: \ Example: \w // template class shorthand_class_entry { public: [[nodiscard]] static auto includes(cpp2::impl::in c) -> decltype(auto); public: [[nodiscard]] static auto to_string() -> decltype(auto); public: shorthand_class_entry() = default; public: shorthand_class_entry(shorthand_class_entry const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(shorthand_class_entry const&) -> void = delete; #line 215 "cpp2regex.h2" }; #line 218 "cpp2regex.h2" // Named basic character classes // template using digits_class = named_class_entry>; template using lower_class = named_class_entry>; template using upper_class = named_class_entry>; // Named other classes // template using alnum_class = named_class_entry,upper_class,digits_class>>; template using alpha_class = named_class_entry,upper_class>>; template using ascii_class = named_class_entry>; template using blank_class = named_class_entry>; template using cntrl_class = named_class_entry,single_class_entry>>; template using graph_class = named_class_entry>; template using hor_space_class = named_class_entry>; template using print_class = named_class_entry>; template using punct_class = named_class_entry','?','@','[','\\',']','^','_','`','{','|','}','~',']'>>; template using space_class = named_class_entry>; template using ver_space_class = named_class_entry>; template using word_class = named_class_entry,single_class_entry>>; template using xdigit_class = named_class_entry,range_class_entry,digits_class>>; // Shorthand class entries // template using short_digits_class = shorthand_class_entry>; template using short_hor_space_class = shorthand_class_entry>; template using short_space_class = shorthand_class_entry>; template using short_vert_space_class = shorthand_class_entry>; template using short_word_class = shorthand_class_entry>; template using short_not_digits_class = negated_class_entry>>; template using short_not_hor_space_class = negated_class_entry>>; template using short_not_space_class = negated_class_entry>>; template using short_not_vert_space_class = negated_class_entry>>; template using short_not_word_class = negated_class_entry>>; #line 255 "cpp2regex.h2" // Regex syntax: | Example: ab|ba // // Non greedy implementation. First alternative that matches is chosen. // template class alternative_token_matcher { public: [[nodiscard]] static auto match(auto const& cur, auto& ctx, auto const& end_func, auto const& tail, auto const& ...functions) -> auto; #line 265 "cpp2regex.h2" private: template [[nodiscard]] static auto match_first(auto const& cur, auto& ctx, auto const& end_func, auto const& tail, auto const& cur_func, auto const& cur_reset, Other const& ...other) -> auto; public: alternative_token_matcher() = default; public: alternative_token_matcher(alternative_token_matcher const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(alternative_token_matcher const&) -> void = delete; #line 283 "cpp2regex.h2" }; #line 286 "cpp2regex.h2" // Regex syntax: . // template [[nodiscard]] auto any_token_matcher(auto& cur, auto& ctx) -> bool; #line 301 "cpp2regex.h2" // TODO: Check if vectorization works at some point with this implementation. // char_token_matcher: (inout cur, inout ctx) -> bool = { // if !(std::distance(cur, ctx.end) < tokens..size()) { // return false; // } // matched : bool = true; // (copy i: int = 0) while i < tokens..size() next i += 1 { // if tokens..data()[i] != cur[i] { // matched = false; // No break for performance optimization. Without break, the loop vectorizes. // } // } // if matched { // cur += tokens..size(); // } // return matched; // } // char_token_case_insensitive_matcher: (inout cur, inout ctx) -> bool = { // if !(std::distance(cur, ctx.end) < lower..size()) { // return false; // } // matched : bool = true; // (copy i : int = 0) while i < lower..size() next i += 1 { // if !(lower..data()[i] == cur[i] || upper..data()[i] == cur[i]) { // matched = false; // No break for performance optimization. Without break, the loop vectorizes. // } // } // if matched { // cur += lower..size(); // } // return matched; // } #line 335 "cpp2regex.h2" // Regex syntax: [] Example: [abcx-y[:digits:]] // template class class_token_matcher { public: [[nodiscard]] static auto match(auto& cur, auto& ctx) -> bool; #line 368 "cpp2regex.h2" private: template [[nodiscard]] static auto match_any(cpp2::impl::in c) -> bool; public: class_token_matcher() = default; public: class_token_matcher(class_token_matcher const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(class_token_matcher const&) -> void = delete; #line 381 "cpp2regex.h2" // TODO: Implement proper to string // to_string: () -> bstring = { // r: bstring = "["; // if negate { // r += "^"; // } // r += (bstring() + ... + List::to_string()); // r += "]"; // return r; // } #line 392 "cpp2regex.h2" }; #line 395 "cpp2regex.h2" // Named short classes // template using named_class_no_new_line = class_token_matcher>; template using named_class_digits = class_token_matcher>; template using named_class_hor_space = class_token_matcher>; template using named_class_space = class_token_matcher>; template using named_class_ver_space = class_token_matcher>; template using named_class_word = class_token_matcher>; template using named_class_not_digits = class_token_matcher>; template using named_class_not_hor_space = class_token_matcher>; template using named_class_not_space = class_token_matcher>; template using named_class_not_ver_space = class_token_matcher>; template using named_class_not_word = class_token_matcher>; #line 411 "cpp2regex.h2" // Regex syntax: \ Example: \1 // \g{name_or_number} // \k{name_or_number} // \k // \k'name_or_number' // template [[nodiscard]] auto group_ref_token_matcher(auto& cur, auto& ctx) -> bool; #line 448 "cpp2regex.h2" // Regex syntax: $ Example: aa$ // template [[nodiscard]] auto line_end_token_matcher(auto const& cur, auto& ctx) -> bool; #line 464 "cpp2regex.h2" // Regex syntax: ^ Example: ^aa // template [[nodiscard]] auto line_start_token_matcher(auto const& cur, auto& ctx) -> bool; #line 473 "cpp2regex.h2" // Regex syntax: (?=) or (?!) or (*pla), etc. Example: (?=AA) // // Parsed in group_token. // template [[nodiscard]] auto lookahead_token_matcher(auto const& cur, auto& ctx, auto const& func) -> bool; #line 488 "cpp2regex.h2" // TODO: @enum as template parameter currently not working. See issue https://github.com/hsutter/cppfront/issues/1147 #line 491 "cpp2regex.h2" // Options for range matching. class range_flags { public: static const int not_greedy;// Try to take as few as possible. public: static const int greedy;// Try to take as many as possible. public: static const int possessive;// Do not give back after a greedy match. No backtracking. public: range_flags() = default; public: range_flags(range_flags const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(range_flags const&) -> void = delete; }; #line 497 "cpp2regex.h2" #line 499 "cpp2regex.h2" // Regex syntax: {min, max} Example: a{2,4} // template class range_token_matcher { public: template [[nodiscard]] static auto match(Iter const& cur, auto& ctx, auto const& inner, auto const& reset_func, auto const& end_func, auto const& tail) -> auto; #line 517 "cpp2regex.h2" private: [[nodiscard]] static auto is_below_upper_bound(cpp2::impl::in count) -> bool; #line 522 "cpp2regex.h2" private: [[nodiscard]] static auto is_below_lower_bound(cpp2::impl::in count) -> bool; #line 527 "cpp2regex.h2" private: [[nodiscard]] static auto is_in_range(cpp2::impl::in count) -> bool; #line 533 "cpp2regex.h2" private: template [[nodiscard]] static auto match_min_count(Iter const& cur, auto& ctx, auto const& inner, auto const& end_func, int& count_r) -> auto; #line 549 "cpp2regex.h2" private: template [[nodiscard]] static auto match_greedy(cpp2::impl::in count, Iter const& cur, Iter const& last_valid, auto& ctx, auto const& inner, auto const& reset_func, auto const& end_func, auto const& other) -> match_return; #line 579 "cpp2regex.h2" private: template [[nodiscard]] static auto match_possessive(Iter const& cur, auto& ctx, auto const& inner, auto const& end_func, auto const& other) -> match_return; #line 607 "cpp2regex.h2" private: template [[nodiscard]] static auto match_not_greedy(Iter const& cur, auto& ctx, auto const& inner, auto const& end_func, auto const& other) -> match_return; public: range_token_matcher() = default; public: range_token_matcher(range_token_matcher const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(range_token_matcher const&) -> void = delete; #line 633 "cpp2regex.h2" }; #line 636 "cpp2regex.h2" // Regex syntax: \b or \B Example: \bword\b // // Matches the start end end of word boundaries. // template [[nodiscard]] auto word_boundary_token_matcher(auto& cur, auto& ctx) -> bool; #line 665 "cpp2regex.h2" //----------------------------------------------------------------------- // // Regular expression implementation. // //----------------------------------------------------------------------- // // Regular expression implementation template class regular_expression { public: template using matcher = matcher_wrapper_type;// TODO: Remove when nested types are allowed: https://github.com/hsutter/cppfront/issues/727 public: template using context = matcher_context_type>;// TODO: Remove when nested types are allowed: https://github.com/hsutter/cppfront/issues/727 public: template class search_return { public: bool matched; public: context ctx; public: int pos; public: search_return(cpp2::impl::in matched_, context const& ctx_, Iter const& pos_); #line 690 "cpp2regex.h2" public: [[nodiscard]] auto group_number() const& -> decltype(auto); public: [[nodiscard]] auto group(cpp2::impl::in g) const& -> decltype(auto); public: [[nodiscard]] auto group_start(cpp2::impl::in g) const& -> decltype(auto); public: [[nodiscard]] auto group_end(cpp2::impl::in g) const& -> decltype(auto); public: [[nodiscard]] auto group(cpp2::impl::in> g) const& -> decltype(auto); public: [[nodiscard]] auto group_start(cpp2::impl::in> g) const& -> decltype(auto); public: [[nodiscard]] auto group_end(cpp2::impl::in> g) const& -> decltype(auto); private: [[nodiscard]] auto get_group_id(cpp2::impl::in> g) const& -> auto; public: search_return(search_return const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(search_return const&) -> void = delete; #line 706 "cpp2regex.h2" }; public: [[nodiscard]] auto match(cpp2::impl::in> str) const& -> decltype(auto); public: [[nodiscard]] auto match(cpp2::impl::in> str, auto const& start) const& -> decltype(auto); public: [[nodiscard]] auto match(cpp2::impl::in> str, auto const& start, auto const& length) const& -> decltype(auto); public: template [[nodiscard]] auto match(Iter const& start, Iter const& end) const& -> search_return; #line 719 "cpp2regex.h2" public: [[nodiscard]] auto search(cpp2::impl::in> str) const& -> decltype(auto); public: [[nodiscard]] auto search(cpp2::impl::in> str, auto const& start) const& -> decltype(auto); public: [[nodiscard]] auto search(cpp2::impl::in> str, auto const& start, auto const& length) const& -> decltype(auto); public: template [[nodiscard]] auto search(Iter const& start, Iter const& end) const& -> search_return; #line 742 "cpp2regex.h2" public: [[nodiscard]] auto to_string() const& -> decltype(auto); // Helper functions // private: [[nodiscard]] static auto get_iter(cpp2::impl::in> str, auto const& pos) -> auto; public: regular_expression() = default; public: regular_expression(regular_expression const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(regular_expression const&) -> void = delete; #line 754 "cpp2regex.h2" }; } } #endif //=== Cpp2 function definitions ================================================= #line 1 "cpp2regex.h2" #line 22 "cpp2regex.h2" namespace cpp2 { namespace regex { template match_group::match_group(auto const& start_, auto const& end_, auto const& matched_) : start{ start_ } , end{ end_ } , matched{ matched_ }{} template match_group::match_group(){} template match_return::match_return(auto const& matched_, auto const& pos_) : matched{ matched_ } , pos{ pos_ }{} template match_return::match_return(){} #line 63 "cpp2regex.h2" template match_context::match_context(Iter const& begin_, Iter const& end_) : begin{ begin_ } , end{ end_ }{ #line 66 "cpp2regex.h2" } #line 68 "cpp2regex.h2" template match_context::match_context(match_context const& that) : begin{ that.begin } , end{ that.end } , groups{ that.groups }{} #line 68 "cpp2regex.h2" template auto match_context::operator=(match_context const& that) -> match_context& { begin = that.begin; end = that.end; groups = that.groups; return *this; } #line 68 "cpp2regex.h2" template match_context::match_context(match_context&& that) noexcept : begin{ std::move(that).begin } , end{ std::move(that).end } , groups{ std::move(that).groups }{} #line 68 "cpp2regex.h2" template auto match_context::operator=(match_context&& that) noexcept -> match_context& { begin = std::move(that).begin; end = std::move(that).end; groups = std::move(that).groups; return *this; } #line 72 "cpp2regex.h2" template [[nodiscard]] auto match_context::get_group(auto const& group) const& -> decltype(auto) { return CPP2_ASSERT_IN_BOUNDS(groups, group); } #line 74 "cpp2regex.h2" template [[nodiscard]] auto match_context::get_group_end(auto const& group) const& -> int{ if (cpp2::impl::cmp_greater_eq(group,max_groups) || !(CPP2_ASSERT_IN_BOUNDS(groups, group).matched)) { return 0; } return cpp2::unchecked_narrow(std::distance(begin, CPP2_ASSERT_IN_BOUNDS(groups, group).end)); } #line 80 "cpp2regex.h2" template [[nodiscard]] auto match_context::get_group_start(auto const& group) const& -> int{ if (cpp2::impl::cmp_greater_eq(group,max_groups) || !(CPP2_ASSERT_IN_BOUNDS(groups, group).matched)) { return 0; } return cpp2::unchecked_narrow(std::distance(begin, CPP2_ASSERT_IN_BOUNDS(groups, group).start)); } #line 86 "cpp2regex.h2" template [[nodiscard]] auto match_context::get_group_string(auto const& group) const& -> std::string{ if (cpp2::impl::cmp_greater_eq(group,max_groups) || !(CPP2_ASSERT_IN_BOUNDS(groups, group).matched)) { return ""; } return std::string(CPP2_ASSERT_IN_BOUNDS(groups, group).start, CPP2_ASSERT_IN_BOUNDS(groups, group).end); } #line 93 "cpp2regex.h2" template auto match_context::set_group_end(auto const& group, auto const& pos) & -> void{ CPP2_ASSERT_IN_BOUNDS(groups, group).end = pos; CPP2_ASSERT_IN_BOUNDS(groups, group).matched = true; } #line 98 "cpp2regex.h2" template auto match_context::set_group_invalid(auto const& group) & -> void{ CPP2_ASSERT_IN_BOUNDS(groups, group).matched = false; } #line 102 "cpp2regex.h2" template auto match_context::set_group_start(auto const& group, auto const& pos) & -> void{ CPP2_ASSERT_IN_BOUNDS(groups, group).start = pos; } #line 106 "cpp2regex.h2" template [[nodiscard]] auto match_context::size() const& -> decltype(auto) { return max_groups; } #line 110 "cpp2regex.h2" template [[nodiscard]] auto match_context::fail() const& -> decltype(auto) { return match_return(false, end); } #line 111 "cpp2regex.h2" template [[nodiscard]] auto match_context::pass(cpp2::impl::in cur) const& -> decltype(auto) { return match_return(true, cur); } #line 119 "cpp2regex.h2" [[nodiscard]] auto true_end_func::operator()(auto const& cur, auto& ctx) const& -> decltype(auto) { return ctx.pass(cur); } #line 127 "cpp2regex.h2" auto no_reset::operator()([[maybe_unused]] auto& unnamed_param_2) const& -> void{} #line 136 "cpp2regex.h2" template on_return::on_return(Func const& f) : func{ f }{ #line 138 "cpp2regex.h2" } #line 136 "cpp2regex.h2" template auto on_return::operator=(Func const& f) -> on_return& { func = f; return *this; #line 138 "cpp2regex.h2" } #line 140 "cpp2regex.h2" template on_return::~on_return() noexcept{ cpp2::move(*this).func(); } #line 147 "cpp2regex.h2" template [[nodiscard]] auto make_on_return(Func const& func) -> decltype(auto) { return on_return(func); } #line 161 "cpp2regex.h2" template [[nodiscard]] auto single_class_entry::includes(cpp2::impl::in c) -> decltype(auto) { return c == C; } #line 162 "cpp2regex.h2" template [[nodiscard]] auto single_class_entry::to_string() -> decltype(auto) { return bstring(1, C); } #line 170 "cpp2regex.h2" template [[nodiscard]] auto range_class_entry::includes(cpp2::impl::in c) -> decltype(auto) { return [_0 = Start, _1 = c, _2 = End]{ return cpp2::impl::cmp_less_eq(_0,_1) && cpp2::impl::cmp_less_eq(_1,_2); }(); } #line 171 "cpp2regex.h2" template [[nodiscard]] auto range_class_entry::to_string() -> decltype(auto) { return "" + cpp2::to_string(Start) + "-" + cpp2::to_string(End) + ""; } #line 179 "cpp2regex.h2" template [[nodiscard]] auto combined_class_entry::includes(cpp2::impl::in c) -> decltype(auto) { return (false || ... || List::includes(c)); } #line 180 "cpp2regex.h2" template [[nodiscard]] auto combined_class_entry::to_string() -> decltype(auto) { return (bstring() + ... + List::to_string()); } #line 188 "cpp2regex.h2" template [[nodiscard]] auto list_class_entry::includes(cpp2::impl::in c) -> decltype(auto) { return (false || ... || (List == c)); } #line 189 "cpp2regex.h2" template [[nodiscard]] auto list_class_entry::to_string() -> decltype(auto) { return (bstring() + ... + List); } #line 197 "cpp2regex.h2" template [[nodiscard]] auto named_class_entry::includes(cpp2::impl::in c) -> decltype(auto) { return Inner::includes(c); } #line 198 "cpp2regex.h2" template [[nodiscard]] auto named_class_entry::to_string() -> decltype(auto) { return "[:" + cpp2::to_string(Name.data()) + ":]"; } #line 205 "cpp2regex.h2" template [[nodiscard]] auto negated_class_entry::includes(cpp2::impl::in c) -> decltype(auto) { return !(Inner::includes(c)); } #line 213 "cpp2regex.h2" template [[nodiscard]] auto shorthand_class_entry::includes(cpp2::impl::in c) -> decltype(auto) { return Inner::includes(c); } #line 214 "cpp2regex.h2" template [[nodiscard]] auto shorthand_class_entry::to_string() -> decltype(auto) { return Name.str(); } #line 261 "cpp2regex.h2" template [[nodiscard]] auto alternative_token_matcher::match(auto const& cur, auto& ctx, auto const& end_func, auto const& tail, auto const& ...functions) -> auto{ return match_first(cur, ctx, end_func, tail, functions...); } #line 265 "cpp2regex.h2" template template [[nodiscard]] auto alternative_token_matcher::match_first(auto const& cur, auto& ctx, auto const& end_func, auto const& tail, auto const& cur_func, auto const& cur_reset, Other const& ...other) -> auto { auto inner_call {[_0 = (tail), _1 = (end_func)](auto const& tail_cur, auto& tail_ctx) -> auto{ return _0(tail_cur, tail_ctx, _1); }}; auto r {cur_func(cur, ctx, cpp2::move(inner_call))}; if (r.matched) { return r; }else { cur_reset(ctx); if constexpr (0 != sizeof...(Other)) { return match_first(cur, ctx, end_func, tail, other...); }else { return ctx.fail(); } } } #line 288 "cpp2regex.h2" template [[nodiscard]] auto any_token_matcher(auto& cur, auto& ctx) -> bool { if ( cur != ctx.end // any char except the end && (single_line || *cpp2::impl::assert_not_null(cur) != '\n')) // do not match new lines in multi line mode { cur += 1; return true; } // Else return false; } #line 339 "cpp2regex.h2" template [[nodiscard]] auto class_token_matcher::match(auto& cur, auto& ctx) -> bool { if constexpr (case_insensitive) { if ( cur != ctx.end && negate != ( match_any(string_util::safe_tolower(*cpp2::impl::assert_not_null(cur))) || match_any(string_util::safe_toupper(*cpp2::impl::assert_not_null(cur))))) { cur += 1; return true; } else { return false; } } else { if (cur != ctx.end && negate != match_any(*cpp2::impl::assert_not_null(cur))) { cur += 1; return true; } else { return false; } } } #line 368 "cpp2regex.h2" template template [[nodiscard]] auto class_token_matcher::match_any(cpp2::impl::in c) -> bool { bool r {First::includes(c)}; if (!(r)) { if constexpr (0 != sizeof...(Other)) { r = match_any(c); } } return r; } #line 417 "cpp2regex.h2" template [[nodiscard]] auto group_ref_token_matcher(auto& cur, auto& ctx) -> bool { auto g {ctx.get_group(group)}; auto group_pos {cpp2::move(g).start}; for( ; group_pos != g.end && cur != ctx.end; (++group_pos, ++cur) ) { if constexpr (case_insensitive) { if (string_util::safe_tolower(*cpp2::impl::assert_not_null(group_pos)) != string_util::safe_tolower(*cpp2::impl::assert_not_null(cur))) { return false; } } else { if (*cpp2::impl::assert_not_null(group_pos) != *cpp2::impl::assert_not_null(cur)) { return false; } } } if (cpp2::move(group_pos) == cpp2::move(g).end) { return true; } else { return false; } } #line 450 "cpp2regex.h2" template [[nodiscard]] auto line_end_token_matcher(auto const& cur, auto& ctx) -> bool { if (cur == ctx.end || (match_new_line && *cpp2::impl::assert_not_null(cur) == '\n')) { return true; } else {if (match_new_line_before_end && (*cpp2::impl::assert_not_null(cur) == '\n' && (cur + 1) == ctx.end)) {// Special case for new line at end. return true; } else { return false; }} } #line 466 "cpp2regex.h2" template [[nodiscard]] auto line_start_token_matcher(auto const& cur, auto& ctx) -> bool { return cur == ctx.begin || // Start of string (match_new_line && *cpp2::impl::assert_not_null((cur - 1)) == '\n'); // Start of new line } #line 477 "cpp2regex.h2" template [[nodiscard]] auto lookahead_token_matcher(auto const& cur, auto& ctx, auto const& func) -> bool { auto r {func(cur, ctx, true_end_func())}; if (!(positive)) { r.matched = !(r.matched); } return cpp2::move(r).matched; } #line 493 "cpp2regex.h2" inline CPP2_CONSTEXPR int range_flags::not_greedy{ 1 }; inline CPP2_CONSTEXPR int range_flags::greedy{ 2 }; inline CPP2_CONSTEXPR int range_flags::possessive{ 3 }; #line 504 "cpp2regex.h2" template template [[nodiscard]] auto range_token_matcher::match(Iter const& cur, auto& ctx, auto const& inner, auto const& reset_func, auto const& end_func, auto const& tail) -> auto { if (range_flags::possessive == kind) { return match_possessive(cur, ctx, inner, end_func, tail); } else {if (range_flags::greedy == kind) { return match_greedy(0, cur, ctx.end, ctx, inner, reset_func, end_func, tail); } else { // range_flags::not_greedy == kind return match_not_greedy(cur, ctx, inner, end_func, tail); }} } #line 517 "cpp2regex.h2" template [[nodiscard]] auto range_token_matcher::is_below_upper_bound(cpp2::impl::in count) -> bool{ if (-1 == max_count) {return true; } else {return cpp2::impl::cmp_less(count,max_count); } } #line 522 "cpp2regex.h2" template [[nodiscard]] auto range_token_matcher::is_below_lower_bound(cpp2::impl::in count) -> bool{ if (-1 == min_count) {return false; } else {return cpp2::impl::cmp_less(count,min_count); } } #line 527 "cpp2regex.h2" template [[nodiscard]] auto range_token_matcher::is_in_range(cpp2::impl::in count) -> bool{ if (-1 != min_count && cpp2::impl::cmp_less(count,min_count)) {return false; } if (-1 != max_count && cpp2::impl::cmp_greater(count,max_count)) {return false; } return true; } #line 533 "cpp2regex.h2" template template [[nodiscard]] auto range_token_matcher::match_min_count(Iter const& cur, auto& ctx, auto const& inner, auto const& end_func, int& count_r) -> auto { // TODO: count_r as out parameter introduces a performance loss. auto res {ctx.pass(cur)}; auto count {0}; while( is_below_lower_bound(count) && res.matched ) { res = inner(res.pos, ctx, end_func); if (res.matched) { count += 1; } } count_r = cpp2::move(count); return res; } #line 549 "cpp2regex.h2" template template [[nodiscard]] auto range_token_matcher::match_greedy(cpp2::impl::in count, Iter const& cur, Iter const& last_valid, auto& ctx, auto const& inner, auto const& reset_func, auto const& end_func, auto const& other) -> match_return { auto inner_call {[_0 = (count + 1), _1 = (cur), _2 = (inner), _3 = (reset_func), _4 = (end_func), _5 = (other)](auto const& tail_cur, auto& tail_ctx) -> auto{ return match_greedy(_0, tail_cur, _1, tail_ctx, _2, _3, _4, _5); }}; auto is_m_valid {true}; auto r {ctx.fail()}; if (is_below_upper_bound(count) && (is_below_lower_bound(count) || cur != last_valid)) { is_m_valid = false; // Group ranges in M are invalidated through the call. r = inner(cur, ctx, cpp2::move(inner_call)); } if (!(r.matched) && is_in_range(count)) { // The recursion did not yield a match try now the tail r = other(cur, ctx, end_func); if (r.matched && !(cpp2::move(is_m_valid))) { // We have a match rematch M if required reset_func(ctx); if (cpp2::impl::cmp_greater(count,0)) { static_cast(inner(last_valid, ctx, true_end_func())); } } } return r; } #line 579 "cpp2regex.h2" template template [[nodiscard]] auto range_token_matcher::match_possessive(Iter const& cur, auto& ctx, auto const& inner, auto const& end_func, auto const& other) -> match_return { auto count {0}; auto r {match_min_count(cur, ctx, inner, end_func, count)}; if (!(r.matched)) { return r; } auto pos {r.pos}; while( r.matched && is_below_upper_bound(count) ) { r = inner(pos, ctx, true_end_func()); if (pos == r.pos) { break; // Break infinite loop. } if (r.matched) { count += 1; pos = r.pos; } } return other(cpp2::move(pos), ctx, end_func); } #line 607 "cpp2regex.h2" template template [[nodiscard]] auto range_token_matcher::match_not_greedy(Iter const& cur, auto& ctx, auto const& inner, auto const& end_func, auto const& other) -> match_return { auto count {0}; auto start {match_min_count(cur, ctx, inner, end_func, count)}; if (!(start.matched)) { return start; } auto pos {cpp2::move(start).pos}; while( is_below_upper_bound(count) ) { auto o {other(pos, ctx, end_func)}; if (o.matched) { return o; } auto r {inner(pos, ctx, end_func)}; if (!(r.matched)) { return ctx.fail(); } count += 1; pos = cpp2::move(r).pos; } return other(cpp2::move(pos), ctx, end_func); // Upper bound reached. } #line 640 "cpp2regex.h2" template [[nodiscard]] auto word_boundary_token_matcher(auto& cur, auto& ctx) -> bool { word_class words {}; auto is_match {false}; if (cur == ctx.begin) {// String start if (cur != ctx.end) {// No empty string is_match = cpp2::move(words).includes(*cpp2::impl::assert_not_null(cur)); } } else {if (cur == ctx.end) {// String end is_match = cpp2::move(words).includes(*cpp2::impl::assert_not_null((cur - 1))); } else { // Middle of string is_match = (words.includes(*cpp2::impl::assert_not_null((cur - 1))) && !(words.includes(*cpp2::impl::assert_not_null(cur)))) // End of word: \w\W || (!(words.includes(*cpp2::impl::assert_not_null((cur - 1)))) && words.includes(*cpp2::impl::assert_not_null(cur)));// Start of word: \W\w }} if (negate) { is_match = !(is_match); } return is_match; } #line 684 "cpp2regex.h2" template template regular_expression::search_return::search_return(cpp2::impl::in matched_, context const& ctx_, Iter const& pos_) : matched{ matched_ } , ctx{ ctx_ } , pos{ cpp2::unchecked_narrow(std::distance(ctx_.begin, pos_)) }{ #line 688 "cpp2regex.h2" } #line 690 "cpp2regex.h2" template template [[nodiscard]] auto regular_expression::search_return::group_number() const& -> decltype(auto) { return ctx.size(); } #line 691 "cpp2regex.h2" template template [[nodiscard]] auto regular_expression::search_return::group(cpp2::impl::in g) const& -> decltype(auto) { return ctx.get_group_string(g); } #line 692 "cpp2regex.h2" template template [[nodiscard]] auto regular_expression::search_return::group_start(cpp2::impl::in g) const& -> decltype(auto) { return ctx.get_group_start(g); } #line 693 "cpp2regex.h2" template template [[nodiscard]] auto regular_expression::search_return::group_end(cpp2::impl::in g) const& -> decltype(auto) { return ctx.get_group_end(g); } #line 695 "cpp2regex.h2" template template [[nodiscard]] auto regular_expression::search_return::group(cpp2::impl::in> g) const& -> decltype(auto) { return group(get_group_id(g)); } #line 696 "cpp2regex.h2" template template [[nodiscard]] auto regular_expression::search_return::group_start(cpp2::impl::in> g) const& -> decltype(auto) { return group_start(get_group_id(g)); } #line 697 "cpp2regex.h2" template template [[nodiscard]] auto regular_expression::search_return::group_end(cpp2::impl::in> g) const& -> decltype(auto) { return group_end(get_group_id(g)); } #line 699 "cpp2regex.h2" template template [[nodiscard]] auto regular_expression::search_return::get_group_id(cpp2::impl::in> g) const& -> auto{ auto group_id {matcher::get_named_group_index(g)}; if (-1 == group_id) { // TODO: Throw error. } return group_id; } #line 708 "cpp2regex.h2" template [[nodiscard]] auto regular_expression::match(cpp2::impl::in> str) const& -> decltype(auto) { return match(str.begin(), str.end()); } #line 709 "cpp2regex.h2" template [[nodiscard]] auto regular_expression::match(cpp2::impl::in> str, auto const& start) const& -> decltype(auto) { return match(get_iter(str, start), str.end()); } #line 710 "cpp2regex.h2" template [[nodiscard]] auto regular_expression::match(cpp2::impl::in> str, auto const& start, auto const& length) const& -> decltype(auto) { return match(get_iter(str, start), get_iter(str, start + length)); } #line 711 "cpp2regex.h2" template template [[nodiscard]] auto regular_expression::match(Iter const& start, Iter const& end) const& -> search_return { context ctx {start, end}; auto r {matcher::entry(start, ctx)}; return search_return(r.matched && r.pos == end, cpp2::move(ctx), r.pos); } #line 719 "cpp2regex.h2" template [[nodiscard]] auto regular_expression::search(cpp2::impl::in> str) const& -> decltype(auto) { return search(str.begin(), str.end()); } #line 720 "cpp2regex.h2" template [[nodiscard]] auto regular_expression::search(cpp2::impl::in> str, auto const& start) const& -> decltype(auto) { return search(get_iter(str, start), str.end()); } #line 721 "cpp2regex.h2" template [[nodiscard]] auto regular_expression::search(cpp2::impl::in> str, auto const& start, auto const& length) const& -> decltype(auto) { return search(get_iter(str, start), get_iter(str, start + length)); } #line 722 "cpp2regex.h2" template template [[nodiscard]] auto regular_expression::search(Iter const& start, Iter const& end) const& -> search_return { context ctx {start, end}; auto r {ctx.fail()}; auto cur {start}; for( ; true; (++cur) ) { r = matcher::entry(cur, ctx); if (r.matched) { break; } if (cur == ctx.end) { break; } } return search_return(r.matched, cpp2::move(ctx), cpp2::move(r).pos); } #line 742 "cpp2regex.h2" template [[nodiscard]] auto regular_expression::to_string() const& -> decltype(auto) { return matcher_wrapper::to_string(); } #line 746 "cpp2regex.h2" template [[nodiscard]] auto regular_expression::get_iter(cpp2::impl::in> str, auto const& pos) -> auto{ if (cpp2::impl::cmp_less(pos,str.size())) { return str.begin() + pos; } else { return str.end(); } } #line 756 "cpp2regex.h2" } } #endif