diff --git a/docs/notes/regex_status.md b/docs/notes/regex_status.md
index fa43c928a7..0ef8ef7f8e 100644
--- a/docs/notes/regex_status.md
+++ b/docs/notes/regex_status.md
@@ -15,7 +15,7 @@ The listings are taken from the [Perl regex docs](https://perldoc.perl.org/perlr
| **`s`** | Treat the string as single line. That is, change `.` to match any character whatsoever, even a newline, which normally it would not match. | Supported |
| ***`x` and `xx`** | Extend your pattern's legibility by permitting whitespace and comments. For details see: [Perl regex docs: `/x` and `/xx`](https://perldoc.perl.org/perlre#/x-and-/xx). | Supported |
| **`n`** | Prevent the grouping metacharacters `(` and `)` from capturing. This modifier will stop `$1`, `$2`, etc. from being filled in. | Supported |
-| **`c`** | Keep the current position during repeated matching. | Planned |
+| **`c`** | Keep the current position during repeated matching. | Supported |
### Escape sequences __(Complete)__
@@ -96,7 +96,7 @@ The listings are taken from the [Perl regex docs](https://perldoc.perl.org/perlr
| **`\A`** | Match only at beginning of string | Supported |
| **`\Z`** | Match only at end of string, or before newline at the end | Supported |
| **`\z`** | Match only at end of string | Supported |
-| **`\G`** | Match only at pos() (e.g. at the end-of-match position of prior m//g) | Planned |
+| **`\G`** | Match only at pos() (e.g. at the end-of-match position of prior m//g) | Supported |
### Capture groups __(Complete)__
@@ -128,8 +128,8 @@ The listings are taken from the [Perl regex docs](https://perldoc.perl.org/perlr
| **`(?'NAME'pattern)`** | Named capture group | Supported |
| **`(?(condition)yes-pattern`|
`no-pattern)`** | Conditional patterns. | Planned |
| **`(?(condition)yes-pattern)`** | Conditional patterns. | Planned |
-| **`(?>pattern)`** | Atomic patterns. (Disable backtrack.) | Planned |
-| **`(*atomic:pattern)`** | Atomic patterns. (Disable backtrack.) | Planned |
+| **`(?>pattern)`** | Atomic patterns. (Disable backtrack.) | Supported |
+| **`(*atomic:pattern)`** | Atomic patterns. (Disable backtrack.) | Supported |
### Lookaround Assertions
@@ -142,12 +142,12 @@ The listings are taken from the [Perl regex docs](https://perldoc.perl.org/perlr
| **`(?!pattern)`** | Negative look ahead. | Supported |
| **`(*nla:pattern)`** | Negative look ahead. | Supported |
| **`(*negative_lookahead:pattern)`** | Negative look ahead. | Supported |
-| **`(?<=pattern)`** | Positive look behind. | Planned |
-| **`(*plb:pattern)`** | Positive look behind. | Planned |
-| **`(*positive_lookbehind:pattern)`** | Positive look behind. | Planned |
-| **`(?Planned |
-| **`(*nlb:pattern)`** | Negative look behind. | Planned |
-| **`(*negative_lookbehind:pattern)`** | Negative look behind. | Planned |
+| **`(?<=pattern)`** | Positive look behind. | Supported |
+| **`(*plb:pattern)`** | Positive look behind. | Supported |
+| **`(*positive_lookbehind:pattern)`** | Positive look behind. | Supported |
+| **`(?Supported |
+| **`(*nlb:pattern)`** | Negative look behind. | Supported |
+| **`(*negative_lookbehind:pattern)`** | Negative look behind. | Supported |
### Special Backtracking Control Verbs
diff --git a/include/cpp2regex.h b/include/cpp2regex.h
index 27b4f2b9b3..abf28a1cba 100644
--- a/include/cpp2regex.h
+++ b/include/cpp2regex.h
@@ -10,67 +10,70 @@
#line 1 "cpp2regex.h2"
-#line 22 "cpp2regex.h2"
+#line 20 "cpp2regex.h2"
namespace cpp2 {
namespace regex {
-#line 38 "cpp2regex.h2"
+#line 36 "cpp2regex.h2"
template class match_group;
-#line 48 "cpp2regex.h2"
+#line 46 "cpp2regex.h2"
template class match_return;
-#line 56 "cpp2regex.h2"
+#line 54 "cpp2regex.h2"
template class match_context;
-#line 117 "cpp2regex.h2"
+#line 125 "cpp2regex.h2"
+template class reverse_match_context;
+
+#line 194 "cpp2regex.h2"
class true_end_func;
-#line 125 "cpp2regex.h2"
+#line 202 "cpp2regex.h2"
class no_reset;
-#line 132 "cpp2regex.h2"
+#line 209 "cpp2regex.h2"
template class on_return;
-#line 159 "cpp2regex.h2"
+#line 236 "cpp2regex.h2"
template class single_class_entry;
-#line 168 "cpp2regex.h2"
+#line 245 "cpp2regex.h2"
template class range_class_entry;
-#line 177 "cpp2regex.h2"
+#line 254 "cpp2regex.h2"
template class combined_class_entry;
-#line 186 "cpp2regex.h2"
+#line 263 "cpp2regex.h2"
template class list_class_entry;
-#line 195 "cpp2regex.h2"
+#line 272 "cpp2regex.h2"
template class named_class_entry;
-#line 202 "cpp2regex.h2"
+#line 279 "cpp2regex.h2"
template class negated_class_entry;
-#line 211 "cpp2regex.h2"
+#line 288 "cpp2regex.h2"
template class shorthand_class_entry;
-#line 259 "cpp2regex.h2"
+#line 336 "cpp2regex.h2"
template class alternative_token_matcher;
-#line 337 "cpp2regex.h2"
+#line 427 "cpp2regex.h2"
template class class_token_matcher;
-#line 492 "cpp2regex.h2"
+#line 604 "cpp2regex.h2"
class range_flags;
-#line 501 "cpp2regex.h2"
+#line 613 "cpp2regex.h2"
template class range_token_matcher;
-#line 673 "cpp2regex.h2"
-template class regular_expression;
+#line 785 "cpp2regex.h2"
+template class regular_expression;
-#line 756 "cpp2regex.h2"
+#line 921 "cpp2regex.h2"
}
}
@@ -93,13 +96,11 @@ template class regular_expression;
#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;
+template
+using matcher_context_type = typename matcher::template context;
-#line 22 "cpp2regex.h2"
+#line 20 "cpp2regex.h2"
namespace cpp2 {
namespace regex {
@@ -125,7 +126,7 @@ template class match_group
public: match_group(auto const& start_, auto const& end_, auto const& matched_);
public: match_group();
-#line 44 "cpp2regex.h2"
+#line 42 "cpp2regex.h2"
};
// Return value for every matcher.
@@ -137,7 +138,7 @@ template class match_return
public: match_return(auto const& matched_, auto const& pos_);
public: match_return();
-#line 52 "cpp2regex.h2"
+#line 50 "cpp2regex.h2"
};
// Modifiable state during matching.
@@ -151,46 +152,121 @@ template class match_context
public: match_context(Iter const& begin_, Iter const& end_);
-#line 68 "cpp2regex.h2"
+#line 66 "cpp2regex.h2"
public: match_context(match_context const& that);
-#line 68 "cpp2regex.h2"
+#line 66 "cpp2regex.h2"
public: auto operator=(match_context const& that) -> match_context& ;
-#line 68 "cpp2regex.h2"
+#line 66 "cpp2regex.h2"
public: match_context(match_context&& that) noexcept;
-#line 68 "cpp2regex.h2"
+#line 66 "cpp2regex.h2"
public: auto operator=(match_context&& that) noexcept -> match_context& ;
+ // String end and start positions
+ //
+ public: [[nodiscard]] auto get_string_start() const& -> decltype(auto);
+ public: [[nodiscard]] auto get_string_end() const& -> decltype(auto);
+
// 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"
+#line 83 "cpp2regex.h2"
public: [[nodiscard]] auto get_group_start(auto const& group) const& -> int;
-#line 86 "cpp2regex.h2"
+#line 89 "cpp2regex.h2"
public: [[nodiscard]] auto get_group_string(auto const& group) const& -> std::string;
-#line 93 "cpp2regex.h2"
+#line 96 "cpp2regex.h2"
public: auto set_group_end(auto const& group, auto const& pos) & -> void;
-#line 98 "cpp2regex.h2"
+#line 101 "cpp2regex.h2"
public: auto set_group_invalid(auto const& group) & -> void;
-#line 102 "cpp2regex.h2"
+#line 105 "cpp2regex.h2"
public: auto set_group_start(auto const& group, auto const& pos) & -> void;
-#line 106 "cpp2regex.h2"
+#line 109 "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);
+
+ public: auto reset() & -> void;
+
+#line 121 "cpp2regex.h2"
};
-#line 115 "cpp2regex.h2"
+// Wrapper of context for reverse matches. Implements only the minimal interface for matching.
+//
+template class reverse_match_context
+ {
+ public: using ReverseIter = std::reverse_iterator;
+ public: match_context* forward_context;
+
+ public: ReverseIter begin;
+ public: ReverseIter end;
+
+ public: reverse_match_context(auto const& forward_context_);
+#line 133 "cpp2regex.h2"
+ public: auto operator=(auto const& forward_context_) -> reverse_match_context& ;
+
+#line 139 "cpp2regex.h2"
+ public: reverse_match_context(reverse_match_context const& that);
+#line 139 "cpp2regex.h2"
+ public: auto operator=(reverse_match_context const& that) -> reverse_match_context& ;
+#line 139 "cpp2regex.h2"
+ public: reverse_match_context(reverse_match_context&& that) noexcept;
+#line 139 "cpp2regex.h2"
+ public: auto operator=(reverse_match_context&& that) noexcept -> reverse_match_context& ;
+
+ // String end and start positions
+ //
+ public: [[nodiscard]] auto get_string_start() const& -> decltype(auto);
+ public: [[nodiscard]] auto get_string_end() const& -> decltype(auto);
+
+ // Getter and setter for groups
+ //
+ public: auto set_group_end(auto const& group, auto const& pos) & -> void;
+
+#line 152 "cpp2regex.h2"
+ public: auto set_group_invalid(auto const& group) & -> void;
+
+#line 156 "cpp2regex.h2"
+ public: auto set_group_start(auto const& group, auto const& pos) & -> void;
+
+#line 160 "cpp2regex.h2"
+ // Misc functions
+ //
+ public: [[nodiscard]] auto fail() const& -> decltype(auto);
+ public: [[nodiscard]] auto pass(cpp2::impl::in cur) const& -> decltype(auto);
+};
+
+// Helpers for creating wrappers of the match context.
+//
+template [[nodiscard]] auto make_forward_match_context(match_context& ctx) -> decltype(auto);
+
+#line 172 "cpp2regex.h2"
+template [[nodiscard]] auto make_forward_match_context(reverse_match_context& ctx) -> decltype(auto);
+
+#line 176 "cpp2regex.h2"
+template [[nodiscard]] auto make_reverse_match_context(match_context& ctx) -> auto;
+
+#line 180 "cpp2regex.h2"
+template [[nodiscard]] auto make_reverse_match_context(reverse_match_context& ctx) -> decltype(auto);
+
+#line 184 "cpp2regex.h2"
+// Helpers for creating wrappers of the iterators.
+//
+template [[nodiscard]] auto make_forward_iterator(Iter const& pos) -> auto;
+template [[nodiscard]] auto make_forward_iterator(std::reverse_iterator const& pos) -> auto;
+template [[nodiscard]] auto make_reverse_iterator(Iter const& pos) -> auto;
+template [[nodiscard]] auto make_reverse_iterator(std::reverse_iterator const& pos) -> auto;
+
+#line 192 "cpp2regex.h2"
// End function that returns a valid match.
//
class true_end_func
@@ -198,7 +274,7 @@ class true_end_func
public: [[nodiscard]] auto operator()(auto const& cur, auto& ctx) const& -> decltype(auto);
};
-#line 123 "cpp2regex.h2"
+#line 200 "cpp2regex.h2"
// Empty group reset function.
//
class no_reset
@@ -206,30 +282,30 @@ class no_reset
public: auto operator()([[maybe_unused]] auto& unnamed_param_2) const& -> void;
};
-#line 131 "cpp2regex.h2"
+#line 208 "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"
+#line 213 "cpp2regex.h2"
public: auto operator=(Func const& f) -> on_return& ;
-#line 140 "cpp2regex.h2"
+#line 217 "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 220 "cpp2regex.h2"
};
-#line 146 "cpp2regex.h2"
+#line 223 "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"
+#line 227 "cpp2regex.h2"
//-----------------------------------------------------------------------
//
// Character classes for regular expressions.
@@ -247,10 +323,10 @@ template class single_class_entry
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 240 "cpp2regex.h2"
};
-#line 166 "cpp2regex.h2"
+#line 243 "cpp2regex.h2"
// Class syntax: - Example: a-c
//
template class range_class_entry
@@ -261,10 +337,10 @@ template class range_class_entry
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 249 "cpp2regex.h2"
};
-#line 175 "cpp2regex.h2"
+#line 252 "cpp2regex.h2"
// Helper for combining two character classes
//
template class combined_class_entry
@@ -275,10 +351,10 @@ template class combined_class_entry
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 258 "cpp2regex.h2"
};
-#line 184 "cpp2regex.h2"
+#line 261 "cpp2regex.h2"
// Class syntax: Example: abcd
//
template class list_class_entry
@@ -289,10 +365,10 @@ template class list_class_entry
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 267 "cpp2regex.h2"
};
-#line 193 "cpp2regex.h2"
+#line 270 "cpp2regex.h2"
// Class syntax: [: class named_class_entry
@@ -303,10 +379,10 @@ template class n
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 276 "cpp2regex.h2"
};
-#line 202 "cpp2regex.h2"
+#line 279 "cpp2regex.h2"
template class negated_class_entry
: public Inner {
@@ -315,10 +391,10 @@ template class negated_class_entry
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 283 "cpp2regex.h2"
};
-#line 209 "cpp2regex.h2"
+#line 286 "cpp2regex.h2"
// Short class syntax: \ Example: \w
//
template class shorthand_class_entry
@@ -329,10 +405,10 @@ template class s
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 292 "cpp2regex.h2"
};
-#line 218 "cpp2regex.h2"
+#line 295 "cpp2regex.h2"
// Named basic character classes
//
template using digits_class = named_class_entry>;
@@ -369,7 +445,7 @@ template using short_not_space_class = nega
template using short_not_vert_space_class = negated_class_entry>>;
template using short_not_word_class = negated_class_entry>>;
-#line 255 "cpp2regex.h2"
+#line 332 "cpp2regex.h2"
// Regex syntax: | Example: ab|ba
//
// Non greedy implementation. First alternative that matches is chosen.
@@ -378,22 +454,27 @@ 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"
+#line 342 "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 360 "cpp2regex.h2"
};
-#line 286 "cpp2regex.h2"
+#line 363 "cpp2regex.h2"
// Regex syntax: .
//
template [[nodiscard]] auto any_token_matcher(auto& cur, auto& ctx) -> bool;
-#line 301 "cpp2regex.h2"
+#line 377 "cpp2regex.h2"
+// Regex syntax: (?>) Example: a(?>bc|c)c
+//
+template [[nodiscard]] auto atomic_group_matcher(Iter const& cur, auto& ctx, auto const& inner, auto const& end_func, auto const& other) -> auto;
+
+#line 391 "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()) {
@@ -427,21 +508,21 @@ template [[nodiscard]] auto any_token_matcher(
// return matched;
// }
-#line 335 "cpp2regex.h2"
+#line 425 "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"
+#line 458 "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"
+#line 471 "cpp2regex.h2"
// TODO: Implement proper to string
// to_string: () -> bstring = {
// r: bstring = "[";
@@ -453,10 +534,10 @@ template c
// return r;
// }
-#line 392 "cpp2regex.h2"
+#line 482 "cpp2regex.h2"
};
-#line 395 "cpp2regex.h2"
+#line 485 "cpp2regex.h2"
// Named short classes
//
template using named_class_no_new_line = class_token_matcher>;
@@ -472,36 +553,43 @@ template usi
template using named_class_not_ver_space = class_token_matcher>;
template using named_class_not_word = class_token_matcher>;
-#line 411 "cpp2regex.h2"
+#line 501 "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;
+template [[nodiscard]] auto group_ref_token_matcher(auto& cur, auto& ctx) -> bool;
-#line 448 "cpp2regex.h2"
+#line 546 "cpp2regex.h2"
// Regex syntax: $ Example: aa$
//
template [[nodiscard]] auto line_end_token_matcher(auto const& cur, auto& ctx) -> bool;
-#line 464 "cpp2regex.h2"
+#line 562 "cpp2regex.h2"
// Regex syntax: ^ Example: ^aa
//
template [[nodiscard]] auto line_start_token_matcher(auto const& cur, auto& ctx) -> bool;
-#line 473 "cpp2regex.h2"
+#line 571 "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"
+#line 585 "cpp2regex.h2"
+// Regex syntax: (?<=) or (? [[nodiscard]] auto lookbehind_token_matcher(auto const& cur, auto& ctx, auto const& func) -> bool;
+
+#line 600 "cpp2regex.h2"
// TODO: @enum as template parameter currently not working. See issue https://github.com/hsutter/cppfront/issues/1147
-#line 491 "cpp2regex.h2"
+#line 603 "cpp2regex.h2"
// Options for range matching.
class range_flags {
public: static const int not_greedy;// Try to take as few as possible.
@@ -512,9 +600,9 @@ class range_flags {
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 609 "cpp2regex.h2"
-#line 499 "cpp2regex.h2"
+#line 611 "cpp2regex.h2"
// Regex syntax: {min, max} Example: a{2,4}
//
template class range_token_matcher
@@ -522,42 +610,42 @@ template class range_tok
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"
+#line 629 "cpp2regex.h2"
private: [[nodiscard]] static auto is_below_upper_bound(cpp2::impl::in count) -> bool;
-#line 522 "cpp2regex.h2"
+#line 634 "cpp2regex.h2"
private: [[nodiscard]] static auto is_below_lower_bound(cpp2::impl::in count) -> bool;
-#line 527 "cpp2regex.h2"
+#line 639 "cpp2regex.h2"
private: [[nodiscard]] static auto is_in_range(cpp2::impl::in count) -> bool;
-#line 533 "cpp2regex.h2"
+#line 645 "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"
+#line 661 "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"
+#line 691 "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"
+#line 719 "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 745 "cpp2regex.h2"
};
-#line 636 "cpp2regex.h2"
+#line 748 "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"
+#line 777 "cpp2regex.h2"
//-----------------------------------------------------------------------
//
// Regular expression implementation.
@@ -566,10 +654,9 @@ template [[nodiscard]] auto word_boundary_token_mat
//
// Regular expression implementation
-template class regular_expression
+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 using context = matcher_context_type;// TODO: Remove when nested types are allowed: https://github.com/hsutter/cppfront/issues/727
public: template class search_return
{
@@ -579,7 +666,10 @@ template class regular_expression
public: search_return(cpp2::impl::in matched_, context const& ctx_, Iter const& pos_);
-#line 690 "cpp2regex.h2"
+#line 801 "cpp2regex.h2"
+ public: search_return(Iter const& begin, Iter const& end);
+
+#line 807 "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);
@@ -589,26 +679,38 @@ template class regular_expression
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: auto update(cpp2::impl::in> r) & -> void;
+
+#line 821 "cpp2regex.h2"
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"
+#line 828 "cpp2regex.h2"
};
+ public: [[nodiscard]] auto find_all(auto&& func, cpp2::impl::in> str) const& -> decltype(auto);
+ public: [[nodiscard]] auto find_all(auto&& func, cpp2::impl::in> str, cpp2::impl::in start) const& -> decltype(auto);
+ public: [[nodiscard]] auto find_all(auto&& func, cpp2::impl::in> str, cpp2::impl::in start, cpp2::impl::in length) const& -> decltype(auto);
+ public: template auto find_all(auto const& func, Iter const& start, Iter const& end) const& -> void;
+
+#line 861 "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"
+#line 872 "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"
+#line 882 "cpp2regex.h2"
+ private: template [[nodiscard]] auto search_with_context(context& ctx, Iter const& start) const& -> match_return;
+
+#line 907 "cpp2regex.h2"
public: [[nodiscard]] auto to_string() const& -> decltype(auto);
// Helper functions
@@ -619,7 +721,7 @@ template class regular_expression
public: auto operator=(regular_expression const&) -> void = delete;
-#line 754 "cpp2regex.h2"
+#line 919 "cpp2regex.h2"
};
}
@@ -631,7 +733,7 @@ template class regular_expression
#line 1 "cpp2regex.h2"
-#line 22 "cpp2regex.h2"
+#line 20 "cpp2regex.h2"
namespace cpp2 {
namespace regex {
@@ -646,55 +748,60 @@ template match_return::match_return(auto const& matched_,
, pos{ pos_ }{}
template match_return::match_return(){}
-#line 63 "cpp2regex.h2"
+#line 61 "cpp2regex.h2"
template match_context::match_context(Iter const& begin_, Iter const& end_)
: begin{ begin_ }
, end{ end_ }{
-#line 66 "cpp2regex.h2"
+#line 64 "cpp2regex.h2"
}
-#line 68 "cpp2regex.h2"
+#line 66 "cpp2regex.h2"
template match_context::match_context(match_context const& that)
: begin{ that.begin }
, end{ that.end }
, groups{ that.groups }{}
-#line 68 "cpp2regex.h2"
+#line 66 "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"
+#line 66 "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"
+#line 66 "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"
+#line 70 "cpp2regex.h2"
+ template [[nodiscard]] auto match_context::get_string_start() const& -> decltype(auto) { return begin; }
+#line 71 "cpp2regex.h2"
+ template [[nodiscard]] auto match_context::get_string_end() const& -> decltype(auto) { return end; }
+
+#line 75 "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"
+#line 77 "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"
+#line 83 "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"
+#line 89 "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 "";
@@ -702,97 +809,199 @@ template match_return::match_return(){}
return std::string(CPP2_ASSERT_IN_BOUNDS(groups, group).start, CPP2_ASSERT_IN_BOUNDS(groups, group).end);
}
-#line 93 "cpp2regex.h2"
+#line 96 "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"
+#line 101 "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"
+#line 105 "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"
+#line 109 "cpp2regex.h2"
template [[nodiscard]] auto match_context::size() const& -> decltype(auto) { return max_groups; }
-#line 110 "cpp2regex.h2"
+#line 113 "cpp2regex.h2"
template [[nodiscard]] auto match_context::fail() const& -> decltype(auto) { return match_return(false, end); }
-#line 111 "cpp2regex.h2"
+#line 114 "cpp2regex.h2"
template [[nodiscard]] auto match_context::pass(cpp2::impl::in cur) const& -> decltype(auto) { return match_return(true, cur); }
-#line 119 "cpp2regex.h2"
+#line 116 "cpp2regex.h2"
+ template auto match_context::reset() & -> void{
+ for ( auto& g : groups ) {
+ g.matched = false;
+ }
+ }
+
+#line 133 "cpp2regex.h2"
+ template reverse_match_context::reverse_match_context(auto const& forward_context_)
+ : forward_context{ forward_context_ }
+ , begin{ std::make_reverse_iterator((*cpp2::impl::assert_not_null(forward_context)).end) }
+ , end{ std::make_reverse_iterator((*cpp2::impl::assert_not_null(forward_context)).begin) }{
+
+#line 137 "cpp2regex.h2"
+ }
+#line 133 "cpp2regex.h2"
+ template auto reverse_match_context::operator=(auto const& forward_context_) -> reverse_match_context& {
+ forward_context = forward_context_;
+ begin = std::make_reverse_iterator((*cpp2::impl::assert_not_null(forward_context)).end);
+ end = std::make_reverse_iterator((*cpp2::impl::assert_not_null(forward_context)).begin);
+ return *this;
+
+#line 137 "cpp2regex.h2"
+ }
+
+#line 139 "cpp2regex.h2"
+ template reverse_match_context::reverse_match_context(reverse_match_context const& that)
+ : forward_context{ that.forward_context }
+ , begin{ that.begin }
+ , end{ that.end }{}
+#line 139 "cpp2regex.h2"
+ template auto reverse_match_context::operator=(reverse_match_context const& that) -> reverse_match_context& {
+ forward_context = that.forward_context;
+ begin = that.begin;
+ end = that.end;
+ return *this; }
+#line 139 "cpp2regex.h2"
+ template reverse_match_context::reverse_match_context(reverse_match_context&& that) noexcept
+ : forward_context{ std::move(that).forward_context }
+ , begin{ std::move(that).begin }
+ , end{ std::move(that).end }{}
+#line 139 "cpp2regex.h2"
+ template auto reverse_match_context::operator=(reverse_match_context&& that) noexcept -> reverse_match_context& {
+ forward_context = std::move(that).forward_context;
+ begin = std::move(that).begin;
+ end = std::move(that).end;
+ return *this; }
+
+#line 143 "cpp2regex.h2"
+ template [[nodiscard]] auto reverse_match_context::get_string_start() const& -> decltype(auto) { return end; }
+#line 144 "cpp2regex.h2"
+ template [[nodiscard]] auto reverse_match_context::get_string_end() const& -> decltype(auto) { return begin; }
+
+#line 148 "cpp2regex.h2"
+ template auto reverse_match_context::set_group_end(auto const& group, auto const& pos) & -> void{
+ (*cpp2::impl::assert_not_null(forward_context)).set_group_end(group, CPP2_UFCS(base)((pos)));
+ }
+
+#line 152 "cpp2regex.h2"
+ template auto reverse_match_context::set_group_invalid(auto const& group) & -> void{
+ (*cpp2::impl::assert_not_null(forward_context)).set_group_invalid(group);
+ }
+
+#line 156 "cpp2regex.h2"
+ template auto reverse_match_context::set_group_start(auto const& group, auto const& pos) & -> void{
+ (*cpp2::impl::assert_not_null(forward_context)).set_group_start(group, CPP2_UFCS(base)((pos)));
+ }
+
+#line 162 "cpp2regex.h2"
+ template [[nodiscard]] auto reverse_match_context::fail() const& -> decltype(auto) { return match_return(false, end); }
+#line 163 "cpp2regex.h2"
+ template [[nodiscard]] auto reverse_match_context::pass(cpp2::impl::in cur) const& -> decltype(auto) { return match_return(true, cur); }
+
+#line 168 "cpp2regex.h2"
+template [[nodiscard]] auto make_forward_match_context(match_context& ctx) -> decltype(auto){
+ return ctx;
+}
+
+#line 172 "cpp2regex.h2"
+template [[nodiscard]] auto make_forward_match_context(reverse_match_context& ctx) -> decltype(auto){
+ return *cpp2::impl::assert_not_null(ctx.forward_context);
+}
+
+#line 176 "cpp2regex.h2"
+template [[nodiscard]] auto make_reverse_match_context(match_context& ctx) -> auto{
+ return reverse_match_context(&ctx);
+}
+
+#line 180 "cpp2regex.h2"
+template [[nodiscard]] auto make_reverse_match_context(reverse_match_context& ctx) -> decltype(auto){
+ return ctx;
+}
+
+#line 186 "cpp2regex.h2"
+template [[nodiscard]] auto make_forward_iterator(Iter const& pos) -> auto { return pos; }
+#line 187 "cpp2regex.h2"
+template [[nodiscard]] auto make_forward_iterator(std::reverse_iterator const& pos) -> auto { return CPP2_UFCS(base)(pos); }
+#line 188 "cpp2regex.h2"
+template [[nodiscard]] auto make_reverse_iterator(Iter const& pos) -> auto { return std::make_reverse_iterator(pos); }
+#line 189 "cpp2regex.h2"
+template [[nodiscard]] auto make_reverse_iterator(std::reverse_iterator const& pos) -> auto { return pos; }
+
+#line 196 "cpp2regex.h2"
[[nodiscard]] auto true_end_func::operator()(auto const& cur, auto& ctx) const& -> decltype(auto) { return ctx.pass(cur); }
-#line 127 "cpp2regex.h2"
+#line 204 "cpp2regex.h2"
auto no_reset::operator()([[maybe_unused]] auto& unnamed_param_2) const& -> void{}
-#line 136 "cpp2regex.h2"
+#line 213 "cpp2regex.h2"
template on_return::on_return(Func const& f)
: func{ f }{
-#line 138 "cpp2regex.h2"
+#line 215 "cpp2regex.h2"
}
-#line 136 "cpp2regex.h2"
+#line 213 "cpp2regex.h2"
template auto on_return::operator=(Func const& f) -> on_return& {
func = f;
return *this;
-#line 138 "cpp2regex.h2"
+#line 215 "cpp2regex.h2"
}
-#line 140 "cpp2regex.h2"
+#line 217 "cpp2regex.h2"
template on_return::~on_return() noexcept{
cpp2::move(*this).func();
}
-#line 147 "cpp2regex.h2"
+#line 224 "cpp2regex.h2"
template [[nodiscard]] auto make_on_return(Func const& func) -> decltype(auto) { return on_return(func); }
-#line 161 "cpp2regex.h2"
+#line 238 "cpp2regex.h2"
template