@@ -135,13 +135,106 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
135
135
return evaluate (begin, result.position , last, consumed_something (f, sizeof ...(String) > 0 ), captures, ctll::list<Tail...>());
136
136
}
137
137
138
+ template <typename T, typename ... Ts> constexpr auto collides_with (T, ctll::list<Ts...>) noexcept {
139
+ return decltype ((ctll::list<>{} + ... + ctll::item_matcher<Ts>::pick (
140
+ typename std::conditional<collides (calculate_first (sequence<T>{}), calculate_first (sequence<Ts>{})), std::true_type, std::false_type>::type{}
141
+ ))){};
142
+ }
143
+ template <typename T, typename ... Ts> constexpr auto collides_with_negated (T, ctll::list<Ts...>) noexcept {
144
+ return decltype ((ctll::list<>{} + ... + ctll::item_matcher<Ts>::pick (
145
+ typename std::conditional<collides (ctre::negative_set<decltype (calculate_first (sequence<T>{}))>{}, calculate_first (sequence<Ts>{})), std::true_type, std::false_type>::type{}
146
+ ))){};
147
+ }
148
+
149
+ template <typename T, typename ... Ts> constexpr auto mutually_exclusive_with (T, ctll::list<Ts...>) noexcept {
150
+ return decltype ((ctll::list<>{} + ... + ctll::item_matcher<Ts>::pick (
151
+ typename std::conditional<!collides (calculate_first (sequence<T>{}), calculate_first (sequence<Ts>{})), std::true_type, std::false_type>::type{}
152
+ ))){};
153
+ }
154
+
155
+ namespace detail {
156
+ template <typename ... Content>
157
+ constexpr auto transform_into_set (ctll::list<Content...>) {
158
+ return ctre::set<decltype (Content{})...>{};
159
+ // return ctre::set<decltype(transform_into_set(Content{}))... > {};
160
+ }
161
+
162
+ template <typename T>
163
+ constexpr auto transform_into_set (T) {
164
+ return T{};
165
+ }
166
+
167
+ template <>
168
+ constexpr auto transform_into_set (can_be_anything) {
169
+ return ctre::char_range<std::numeric_limits<int64_t >::min (), std::numeric_limits<int64_t >::max ()>{};
170
+ }
171
+
172
+ template <typename ... Content>
173
+ constexpr auto transform_into_select (ctll::list<Content...>) {
174
+ return ctre::select <decltype (Content{})...>{};
175
+ }
176
+ }
177
+
138
178
// matching select in patterns
139
179
template <typename R, typename Iterator, typename EndIterator, typename HeadOptions, typename ... TailOptions, typename ... Tail>
140
180
constexpr CTRE_FORCE_INLINE R evaluate (const Iterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<select<HeadOptions, TailOptions...>, Tail...>) noexcept {
141
- if (auto r = evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>())) {
142
- return r;
181
+ constexpr auto collision_list = collides_with (sequence<HeadOptions, Tail...>, ctll::list<
182
+ sequence<TailOptions, Tail...>, ...
183
+ >{});
184
+ if constexpr (ctll::empty (collision_list)) {
185
+ // we're mutually exclusive from everything else
186
+ using set_type = decltype (detail::transform_into_set (calculate_first (sequence<HeadOptions, Tail...>{})));
187
+ if constexpr (::std::is_same_v<set<>, set_type>) {
188
+ // fail handle as normal
189
+ if (auto r = evaluate (begin, current, end, f, captures, ctll::list<HeadOptions, Tail...>())) {
190
+ return r;
191
+ } else {
192
+ return evaluate (begin, current, end, f, captures, ctll::list<select <TailOptions...>, Tail...>());
193
+ }
194
+ } else {
195
+ // ok optimize into exclusive select
196
+ if (auto r = evaluate (begin, current, end, f, captures, ctll::list<set_type, end_cycle_mark>{})) {
197
+ return evaluate (begin, current, end, f, captures, ctll::list<HeadOptions, Tail...>{});
198
+ } else {
199
+ return evaluate (begin, current, end, f, captures, ctll::list<select <TailOptions...>, Tail...>());
200
+ }
201
+ }
202
+
203
+ return evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>());
204
+ } else if constexpr (ctll::size (collision_list) == sizeof ...(TailOptions)) {
205
+ // continue as normal...we collided with everything
206
+ if (auto r = evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>())) {
207
+ return r;
208
+ } else {
209
+ return evaluate (begin, current, last, f, captures, ctll::list<select <TailOptions...>, Tail...>());
210
+ }
143
211
} else {
144
- return evaluate (begin, current, last, f, captures, ctll::list<select <TailOptions...>, Tail...>());
212
+ // we collided with some things, but not others, bifricate on the first character we see
213
+ // may be less computationally expensive to do a set subtraction from the complete list with the collision list, because we're evaluating collisions again
214
+ constexpr auto negated_collision_list = collides_with_negated (sequence<HeadOptions, Tail...>, ctll::list<
215
+ sequence<TailOptions, Tail...>, ...
216
+ >{});
217
+
218
+ using set_type = decltype (detail::transform_into_set (calculate_first (sequence<HeadOptions, Tail...>{})));
219
+ if constexpr (::std::is_same_v<set<>, set_type>) {
220
+ // fail fallback to normal
221
+ if (auto r = evaluate (begin, current, end, f, captures, ctll::list<HeadOptions, Tail...>())) {
222
+ return r;
223
+ } else {
224
+ return evaluate (begin, current, end, f, captures, ctll::list<select <TailOptions...>, Tail...>());
225
+ }
226
+ } else {
227
+ // ok optimize into a split
228
+ if (auto r = evaluate (begin, current, end, f, captures, ctll::list<set_type, end_cycle_mark>{})) {
229
+ if (auto r2 = evaluate (begin, current, end, f, captures, ctll::list<HeadOptions, Tail...>{})) {
230
+ return r2;
231
+ } else {
232
+ return evaluate (begin, current, end, f, captures, detail::transform_into_select (collision_list));
233
+ }
234
+ } else {
235
+ return evaluate (begin, current, end, f, captures, detail::transform_into_select (negated_collision_list));
236
+ }
237
+ }
145
238
}
146
239
}
147
240
@@ -151,6 +244,22 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator, Iterator, const EndIterat
151
244
return not_matched;
152
245
}
153
246
247
+ // non exclusive select (assume collisions)
248
+ template <typename R, typename Iterator, typename EndIterator, typename HeadOptions, typename ... TailOptions, typename ... Tail>
249
+ constexpr CTRE_FORCE_INLINE R evaluate (const Iterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<non_exclusive_select<HeadOptions, TailOptions...>, Tail...>) noexcept {
250
+ if (auto r = evaluate (begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>())) {
251
+ return r;
252
+ } else {
253
+ return evaluate (begin, current, last, f, captures, ctll::list<non_exclusive_select<TailOptions...>, Tail...>());
254
+ }
255
+ }
256
+
257
+ template <typename R, typename Iterator, typename EndIterator, typename ... Tail>
258
+ constexpr CTRE_FORCE_INLINE R evaluate (const Iterator, Iterator, const EndIterator, flags, R, ctll::list<non_exclusive_select<>, Tail...>) noexcept {
259
+ // no previous option was matched => REJECT
260
+ return not_matched;
261
+ }
262
+
154
263
// matching sequence in patterns
155
264
template <typename R, typename Iterator, typename EndIterator, typename HeadContent, typename ... TailContent, typename ... Tail>
156
265
constexpr CTRE_FORCE_INLINE R evaluate (const Iterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<sequence<HeadContent, TailContent...>, Tail...>) noexcept {
0 commit comments