diff --git a/.gitignore b/.gitignore index 51a3e42d..033032c5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.d test result +test_ordering tests/benchmark-exec/* !tests/benchmark-exec/*.cpp *.pyc @@ -10,4 +11,4 @@ mtent12.txt *.zip tests/benchmark-range/* !tests/benchmark-range/*.cpp -!tests/benchmark-range/*.hpp \ No newline at end of file +!tests/benchmark-range/*.hpp diff --git a/Makefile b/Makefile index 73ab7485..cc5602cd 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ default: all -TARGETS := result.cpp test.cpp $(wildcard tests/benchmark-exec/*.cpp) +TARGETS := result.cpp test_ordering.cpp test.cpp $(wildcard tests/benchmark-exec/*.cpp) DESATOMAT := /www/root/desatomat/console/desatomat.php diff --git a/include/ctre/atoms_characters.hpp b/include/ctre/atoms_characters.hpp index 9c20b92f..a308f0b2 100644 --- a/include/ctre/atoms_characters.hpp +++ b/include/ctre/atoms_characters.hpp @@ -2,6 +2,7 @@ #define CTRE__ATOMS_CHARACTERS__HPP #include "utility.hpp" +#include "ordering.hpp" #include namespace ctre { @@ -21,22 +22,41 @@ template struct character { template CTRE_FORCE_INLINE static constexpr bool match_char(CharT value) noexcept { return value == V; } + + template CTRE_FORCE_INLINE static constexpr equal_less_greater compare_char(CharT value) noexcept { + if (value == V) return {1,1,1}; + if (value < V) return {0,1,0}; + return {0,0,1}; + } }; struct any { template CTRE_FORCE_INLINE static constexpr bool match_char(CharT) noexcept { return true; } + template CTRE_FORCE_INLINE static constexpr equal_less_greater compare_char(CharT value) noexcept { + return {1,0,0}; + } }; template struct negative_set { template inline static constexpr bool match_char(CharT value) noexcept { return !(Content::match_char(value) || ... || false); } + template inline static constexpr equal_less_greater compare_char(CharT value) noexcept { + return {!(Content::match_char(value) || ... || false), 0, 0}; + } }; template struct set { template inline static constexpr bool match_char(CharT value) noexcept { return (Content::match_char(value) || ... || false); } + + template inline static constexpr equal_less_greater compare_char(CharT value) noexcept { + bool equal = (Content::compare_char(value).equal || ... || false); + bool less = (Content::compare_char(value).less && ... && true); + bool greater = (Content::compare_char(value).greater && ... && true); + return {equal, less, greater}; + } }; template struct enumeration : set...> { }; @@ -45,12 +65,24 @@ template struct negate { template inline static constexpr bool match_char(CharT value) noexcept { return !(Content::match_char(value) || ... || false); } + + template inline static constexpr equal_less_greater compare_char(CharT value) noexcept { + return {!(Content::match_char(value) || ... || false), 0, 0}; + } }; template struct char_range { template CTRE_FORCE_INLINE static constexpr bool match_char(CharT value) noexcept { return (value >= A) && (value <= B); } + + template CTRE_FORCE_INLINE static constexpr equal_less_greater compare_char(CharT value) noexcept { + equal_less_greater ret; + if (value >= A && value <= B) ret.equal = true; + if (value <= A) ret.less = true; + if (value >= B) ret.greater = true; + return ret; + } }; struct word_chars : set, char_range<'a','z'>, char_range<'0','9'>, character<'_'> > { }; diff --git a/include/ctre/evaluation.hpp b/include/ctre/evaluation.hpp index 71a0562a..17a7aa9c 100644 --- a/include/ctre/evaluation.hpp +++ b/include/ctre/evaluation.hpp @@ -15,6 +15,12 @@ constexpr inline auto match_re(const Iterator begin, const EndIterator end, Patt return evaluate(begin, begin, end, return_type{}, ctll::list()); } +template +constexpr inline auto ordered_match_re(const Iterator begin, const EndIterator end, Pattern pattern) noexcept { + using return_type = decltype(regex_results(std::declval(), find_captures(pattern))); + return ordered_evaluate(begin, begin, end, return_type{}, ctll::list()); +} + template constexpr inline auto search_re(const Iterator begin, const EndIterator end, Pattern pattern) noexcept { using return_type = decltype(regex_results(std::declval(), find_captures(pattern))); @@ -39,24 +45,44 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator, Iterator, const EndIterat return captures.matched(); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator, Iterator, const EndIterator, R captures, ctll::list) noexcept { + return captures.matched(); +} + // mark start of outer capture template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list) noexcept { return evaluate(begin, current, end, captures.set_start_mark(current), ctll::list()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list) noexcept { + return ordered_evaluate(begin, current, end, captures.set_start_mark(current), ctll::list()); +} + // mark end of outer capture template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list) noexcept { return evaluate(begin, current, end, captures.set_end_mark(current), ctll::list()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list) noexcept { + return ordered_evaluate(begin, current, end, captures.set_end_mark(current), ctll::list()); +} + // mark end of cycle template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator, Iterator current, const EndIterator, R captures, ctll::list) noexcept { return captures.set_end_mark(current).matched(); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator, Iterator current, const EndIterator, R captures, ctll::list) noexcept { + return captures.set_end_mark(current); +} + // matching everything which behave as a one character matcher @@ -67,6 +93,21 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c return evaluate(begin, current+1, end, captures, ctll::list()); } +template ::template value())>)>> +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list) noexcept { + if (end == current) { // target is shorter than pattern + captures.mask_elg({0,1,0}); + return captures; + } + captures.mask_elg(CharacterLike::compare_char(*current)); + if (captures) { + if(!captures.is_less() && !captures.is_greater()) + return evaluate(begin, current+1, end, captures.unmatch(), ctll::list()); + return ordered_evaluate(begin, current+1, end, captures, ctll::list()); + } + return captures; +} + // matching strings in patterns template struct string_match_result { @@ -74,6 +115,11 @@ template struct string_match_result { bool match; }; +template struct string_compare_result { + Iterator current; + equal_less_greater elg; +}; + template constexpr CTRE_FORCE_INLINE string_match_result evaluate_match_string(Iterator current, const EndIterator end) noexcept { if ((end != current) && (Head == *current)) { if constexpr (sizeof...(String) > 0) { @@ -86,6 +132,19 @@ template co } } +template constexpr CTRE_FORCE_INLINE string_compare_result evaluate_compare_string(Iterator current, const EndIterator end) noexcept { + if (end == current) { // target is shorter than pattern (string) + return {current, {0, 1, 0}}; + } + if (Head < *current) return {++current, {0, 0, 1}}; + if (Head > *current) return {++current, {0, 1, 0}}; + if constexpr (sizeof...(String) > 0) { + return evaluate_compare_string(++current, end); + } else { + return {++current, {1, 1, 1}}; + } +} + template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { if constexpr (sizeof...(String) == 0) { @@ -97,6 +156,18 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c } } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + if constexpr (sizeof...(String) == 0) { + return ordered_evaluate(begin, current, end, captures, ctll::list()); + } else if (auto tmp = evaluate_compare_string(current, end); tmp.elg.equal) { + return ordered_evaluate(begin, tmp.current, end, captures, ctll::list()); + } else { + captures.mask_elg(tmp.elg); + return captures; + } +} + // matching select in patterns template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { @@ -113,6 +184,21 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator, Iterator, const EndIterat return not_matched; } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + auto r = ordered_evaluate(begin, current, end, captures, ctll::list()); + if (r) { return r; } + captures.mask_lg(r); + return ordered_evaluate(begin, current, end, captures, ctll::list, Tail...>()); +} + +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator, Iterator, const EndIterator, R captures, ctll::list, Tail...>) noexcept { + // no previous option was matched => REJECT + captures.mask_elg({0,1,1}); + return captures; +} + // matching optional in patterns template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { @@ -125,6 +211,17 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c } } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + auto r1 = ordered_evaluate(begin, current, end, captures, ctll::list, Tail...>()); + if (r1) { return r1; } + auto r2 = ordered_evaluate(begin, current, end, captures, ctll::list()); + if (r2) { return r2; } + captures.mask_elg(r1); + captures.mask_elg(r2); + return captures; +} + // lazy optional template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { @@ -137,6 +234,17 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c } } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + auto r1 = ordered_evaluate(begin, current, end, captures, ctll::list()); + if (r1) { return r1; } + auto r2 = ordered_evaluate(begin, current, end, captures, ctll::list, Tail...>()); + if (r2) { return r2; } + captures.mask_elg(r1); + captures.mask_elg(r2); + return captures; +} + // matching sequence in patterns template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { @@ -145,6 +253,15 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c } else { return evaluate(begin, current, end, captures, ctll::list()); } +} + +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + if constexpr (sizeof...(TailContent) > 0) { + return ordered_evaluate(begin, current, end, captures, ctll::list, Tail...>()); + } else { + return ordered_evaluate(begin, current, end, captures, ctll::list()); + } } @@ -154,6 +271,11 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c return evaluate(begin, current, end, captures, ctll::list()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list) noexcept { + return ordered_evaluate(begin, current, end, captures, ctll::list()); +} + // matching asserts template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list) noexcept { @@ -163,6 +285,15 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c return evaluate(begin, current, end, captures, ctll::list()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list) noexcept { + if (begin != current) { + captures.mask_elg({0,1,1}); + return captures; + } + return ordered_evaluate(begin, current, end, captures, ctll::list()); +} + template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list) noexcept { if (end != current) { @@ -171,6 +302,15 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c return evaluate(begin, current, end, captures, ctll::list()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list) noexcept { + if (end != current) { // target is longer than pattern + captures.mask_elg({0,0,1}); + return captures; + } + return ordered_evaluate(begin, current, end, captures, ctll::list()); +} + // lazy repeat template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { @@ -205,6 +345,39 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c } } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + // A..B + size_t i{0}; + for (; i < A && (A != 0); ++i) { + if (captures = ordered_evaluate(begin, current, end, captures, ctll::list, end_cycle_mark>())) { + current = captures.get_end_position(); + } else { + return captures; + } + } + + if (auto outer_result = ordered_evaluate(begin, current, end, captures, ctll::list())) { + return outer_result; + } else { + captures.mask_lg(outer_result); + for (; (i < B) || (B == 0); ++i) { + if (auto inner_result = ordered_evaluate(begin, current, end, captures, ctll::list, end_cycle_mark>())) { + if (captures = ordered_evaluate(begin, inner_result.get_end_position(), end, inner_result.unmatch(), ctll::list())) { + return captures; + } else { + captures = inner_result; + current = inner_result.get_end_position(); + continue; + } + } else { + return inner_result; + } + } + return ordered_evaluate(begin, current, end, captures, ctll::list()); + } +} + // possessive repeat template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { @@ -231,6 +404,38 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c return evaluate(begin, current, end, captures, ctll::list()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + // A..B + size_t i{0}; + for (; i < A && (A != 0); ++i) { + if (captures = ordered_evaluate(begin, current, end, captures, ctll::list, end_cycle_mark>())) { + current = captures.get_end_position(); + } else { + return captures; + } + } + + for (; (i < B) || (B == 0); ++i) { + // try as many of inner as possible and then try outer once + + // I have to mask this ordering beforehand, as we can't backtrack later. + // This basically throws away the usual runtime benefits of a possessive repeat. + auto outer_result = ordered_evaluate(begin, current, end, captures, ctll::list()); + captures.mask_lg(outer_result); + + auto inner_result = ordered_evaluate(begin, current, end, captures, ctll::list, end_cycle_mark>()); + captures.mask_lg(inner_result); + if (inner_result) { + current = inner_result.get_end_position(); + } else { + return outer_result; + } + } + + return ordered_evaluate(begin, current, end, captures, ctll::list()); +} + // (gready) repeat template constexpr inline R evaluate_recursive(size_t i, const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...> stack) { @@ -268,24 +473,73 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c return evaluate_recursive(i, begin, current, end, captures, stack); } +template +constexpr inline R ordered_evaluate_recursive(size_t i, const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...> stack) { + if ((i < B) || (B == 0)) { + auto inner_result = ordered_evaluate(begin, current, end, captures, ctll::list, end_cycle_mark>()); + if (inner_result) { + // TODO MSVC issue: + // if I uncomment this return it will not fail in constexpr (but the matching result will not be correct) + // return inner_result + // I tried to add all constructors to R but without any success + auto rec_result = ordered_evaluate_recursive(i+1, begin, inner_result.get_end_position(), end, inner_result, stack); + if (rec_result) { return rec_result; } + captures.mask_lg(rec_result); + } + captures.mask_lg(inner_result); + } + return ordered_evaluate(begin, current, end, captures, ctll::list()); +} + +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...> stack) { + // A..B + size_t i{0}; + for (; i < A && (A != 0); ++i) { + captures = ordered_evaluate(begin, current, end, captures, ctll::list, end_cycle_mark>()); + if (captures) { + current = captures.get_end_position(); + } else { + return captures; + } + } + + return ordered_evaluate_recursive(i, begin, current, end, captures, stack); +} + // repeat lazy_star template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { return evaluate(begin, current, end, captures, ctll::list, Tail...>()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + return ordered_evaluate(begin, current, end, captures, ctll::list, Tail...>()); +} + // repeat (lazy_plus) template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { return evaluate(begin, current, end, captures, ctll::list, Tail...>()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + return ordered_evaluate(begin, current, end, captures, ctll::list, Tail...>()); +} + // repeat (possessive_star) template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { return evaluate(begin, current, end, captures, ctll::list, Tail...>()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + return ordered_evaluate(begin, current, end, captures, ctll::list, Tail...>()); +} + // repeat (possessive_plus) template @@ -293,12 +547,22 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c return evaluate(begin, current, end, captures, ctll::list, Tail...>()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + return ordered_evaluate(begin, current, end, captures, ctll::list, Tail...>()); +} + // repeat (greedy) star template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { return evaluate(begin, current, end, captures, ctll::list, Tail...>()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + return ordered_evaluate(begin, current, end, captures, ctll::list, Tail...>()); +} + // repeat (greedy) plus template @@ -306,24 +570,44 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c return evaluate(begin, current, end, captures, ctll::list, Tail...>()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + return ordered_evaluate(begin, current, end, captures, ctll::list, Tail...>()); +} + // capture (numeric ID) template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { return evaluate(begin, current, end, captures.template start_capture(current), ctll::list, numeric_mark, Tail...>()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + return ordered_evaluate(begin, current, end, captures.template start_capture(current), ctll::list, numeric_mark, Tail...>()); +} + // capture end mark (numeric and string ID) template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { return evaluate(begin, current, end, captures.template end_capture(current), ctll::list()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + return ordered_evaluate(begin, current, end, captures.template end_capture(current), ctll::list()); +} + // capture (string ID) template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { return evaluate(begin, current, end, captures.template start_capture(current), ctll::list, numeric_mark, Tail...>()); } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + return ordered_evaluate(begin, current, end, captures.template start_capture(current), ctll::list, numeric_mark, Tail...>()); +} + // backreference support (match agains content of iterators) template constexpr CTRE_FORCE_INLINE string_match_result match_against_range(Iterator current, const EndIterator end, Iterator range_current, const Iterator range_end) noexcept { while (current != end && range_current != range_end) { @@ -337,6 +621,18 @@ template constexpr CTRE_FORCE_INLINE s return {current, range_current == range_end}; } +template constexpr CTRE_FORCE_INLINE string_compare_result compare_against_range(Iterator current, const EndIterator end, Iterator range_current, const Iterator range_end) noexcept { + while (current != end && range_current != range_end) { + if (*current == *range_current) { + current++; + range_current++; + } else { + return {current, {0, *current < *range_current, *current > *range_current}}; + } + } + return {current, {range_current == range_end, 1, range_current == range_end}}; +} + // backreference with name template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { @@ -349,6 +645,20 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c return not_matched; } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + + if (const auto ref = captures.template get()) { + auto tmp = compare_against_range(current, end, ref.begin(), ref.end()); + captures.mask_elg(tmp.elg); + if (tmp.elg.equal) { + return ordered_evaluate(begin, tmp.current, end, captures, ctll::list()); + } + } + captures.mask_elg({0,1,1}); + return captures; +} + // backreference template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { @@ -361,6 +671,20 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c return not_matched; } +template +constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list, Tail...>) noexcept { + + if (const auto ref = captures.template get()) { + auto tmp = compare_against_range(current, end, ref.begin(), ref.end()); + captures.mask_elg(tmp.elg); + if (tmp.elg.equal) { + return ordered_evaluate(begin, tmp.current, end, captures, ctll::list()); + } + } + captures.mask_elg({0,1,1}); + return captures; +} + } diff --git a/include/ctre/ordering.hpp b/include/ctre/ordering.hpp new file mode 100644 index 00000000..ddca2e5b --- /dev/null +++ b/include/ctre/ordering.hpp @@ -0,0 +1,19 @@ +#ifndef CTRE__ORDERING__HPP +#define CTRE__ORDERING__HPP + +namespace ctre { + +enum class partial_ordering { less, greater, equal, unordered }; + +struct equal_less_greater { + bool equal : 1; + bool less : 1; + bool greater : 1; + + constexpr equal_less_greater() noexcept : equal(0), less(0), greater(0) { } + constexpr equal_less_greater(bool e, bool l, bool g) noexcept : equal(e), less(l), greater(g) { } +}; + +} // namespace ctre + +#endif // CTRE__ORDERING__HPP diff --git a/include/ctre/return_type.hpp b/include/ctre/return_type.hpp index fd1c9b5a..7c54bcc6 100644 --- a/include/ctre/return_type.hpp +++ b/include/ctre/return_type.hpp @@ -2,6 +2,7 @@ #define CTRE__RETURN_TYPE__HPP #include "id.hpp" +#include "ordering.hpp" #include #include #include @@ -19,18 +20,31 @@ template struct captured_content { using char_type = typename std::iterator_traits::value_type; - bool _matched{false}; + equal_less_greater _elg; using name = Name; - constexpr CTRE_FORCE_INLINE storage() noexcept {} + constexpr CTRE_FORCE_INLINE storage() noexcept : _elg{1, 1, 1} {} + constexpr CTRE_FORCE_INLINE storage(not_matched_tag_t) noexcept : _elg{0, 0, 0} {} constexpr CTRE_FORCE_INLINE void matched() noexcept { - _matched = true; + // TODO review how matched() and unmatched() are used and revisit those algorithms. + _elg = {1, 0, 0}; } constexpr CTRE_FORCE_INLINE void unmatch() noexcept { - _matched = false; + _elg = {0, 0, 0}; } + + constexpr CTRE_FORCE_INLINE void mask_elg(equal_less_greater elg) { + _elg.equal &= elg.equal; + _elg.less &= elg.less; + _elg.greater &= elg.greater; + } + constexpr CTRE_FORCE_INLINE void mask_lg(equal_less_greater elg) { + _elg.less &= elg.less; + _elg.greater &= elg.greater; + } + constexpr CTRE_FORCE_INLINE void set_start(Iterator pos) noexcept { _begin = pos; } @@ -51,7 +65,26 @@ template struct captured_content { } constexpr CTRE_FORCE_INLINE operator bool() const noexcept { - return _matched; + return _elg.equal; + } + + constexpr CTRE_FORCE_INLINE bool is_less() const noexcept { + return _elg.less; + } + + constexpr CTRE_FORCE_INLINE bool is_greater() const noexcept { + return _elg.greater; + } + + constexpr CTRE_FORCE_INLINE operator equal_less_greater() const noexcept { + return _elg; + } + + constexpr CTRE_FORCE_INLINE operator partial_ordering() const noexcept { + if (_elg.equal) return partial_ordering::equal; + if (_elg.less) return partial_ordering::less; + if (_elg.greater) return partial_ordering::greater; + return partial_ordering::unordered; } constexpr CTRE_FORCE_INLINE auto to_view() const noexcept { @@ -77,6 +110,7 @@ template struct captures; template struct captures: captures { Head head{}; constexpr CTRE_FORCE_INLINE captures() noexcept { } + constexpr CTRE_FORCE_INLINE captures(not_matched_tag_t tag) noexcept : head(tag) { } template CTRE_FORCE_INLINE static constexpr bool exists() noexcept { if constexpr (id == Head::get_id()) { return true; @@ -143,7 +177,7 @@ template struct regex_results { captures::template storage, typename Captures::template storage...> _captures{}; constexpr CTRE_FORCE_INLINE regex_results() noexcept { } - constexpr CTRE_FORCE_INLINE regex_results(not_matched_tag_t) noexcept { } + constexpr CTRE_FORCE_INLINE regex_results(not_matched_tag_t tag) noexcept : _captures(tag) { } // special constructor for deducting constexpr CTRE_FORCE_INLINE regex_results(Iterator, ctll::list) noexcept { } @@ -165,9 +199,29 @@ template struct regex_results { _captures.template select<0>().unmatch(); return *this; } + constexpr CTRE_FORCE_INLINE regex_results & mask_elg(equal_less_greater elg) noexcept { + _captures.template select<0>().mask_elg(elg); + return *this; + } + constexpr CTRE_FORCE_INLINE regex_results & mask_lg(equal_less_greater elg) noexcept { + _captures.template select<0>().mask_lg(elg); + return *this; + } constexpr CTRE_FORCE_INLINE operator bool() const noexcept { return bool(_captures.template select<0>()); } + constexpr CTRE_FORCE_INLINE bool is_less() const noexcept { + return _captures.template select<0>().is_less(); + } + constexpr CTRE_FORCE_INLINE bool is_greater() const noexcept { + return _captures.template select<0>().is_greater(); + } + constexpr CTRE_FORCE_INLINE operator equal_less_greater() const noexcept { + return equal_less_greater(_captures.template select<0>()); + } + constexpr CTRE_FORCE_INLINE operator partial_ordering() const noexcept { + return partial_ordering(_captures.template select<0>()); + } constexpr operator std::basic_string_view() const noexcept { return to_view(); @@ -215,4 +269,4 @@ namespace std { }; } -#endif \ No newline at end of file +#endif diff --git a/include/ctre/utility.hpp b/include/ctre/utility.hpp index 8983b12d..71511d9c 100644 --- a/include/ctre/utility.hpp +++ b/include/ctre/utility.hpp @@ -9,4 +9,4 @@ #define CTRE_FLATTEN __attribute__((flatten)) #endif -#endif \ No newline at end of file +#endif diff --git a/include/ctre/wrapper.hpp b/include/ctre/wrapper.hpp index 55543145..547b3af5 100644 --- a/include/ctre/wrapper.hpp +++ b/include/ctre/wrapper.hpp @@ -22,12 +22,23 @@ struct zero_terminated_string_end_iterator { constexpr CTRE_FORCE_INLINE bool operator!=(const wchar_t * ptr) const noexcept { return *ptr != 0; } + template + friend constexpr CTRE_FORCE_INLINE bool operator==(T t, zero_terminated_string_end_iterator it) { + return it == t; + } + template + friend constexpr CTRE_FORCE_INLINE bool operator!=(T t, zero_terminated_string_end_iterator it) { + return it != t; + } }; template struct regular_expression { template constexpr CTRE_FORCE_INLINE static auto match_2(IteratorBegin begin, IteratorEnd end) noexcept { return match_re(begin, end, RE()); } + template constexpr CTRE_FORCE_INLINE static auto ordered_match_2(IteratorBegin begin, IteratorEnd end) noexcept { + return ordered_match_re(begin, end, RE()); + } template constexpr CTRE_FORCE_INLINE static auto search_2(IteratorBegin begin, IteratorEnd end) noexcept { return search_re(begin, end, RE()); } @@ -60,6 +71,33 @@ template struct regular_expression { static constexpr CTRE_FORCE_INLINE auto match(std::u32string_view sv) noexcept { return match(sv.begin(), sv.end()); } + template constexpr CTRE_FORCE_INLINE static auto ordered_match(Iterator begin, Iterator end) noexcept { + return ordered_match_re(begin, end, RE()); + } + static constexpr CTRE_FORCE_INLINE auto ordered_match(const char * s) noexcept { + return ordered_match_2(s, zero_terminated_string_end_iterator()); + } + static constexpr CTRE_FORCE_INLINE auto ordered_match(const wchar_t * s) noexcept { + return ordered_match_2(s, zero_terminated_string_end_iterator()); + } + static constexpr CTRE_FORCE_INLINE auto ordered_match(const std::string & s) noexcept { + return ordered_match_2(s.c_str(), zero_terminated_string_end_iterator()); + } + static constexpr CTRE_FORCE_INLINE auto ordered_match(const std::wstring & s) noexcept { + return ordered_match_2(s.c_str(), zero_terminated_string_end_iterator()); + } + static constexpr CTRE_FORCE_INLINE auto ordered_match(std::string_view sv) noexcept { + return ordered_match(sv.begin(), sv.end()); + } + static constexpr CTRE_FORCE_INLINE auto ordered_match(std::wstring_view sv) noexcept { + return ordered_match(sv.begin(), sv.end()); + } + static constexpr CTRE_FORCE_INLINE auto ordered_match(std::u16string_view sv) noexcept { + return ordered_match(sv.begin(), sv.end()); + } + static constexpr CTRE_FORCE_INLINE auto ordered_match(std::u32string_view sv) noexcept { + return ordered_match(sv.begin(), sv.end()); + } template constexpr CTRE_FORCE_INLINE static auto search(Iterator begin, Iterator end) noexcept { return search_re(begin, end, RE()); } @@ -94,4 +132,4 @@ template regular_expression(RE) -> regular_expression; } -#endif \ No newline at end of file +#endif diff --git a/test_ordering.cpp b/test_ordering.cpp new file mode 100644 index 00000000..91aaa6e6 --- /dev/null +++ b/test_ordering.cpp @@ -0,0 +1,28 @@ +#include + +#include + +std::ostream& operator<<(std::ostream& os, ctre::partial_ordering ord) { + switch (ord) { + case ctre::partial_ordering::less : + return os << "less"; + case ctre::partial_ordering::greater : + return os << "greater"; + case ctre::partial_ordering::equal : + return os << "equal"; + case ctre::partial_ordering::unordered : + return os << "unordered"; + default : + return os << "BUMM!"; + } +} + +int main(int argc, char ** argv) { + using namespace ctre::literals; + constexpr auto re = "x*+^[a-y]+"_ctre; + + std::cout << ctre::partial_ordering(re.match(argv[1])) << std::endl; + std::cout << ctre::partial_ordering(re.ordered_match(argv[1])) << std::endl; + + return 0; +}