Skip to content

Commit ce3be22

Browse files
committed
Add ordered_match()
1 parent e2bba72 commit ce3be22

8 files changed

+216
-7
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
default: all
44

5-
TARGETS := result.cpp test.cpp $(wildcard tests/benchmark-exec/*.cpp)
5+
TARGETS := result.cpp test_ordering.cpp test.cpp $(wildcard tests/benchmark-exec/*.cpp)
66

77
DESATOMAT := /www/root/desatomat/console/desatomat.php
88

include/ctre/atoms_characters.hpp

+32
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define CTRE__ATOMS_CHARACTERS__HPP
33

44
#include "utility.hpp"
5+
#include "ordering.hpp"
56
#include <cstdint>
67

78
namespace ctre {
@@ -21,22 +22,41 @@ template <auto V> struct character {
2122
template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char(CharT value) noexcept {
2223
return value == V;
2324
}
25+
26+
template <typename CharT> CTRE_FORCE_INLINE static constexpr equal_less_greater compare_char(CharT value) noexcept {
27+
if (value == V) return {1,1,1};
28+
if (value < V) return {0,1,0};
29+
return {0,0,1};
30+
}
2431
};
2532

2633
struct any {
2734
template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char(CharT) noexcept { return true; }
35+
template <typename CharT> CTRE_FORCE_INLINE static constexpr equal_less_greater compare_char(CharT value) noexcept {
36+
return {1,0,0};
37+
}
2838
};
2939

3040
template <typename... Content> struct negative_set {
3141
template <typename CharT> inline static constexpr bool match_char(CharT value) noexcept {
3242
return !(Content::match_char(value) || ... || false);
3343
}
44+
template <typename CharT> inline static constexpr equal_less_greater compare_char(CharT value) noexcept {
45+
return {!(Content::match_char(value) || ... || false), 0, 0};
46+
}
3447
};
3548

3649
template <typename... Content> struct set {
3750
template <typename CharT> inline static constexpr bool match_char(CharT value) noexcept {
3851
return (Content::match_char(value) || ... || false);
3952
}
53+
54+
template <typename CharT> inline static constexpr equal_less_greater compare_char(CharT value) noexcept {
55+
bool equal = (Content::compare_char(value).equal || ... || false);
56+
bool less = (Content::compare_char(value).less && ... && true);
57+
bool greater = (Content::compare_char(value).greater && ... && true);
58+
return {equal, less, greater};
59+
}
4060
};
4161

4262
template <auto... Cs> struct enumeration : set<character<Cs>...> { };
@@ -45,12 +65,24 @@ template <typename... Content> struct negate {
4565
template <typename CharT> inline static constexpr bool match_char(CharT value) noexcept {
4666
return !(Content::match_char(value) || ... || false);
4767
}
68+
69+
template <typename CharT> inline static constexpr equal_less_greater compare_char(CharT value) noexcept {
70+
return {!(Content::match_char(value) || ... || false), 0, 0};
71+
}
4872
};
4973

5074
template <auto A, auto B> struct char_range {
5175
template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char(CharT value) noexcept {
5276
return (value >= A) && (value <= B);
5377
}
78+
79+
template <typename CharT> CTRE_FORCE_INLINE static constexpr equal_less_greater compare_char(CharT value) noexcept {
80+
equal_less_greater ret;
81+
if (value >= A && value <= B) ret.equal = true;
82+
if (value <= A) ret.less = true;
83+
if (value >= B) ret.greater = true;
84+
return ret;
85+
}
5486
};
5587

5688
struct word_chars : set<char_range<'A','Z'>, char_range<'a','z'>, char_range<'0','9'>, character<'_'> > { };

include/ctre/evaluation.hpp

+59
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ constexpr inline auto match_re(const Iterator begin, const EndIterator end, Patt
1515
return evaluate(begin, begin, end, return_type{}, ctll::list<start_mark, Pattern, assert_end, end_mark, accept>());
1616
}
1717

18+
template <typename Iterator, typename EndIterator, typename Pattern>
19+
constexpr inline auto ordered_match_re(const Iterator begin, const EndIterator end, Pattern pattern) noexcept {
20+
using return_type = decltype(regex_results(std::declval<Iterator>(), find_captures(pattern)));
21+
return ordered_evaluate(begin, begin, end, return_type{}, ctll::list<start_mark, Pattern, assert_end, end_mark, accept>());
22+
}
23+
1824
template <typename Iterator, typename EndIterator, typename Pattern>
1925
constexpr inline auto search_re(const Iterator begin, const EndIterator end, Pattern pattern) noexcept {
2026
using return_type = decltype(regex_results(std::declval<Iterator>(), find_captures(pattern)));
@@ -39,18 +45,33 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator, Iterator, const EndIterat
3945
return captures.matched();
4046
}
4147

48+
template <typename R, typename Iterator, typename EndIterator>
49+
constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator, Iterator, const EndIterator, R captures, ctll::list<accept>) noexcept {
50+
return captures.matched();
51+
}
52+
4253
// mark start of outer capture
4354
template <typename R, typename Iterator, typename EndIterator, typename... Tail>
4455
constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list<start_mark, Tail...>) noexcept {
4556
return evaluate(begin, current, end, captures.set_start_mark(current), ctll::list<Tail...>());
4657
}
4758

59+
template <typename R, typename Iterator, typename EndIterator, typename... Tail>
60+
constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list<start_mark, Tail...>) noexcept {
61+
return ordered_evaluate(begin, current, end, captures.set_start_mark(current), ctll::list<Tail...>());
62+
}
63+
4864
// mark end of outer capture
4965
template <typename R, typename Iterator, typename EndIterator, typename... Tail>
5066
constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list<end_mark, Tail...>) noexcept {
5167
return evaluate(begin, current, end, captures.set_end_mark(current), ctll::list<Tail...>());
5268
}
5369

70+
template <typename R, typename Iterator, typename EndIterator, typename... Tail>
71+
constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list<end_mark, Tail...>) noexcept {
72+
return ordered_evaluate(begin, current, end, captures.set_end_mark(current), ctll::list<Tail...>());
73+
}
74+
5475
// mark end of cycle
5576
template <typename R, typename Iterator, typename EndIterator, typename... Tail>
5677
constexpr CTRE_FORCE_INLINE R evaluate(const Iterator, Iterator current, const EndIterator, R captures, ctll::list<end_cycle_mark>) noexcept {
@@ -67,13 +88,33 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
6788
return evaluate(begin, current+1, end, captures, ctll::list<Tail...>());
6889
}
6990

91+
template <typename R, typename Iterator, typename EndIterator, typename CharacterLike, typename... Tail, typename = std::enable_if_t<(MatchesCharacter<CharacterLike>::template value<decltype(*std::declval<Iterator>())>)>>
92+
constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list<CharacterLike, Tail...>) noexcept {
93+
if (end == current) { // target is shorter than pattern
94+
captures.mask_elg({0,1,0});
95+
return captures;
96+
}
97+
captures.mask_elg(CharacterLike::compare_char(*current));
98+
if (captures) {
99+
if(!captures.is_less() && !captures.is_greater())
100+
return evaluate(begin, current+1, end, captures.unmatch(), ctll::list<Tail...>());
101+
return ordered_evaluate(begin, current+1, end, captures, ctll::list<Tail...>());
102+
}
103+
return captures;
104+
}
105+
70106
// matching strings in patterns
71107

72108
template <typename Iterator> struct string_match_result {
73109
Iterator current;
74110
bool match;
75111
};
76112

113+
template <typename Iterator> struct string_compare_result {
114+
Iterator current;
115+
equal_less_greater elg;
116+
};
117+
77118
template <auto Head, auto... String, typename Iterator, typename EndIterator> constexpr CTRE_FORCE_INLINE string_match_result<Iterator> evaluate_match_string(Iterator current, const EndIterator end) noexcept {
78119
if ((end != current) && (Head == *current)) {
79120
if constexpr (sizeof...(String) > 0) {
@@ -145,6 +186,15 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
145186
} else {
146187
return evaluate(begin, current, end, captures, ctll::list<HeadContent, Tail...>());
147188
}
189+
}
190+
191+
template <typename R, typename Iterator, typename EndIterator, typename HeadContent, typename... TailContent, typename... Tail>
192+
constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list<sequence<HeadContent, TailContent...>, Tail...>) noexcept {
193+
if constexpr (sizeof...(TailContent) > 0) {
194+
return ordered_evaluate(begin, current, end, captures, ctll::list<HeadContent, sequence<TailContent...>, Tail...>());
195+
} else {
196+
return ordered_evaluate(begin, current, end, captures, ctll::list<HeadContent, Tail...>());
197+
}
148198

149199
}
150200

@@ -171,6 +221,15 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
171221
return evaluate(begin, current, end, captures, ctll::list<Tail...>());
172222
}
173223

224+
template <typename R, typename Iterator, typename EndIterator, typename... Tail>
225+
constexpr CTRE_FORCE_INLINE R ordered_evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list<assert_end, Tail...>) noexcept {
226+
if (end != current) { // target is longer than pattern
227+
captures.mask_elg({0,0,1});
228+
return captures;
229+
}
230+
return ordered_evaluate(begin, current, end, captures, ctll::list<Tail...>());
231+
}
232+
174233
// lazy repeat
175234
template <typename R, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail>
176235
constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, R captures, ctll::list<lazy_repeat<A,B,Content...>, Tail...>) noexcept {

include/ctre/ordering.hpp

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef CTRE__ORDERING__HPP
2+
#define CTRE__ORDERING__HPP
3+
4+
namespace ctre {
5+
6+
enum class partial_ordering { less, greater, equal, unordered };
7+
8+
struct equal_less_greater {
9+
bool equal : 1 = false;
10+
bool less : 1 = false;
11+
bool greater : 1 = false;
12+
};
13+
14+
} // namespace ctre
15+
16+
#endif // CTRE__ORDERING__HPP

include/ctre/return_type.hpp

+49-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define CTRE__RETURN_TYPE__HPP
33

44
#include "id.hpp"
5+
#include "ordering.hpp"
56
#include <type_traits>
67
#include <tuple>
78
#include <string_view>
@@ -19,18 +20,33 @@ template <size_t Id, typename Name = void> struct captured_content {
1920

2021
using char_type = typename std::iterator_traits<Iterator>::value_type;
2122

22-
bool _matched{false};
23+
bool _matched : 1;
24+
bool _less : 1;
25+
bool _greater : 1;
2326

2427
using name = Name;
2528

26-
constexpr CTRE_FORCE_INLINE storage() noexcept {}
29+
constexpr CTRE_FORCE_INLINE storage() noexcept : _matched(true), _less(true), _greater(true) {}
30+
constexpr CTRE_FORCE_INLINE storage(not_matched_tag_t) noexcept : _matched(false), _less(false), _greater(false) {}
2731

2832
constexpr CTRE_FORCE_INLINE void matched() noexcept {
33+
// TODO review how matched() and unmatched() are used and revisit those algorithms.
2934
_matched = true;
35+
_less = false;
36+
_greater = false;
3037
}
3138
constexpr CTRE_FORCE_INLINE void unmatch() noexcept {
3239
_matched = false;
40+
_less = false;
41+
_greater = false;
3342
}
43+
44+
constexpr CTRE_FORCE_INLINE void mask_elg(equal_less_greater elg) {
45+
_matched &= elg.equal;
46+
_less &= elg.less;
47+
_greater &= elg.greater;
48+
}
49+
3450
constexpr CTRE_FORCE_INLINE void set_start(Iterator pos) noexcept {
3551
_begin = pos;
3652
}
@@ -53,6 +69,21 @@ template <size_t Id, typename Name = void> struct captured_content {
5369
constexpr CTRE_FORCE_INLINE operator bool() const noexcept {
5470
return _matched;
5571
}
72+
73+
constexpr CTRE_FORCE_INLINE bool is_less() const noexcept {
74+
return _less;
75+
}
76+
77+
constexpr CTRE_FORCE_INLINE bool is_greater() const noexcept {
78+
return _greater;
79+
}
80+
81+
constexpr CTRE_FORCE_INLINE operator partial_ordering() const noexcept {
82+
if (_matched) return partial_ordering::equal;
83+
if (_less) return partial_ordering::less;
84+
if (_greater) return partial_ordering::greater;
85+
return partial_ordering::unordered;
86+
}
5687

5788
constexpr CTRE_FORCE_INLINE auto to_view() const noexcept {
5889
return std::basic_string_view<char_type>(&*_begin, static_cast<size_t>(std::distance(_begin, _end)));
@@ -77,6 +108,7 @@ template <typename... Captures> struct captures;
77108
template <typename Head, typename... Tail> struct captures<Head, Tail...>: captures<Tail...> {
78109
Head head{};
79110
constexpr CTRE_FORCE_INLINE captures() noexcept { }
111+
constexpr CTRE_FORCE_INLINE captures(not_matched_tag_t tag) noexcept : head(tag) { }
80112
template <size_t id> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
81113
if constexpr (id == Head::get_id()) {
82114
return true;
@@ -143,7 +175,7 @@ template <typename Iterator, typename... Captures> struct regex_results {
143175
captures<captured_content<0>::template storage<Iterator>, typename Captures::template storage<Iterator>...> _captures{};
144176

145177
constexpr CTRE_FORCE_INLINE regex_results() noexcept { }
146-
constexpr CTRE_FORCE_INLINE regex_results(not_matched_tag_t) noexcept { }
178+
constexpr CTRE_FORCE_INLINE regex_results(not_matched_tag_t tag) noexcept : _captures(tag) { }
147179

148180
// special constructor for deducting
149181
constexpr CTRE_FORCE_INLINE regex_results(Iterator, ctll::list<Captures...>) noexcept { }
@@ -165,9 +197,22 @@ template <typename Iterator, typename... Captures> struct regex_results {
165197
_captures.template select<0>().unmatch();
166198
return *this;
167199
}
200+
constexpr CTRE_FORCE_INLINE regex_results & mask_elg(equal_less_greater elg) noexcept {
201+
_captures.template select<0>().mask_elg(elg);
202+
return *this;
203+
}
168204
constexpr CTRE_FORCE_INLINE operator bool() const noexcept {
169205
return bool(_captures.template select<0>());
170206
}
207+
constexpr CTRE_FORCE_INLINE bool is_less() const noexcept {
208+
return _captures.template select<0>().is_less();
209+
}
210+
constexpr CTRE_FORCE_INLINE bool is_greater() const noexcept {
211+
return _captures.template select<0>().is_greater();
212+
}
213+
constexpr CTRE_FORCE_INLINE operator partial_ordering() const noexcept {
214+
return partial_ordering(_captures.template select<0>());
215+
}
171216

172217
constexpr operator std::basic_string_view<char_type>() const noexcept {
173218
return to_view();
@@ -215,4 +260,4 @@ namespace std {
215260
};
216261
}
217262

218-
#endif
263+
#endif

include/ctre/utility.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99
#define CTRE_FLATTEN __attribute__((flatten))
1010
#endif
1111

12-
#endif
12+
#endif

include/ctre/wrapper.hpp

+31-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ template <typename RE> struct regular_expression {
2828
template <typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto match_2(IteratorBegin begin, IteratorEnd end) noexcept {
2929
return match_re(begin, end, RE());
3030
}
31+
template <typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto ordered_match_2(IteratorBegin begin, IteratorEnd end) noexcept {
32+
return ordered_match_re(begin, end, RE());
33+
}
3134
template <typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto search_2(IteratorBegin begin, IteratorEnd end) noexcept {
3235
return search_re(begin, end, RE());
3336
}
@@ -60,6 +63,33 @@ template <typename RE> struct regular_expression {
6063
static constexpr CTRE_FORCE_INLINE auto match(std::u32string_view sv) noexcept {
6164
return match(sv.begin(), sv.end());
6265
}
66+
template <typename Iterator> constexpr CTRE_FORCE_INLINE static auto ordered_match(Iterator begin, Iterator end) noexcept {
67+
return ordered_match_re(begin, end, RE());
68+
}
69+
static constexpr CTRE_FORCE_INLINE auto ordered_match(const char * s) noexcept {
70+
return ordered_match_2(s, zero_terminated_string_end_iterator());
71+
}
72+
static constexpr CTRE_FORCE_INLINE auto ordered_match(const wchar_t * s) noexcept {
73+
return ordered_match_2(s, zero_terminated_string_end_iterator());
74+
}
75+
static constexpr CTRE_FORCE_INLINE auto ordered_match(const std::string & s) noexcept {
76+
return ordered_match_2(s.c_str(), zero_terminated_string_end_iterator());
77+
}
78+
static constexpr CTRE_FORCE_INLINE auto ordered_match(const std::wstring & s) noexcept {
79+
return ordered_match_2(s.c_str(), zero_terminated_string_end_iterator());
80+
}
81+
static constexpr CTRE_FORCE_INLINE auto ordered_match(std::string_view sv) noexcept {
82+
return ordered_match(sv.begin(), sv.end());
83+
}
84+
static constexpr CTRE_FORCE_INLINE auto ordered_match(std::wstring_view sv) noexcept {
85+
return ordered_match(sv.begin(), sv.end());
86+
}
87+
static constexpr CTRE_FORCE_INLINE auto ordered_match(std::u16string_view sv) noexcept {
88+
return ordered_match(sv.begin(), sv.end());
89+
}
90+
static constexpr CTRE_FORCE_INLINE auto ordered_match(std::u32string_view sv) noexcept {
91+
return ordered_match(sv.begin(), sv.end());
92+
}
6393
template <typename Iterator> constexpr CTRE_FORCE_INLINE static auto search(Iterator begin, Iterator end) noexcept {
6494
return search_re(begin, end, RE());
6595
}
@@ -94,4 +124,4 @@ template <typename RE> regular_expression(RE) -> regular_expression<RE>;
94124

95125
}
96126

97-
#endif
127+
#endif

0 commit comments

Comments
 (0)