Line data Source code
1 : /*
2 : Apache License
3 : Version 2.0, January 2004
4 : http://www.apache.org/licenses/
5 :
6 : TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 :
8 : 1. Definitions.
9 :
10 : "License" shall mean the terms and conditions for use, reproduction,
11 : and distribution as defined by Sections 1 through 9 of this document.
12 :
13 : "Licensor" shall mean the copyright owner or entity authorized by
14 : the copyright owner that is granting the License.
15 :
16 : "Legal Entity" shall mean the union of the acting entity and all
17 : other entities that control, are controlled by, or are under common
18 : control with that entity. For the purposes of this definition,
19 : "control" means (i) the power, direct or indirect, to cause the
20 : direction or management of such entity, whether by contract or
21 : otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 : outstanding shares, or (iii) beneficial ownership of such entity.
23 :
24 : "You" (or "Your") shall mean an individual or Legal Entity
25 : exercising permissions granted by this License.
26 :
27 : "Source" form shall mean the preferred form for making modifications,
28 : including but not limited to software source code, documentation
29 : source, and configuration files.
30 :
31 : "Object" form shall mean any form resulting from mechanical
32 : transformation or translation of a Source form, including but
33 : not limited to compiled object code, generated documentation,
34 : and conversions to other media types.
35 :
36 : "Work" shall mean the work of authorship, whether in Source or
37 : Object form, made available under the License, as indicated by a
38 : copyright notice that is included in or attached to the work
39 : (an example is provided in the Appendix below).
40 :
41 : "Derivative Works" shall mean any work, whether in Source or Object
42 : form, that is based on (or derived from) the Work and for which the
43 : editorial revisions, annotations, elaborations, or other modifications
44 : represent, as a whole, an original work of authorship. For the purposes
45 : of this License, Derivative Works shall not include works that remain
46 : separable from, or merely link (or bind by name) to the interfaces of,
47 : the Work and Derivative Works thereof.
48 :
49 : "Contribution" shall mean any work of authorship, including
50 : the original version of the Work and any modifications or additions
51 : to that Work or Derivative Works thereof, that is intentionally
52 : submitted to Licensor for inclusion in the Work by the copyright owner
53 : or by an individual or Legal Entity authorized to submit on behalf of
54 : the copyright owner. For the purposes of this definition, "submitted"
55 : means any form of electronic, verbal, or written communication sent
56 : to the Licensor or its representatives, including but not limited to
57 : communication on electronic mailing lists, source code control systems,
58 : and issue tracking systems that are managed by, or on behalf of, the
59 : Licensor for the purpose of discussing and improving the Work, but
60 : excluding communication that is conspicuously marked or otherwise
61 : designated in writing by the copyright owner as "Not a Contribution."
62 :
63 : "Contributor" shall mean Licensor and any individual or Legal Entity
64 : on behalf of whom a Contribution has been received by Licensor and
65 : subsequently incorporated within the Work.
66 :
67 : 2. Grant of Copyright License. Subject to the terms and conditions of
68 : this License, each Contributor hereby grants to You a perpetual,
69 : worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 : copyright license to reproduce, prepare Derivative Works of,
71 : publicly display, publicly perform, sublicense, and distribute the
72 : Work and such Derivative Works in Source or Object form.
73 :
74 : 3. Grant of Patent License. Subject to the terms and conditions of
75 : this License, each Contributor hereby grants to You a perpetual,
76 : worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 : (except as stated in this section) patent license to make, have made,
78 : use, offer to sell, sell, import, and otherwise transfer the Work,
79 : where such license applies only to those patent claims licensable
80 : by such Contributor that are necessarily infringed by their
81 : Contribution(s) alone or by combination of their Contribution(s)
82 : with the Work to which such Contribution(s) was submitted. If You
83 : institute patent litigation against any entity (including a
84 : cross-claim or counterclaim in a lawsuit) alleging that the Work
85 : or a Contribution incorporated within the Work constitutes direct
86 : or contributory patent infringement, then any patent licenses
87 : granted to You under this License for that Work shall terminate
88 : as of the date such litigation is filed.
89 :
90 : 4. Redistribution. You may reproduce and distribute copies of the
91 : Work or Derivative Works thereof in any medium, with or without
92 : modifications, and in Source or Object form, provided that You
93 : meet the following conditions:
94 :
95 : (a) You must give any other recipients of the Work or
96 : Derivative Works a copy of this License; and
97 :
98 : (b) You must cause any modified files to carry prominent notices
99 : stating that You changed the files; and
100 :
101 : (c) You must retain, in the Source form of any Derivative Works
102 : that You distribute, all copyright, patent, trademark, and
103 : attribution notices from the Source form of the Work,
104 : excluding those notices that do not pertain to any part of
105 : the Derivative Works; and
106 :
107 : (d) If the Work includes a "NOTICE" text file as part of its
108 : distribution, then any Derivative Works that You distribute must
109 : include a readable copy of the attribution notices contained
110 : within such NOTICE file, excluding those notices that do not
111 : pertain to any part of the Derivative Works, in at least one
112 : of the following places: within a NOTICE text file distributed
113 : as part of the Derivative Works; within the Source form or
114 : documentation, if provided along with the Derivative Works; or,
115 : within a display generated by the Derivative Works, if and
116 : wherever such third-party notices normally appear. The contents
117 : of the NOTICE file are for informational purposes only and
118 : do not modify the License. You may add Your own attribution
119 : notices within Derivative Works that You distribute, alongside
120 : or as an addendum to the NOTICE text from the Work, provided
121 : that such additional attribution notices cannot be construed
122 : as modifying the License.
123 :
124 : You may add Your own copyright statement to Your modifications and
125 : may provide additional or different license terms and conditions
126 : for use, reproduction, or distribution of Your modifications, or
127 : for any such Derivative Works as a whole, provided Your use,
128 : reproduction, and distribution of the Work otherwise complies with
129 : the conditions stated in this License.
130 :
131 : 5. Submission of Contributions. Unless You explicitly state otherwise,
132 : any Contribution intentionally submitted for inclusion in the Work
133 : by You to the Licensor shall be under the terms and conditions of
134 : this License, without any additional terms or conditions.
135 : Notwithstanding the above, nothing herein shall supersede or modify
136 : the terms of any separate license agreement you may have executed
137 : with Licensor regarding such Contributions.
138 :
139 : 6. Trademarks. This License does not grant permission to use the trade
140 : names, trademarks, service marks, or product names of the Licensor,
141 : except as required for reasonable and customary use in describing the
142 : origin of the Work and reproducing the content of the NOTICE file.
143 :
144 : 7. Disclaimer of Warranty. Unless required by applicable law or
145 : agreed to in writing, Licensor provides the Work (and each
146 : Contributor provides its Contributions) on an "AS IS" BASIS,
147 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 : implied, including, without limitation, any warranties or conditions
149 : of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 : PARTICULAR PURPOSE. You are solely responsible for determining the
151 : appropriateness of using or redistributing the Work and assume any
152 : risks associated with Your exercise of permissions under this License.
153 :
154 : 8. Limitation of Liability. In no event and under no legal theory,
155 : whether in tort (including negligence), contract, or otherwise,
156 : unless required by applicable law (such as deliberate and grossly
157 : negligent acts) or agreed to in writing, shall any Contributor be
158 : liable to You for damages, including any direct, indirect, special,
159 : incidental, or consequential damages of any character arising as a
160 : result of this License or out of the use or inability to use the
161 : Work (including but not limited to damages for loss of goodwill,
162 : work stoppage, computer failure or malfunction, or any and all
163 : other commercial damages or losses), even if such Contributor
164 : has been advised of the possibility of such damages.
165 :
166 : 9. Accepting Warranty or Additional Liability. While redistributing
167 : the Work or Derivative Works thereof, You may choose to offer,
168 : and charge a fee for, acceptance of support, warranty, indemnity,
169 : or other liability obligations and/or rights consistent with this
170 : License. However, in accepting such obligations, You may act only
171 : on Your own behalf and on Your sole responsibility, not on behalf
172 : of any other Contributor, and only if You agree to indemnify,
173 : defend, and hold each Contributor harmless for any liability
174 : incurred by, or claims asserted against, such Contributor by reason
175 : of your accepting any such warranty or additional liability.
176 :
177 : END OF TERMS AND CONDITIONS
178 :
179 : APPENDIX: How to apply the Apache License to your work.
180 :
181 : To apply the Apache License to your work, attach the following
182 : boilerplate notice, with the fields enclosed by brackets "[]"
183 : replaced with your own identifying information. (Don't include
184 : the brackets!) The text should be enclosed in the appropriate
185 : comment syntax for the file format. We also recommend that a
186 : file or class name and description of purpose be included on the
187 : same "printed page" as the copyright notice for easier
188 : identification within third-party archives.
189 :
190 : Copyright [yyyy] [name of copyright owner]
191 :
192 : Licensed under the Apache License, Version 2.0 (the "License");
193 : you may not use this file except in compliance with the License.
194 : You may obtain a copy of the License at
195 :
196 : http://www.apache.org/licenses/LICENSE-2.0
197 :
198 : Unless required by applicable law or agreed to in writing, software
199 : distributed under the License is distributed on an "AS IS" BASIS,
200 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 : See the License for the specific language governing permissions and
202 : limitations under the License.
203 :
204 :
205 : --- LLVM Exceptions to the Apache 2.0 License ----
206 :
207 : As an exception, if, as a result of your compiling your source code, portions
208 : of this Software are embedded into an Object form of such source code, you
209 : may redistribute such embedded portions in such Object form without complying
210 : with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
211 :
212 : In addition, if you combine or link compiled forms of this Software with
213 : software that is licensed under the GPLv2 ("Combined Software") and if a
214 : court of competent jurisdiction determines that the patent provision (Section
215 : 3), the indemnity provision (Section 9) or other Section of the License
216 : conflicts with the conditions of the GPLv2, you may retroactively and
217 : prospectively choose to deem waived or otherwise exclude such Section(s) of
218 : the License, but only in their entirety and only with respect to the Combined
219 : Software.
220 : */
221 : #ifndef CTRE_V2__CTRE__HPP
222 : #define CTRE_V2__CTRE__HPP
223 :
224 : #ifndef CTRE_V2__CTRE__LITERALS__HPP
225 : #define CTRE_V2__CTRE__LITERALS__HPP
226 :
227 : #ifndef CTRE_V2__CTLL__HPP
228 : #define CTRE_V2__CTLL__HPP
229 :
230 : #ifndef CTLL__PARSER__HPP
231 : #define CTLL__PARSER__HPP
232 :
233 : #ifndef CTLL__FIXED_STRING__GPP
234 : #define CTLL__FIXED_STRING__GPP
235 :
236 : #ifndef CTLL_IN_A_MODULE
237 : #include <utility>
238 : #include <cstddef>
239 : #include <string_view>
240 : #include <array>
241 : #include <cstdint>
242 : #endif
243 :
244 : #ifndef CTLL__UTILITIES__HPP
245 : #define CTLL__UTILITIES__HPP
246 :
247 : #ifndef CTLL_IN_A_MODULE
248 : #include <type_traits>
249 : #endif
250 :
251 : #ifdef CTLL_IN_A_MODULE
252 : #define CTLL_EXPORT export
253 : #else
254 : #define CTLL_EXPORT
255 : #endif
256 :
257 : #if defined __cpp_nontype_template_parameter_class
258 : #define CTLL_CNTTP_COMPILER_CHECK 1
259 : #elif defined __cpp_nontype_template_args
260 : // compiler which defines correctly feature test macro (not you clang)
261 : #if __cpp_nontype_template_args >= 201911L
262 : #define CTLL_CNTTP_COMPILER_CHECK 1
263 : #elif __cpp_nontype_template_args >= 201411L
264 : // appleclang 13+
265 : #if defined __apple_build_version__
266 : #if defined __clang_major__ && __clang_major__ >= 13
267 : // but only in c++20 and more
268 : #if __cplusplus > 201703L
269 : #define CTLL_CNTTP_COMPILER_CHECK 1
270 : #endif
271 : #endif
272 : #else
273 : // clang 12+
274 : #if defined __clang_major__ && __clang_major__ >= 12
275 : // but only in c++20 and more
276 : #if __cplusplus > 201703L
277 : #define CTLL_CNTTP_COMPILER_CHECK 1
278 : #endif
279 : #endif
280 : #endif
281 : #endif
282 : #endif
283 :
284 : #ifndef CTLL_CNTTP_COMPILER_CHECK
285 : #define CTLL_CNTTP_COMPILER_CHECK 0
286 : #endif
287 :
288 : #ifdef _MSC_VER
289 : #define CTLL_FORCE_INLINE __forceinline
290 : #else
291 : #define CTLL_FORCE_INLINE __attribute__((always_inline))
292 : #endif
293 :
294 : namespace ctll {
295 :
296 : template <bool> struct conditional_helper;
297 :
298 : template <> struct conditional_helper<true> {
299 : template <typename A, typename> using type = A;
300 : };
301 :
302 : template <> struct conditional_helper<false> {
303 : template <typename, typename B> using type = B;
304 : };
305 :
306 : template <bool V, typename A, typename B> using conditional = typename conditional_helper<V>::template type<A,B>;
307 :
308 : }
309 :
310 : #endif
311 :
312 : namespace ctll {
313 :
314 : struct length_value_t {
315 : uint32_t value;
316 : uint8_t length;
317 : };
318 :
319 : constexpr length_value_t length_and_value_of_utf8_code_point(uint8_t first_unit) noexcept {
320 : if ((first_unit & 0b1000'0000) == 0b0000'0000) return {static_cast<uint32_t>(first_unit), 1};
321 : else if ((first_unit & 0b1110'0000) == 0b1100'0000) return {static_cast<uint32_t>(first_unit & 0b0001'1111), 2};
322 : else if ((first_unit & 0b1111'0000) == 0b1110'0000) return {static_cast<uint32_t>(first_unit & 0b0000'1111), 3};
323 : else if ((first_unit & 0b1111'1000) == 0b1111'0000) return {static_cast<uint32_t>(first_unit & 0b0000'0111), 4};
324 : else if ((first_unit & 0b1111'1100) == 0b1111'1000) return {static_cast<uint32_t>(first_unit & 0b0000'0011), 5};
325 : else if ((first_unit & 0b1111'1100) == 0b1111'1100) return {static_cast<uint32_t>(first_unit & 0b0000'0001), 6};
326 : else return {0, 0};
327 : }
328 :
329 : constexpr char32_t value_of_trailing_utf8_code_point(uint8_t unit, bool & correct) noexcept {
330 : if ((unit & 0b1100'0000) == 0b1000'0000) return unit & 0b0011'1111;
331 : else {
332 : correct = false;
333 : return 0;
334 : }
335 : }
336 :
337 : constexpr length_value_t length_and_value_of_utf16_code_point(uint16_t first_unit) noexcept {
338 : if ((first_unit & 0b1111110000000000) == 0b1101'1000'0000'0000) return {static_cast<uint32_t>(first_unit & 0b0000001111111111), 2};
339 : else return {first_unit, 1};
340 : }
341 :
342 : struct construct_from_pointer_t { };
343 :
344 : constexpr auto construct_from_pointer = construct_from_pointer_t{};
345 :
346 : CTLL_EXPORT template <size_t N> struct fixed_string {
347 : char32_t content[N] = {};
348 : size_t real_size{0};
349 : bool correct_flag{true};
350 :
351 : template <typename T> constexpr fixed_string(construct_from_pointer_t, const T * input) noexcept {
352 : if constexpr (std::is_same_v<T, char>) {
353 : #ifdef CTRE_STRING_IS_UTF8
354 : size_t out{0};
355 : for (size_t i{0}; i < N; ++i) {
356 : length_value_t info = length_and_value_of_utf8_code_point(input[i]);
357 : switch (info.length) {
358 : case 6:
359 : if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
360 : [[fallthrough]];
361 : case 5:
362 : if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
363 : [[fallthrough]];
364 : case 4:
365 : if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
366 : [[fallthrough]];
367 : case 3:
368 : if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
369 : [[fallthrough]];
370 : case 2:
371 : if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
372 : [[fallthrough]];
373 : case 1:
374 : content[out++] = static_cast<char32_t>(info.value);
375 : real_size++;
376 : break;
377 : default:
378 : correct_flag = false;
379 : return;
380 : }
381 : }
382 : #else
383 : for (size_t i{0}; i < N; ++i) {
384 : content[i] = static_cast<uint8_t>(input[i]);
385 : real_size++;
386 : }
387 : #endif
388 : #if defined(__cpp_char8_t)
389 : } else if constexpr (std::is_same_v<T, char8_t>) {
390 : size_t out{0};
391 : for (size_t i{0}; i < N; ++i) {
392 : length_value_t info = length_and_value_of_utf8_code_point(input[i]);
393 : switch (info.length) {
394 : case 6:
395 : if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
396 : [[fallthrough]];
397 : case 5:
398 : if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
399 : [[fallthrough]];
400 : case 4:
401 : if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
402 : [[fallthrough]];
403 : case 3:
404 : if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
405 : [[fallthrough]];
406 : case 2:
407 : if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
408 : [[fallthrough]];
409 : case 1:
410 : content[out++] = static_cast<char32_t>(info.value);
411 : real_size++;
412 : break;
413 : default:
414 : correct_flag = false;
415 : return;
416 : }
417 : }
418 : #endif
419 : } else if constexpr (std::is_same_v<T, char16_t>) {
420 : size_t out{0};
421 : for (size_t i{0}; i < N; ++i) {
422 : length_value_t info = length_and_value_of_utf16_code_point(input[i]);
423 : if (info.length == 2) {
424 : if (++i < N) {
425 : if ((input[i] & 0b1111'1100'0000'0000) == 0b1101'1100'0000'0000) {
426 : content[out++] = ((info.value << 10) | (input[i] & 0b0000'0011'1111'1111)) + 0x10000;
427 : } else {
428 : correct_flag = false;
429 : break;
430 : }
431 : }
432 : } else {
433 : content[out++] = info.value;
434 : }
435 : }
436 : real_size = out;
437 : } else if constexpr (std::is_same_v<T, wchar_t> || std::is_same_v<T, char32_t>) {
438 : for (size_t i{0}; i < N; ++i) {
439 : content[i] = static_cast<char32_t>(input[i]);
440 : real_size++;
441 : }
442 : }
443 : }
444 :
445 : template <typename T> constexpr fixed_string(const std::array<T, N> & in) noexcept: fixed_string{construct_from_pointer, in.data()} { }
446 : template <typename T> constexpr fixed_string(const T (&input)[N+1]) noexcept: fixed_string{construct_from_pointer, input} { }
447 :
448 : constexpr fixed_string(const fixed_string & other) noexcept {
449 : for (size_t i{0}; i < N; ++i) {
450 : content[i] = other.content[i];
451 : }
452 : real_size = other.real_size;
453 : correct_flag = other.correct_flag;
454 : }
455 : constexpr bool correct() const noexcept {
456 : return correct_flag;
457 : }
458 : constexpr size_t size() const noexcept {
459 : return real_size;
460 : }
461 : constexpr const char32_t * begin() const noexcept {
462 : return content;
463 : }
464 : constexpr const char32_t * end() const noexcept {
465 : return content + size();
466 : }
467 : constexpr char32_t operator[](size_t i) const noexcept {
468 : return content[i];
469 : }
470 : template <size_t M> constexpr bool is_same_as(const fixed_string<M> & rhs) const noexcept {
471 : if (real_size != rhs.size()) return false;
472 : for (size_t i{0}; i != real_size; ++i) {
473 : if (content[i] != rhs[i]) return false;
474 : }
475 : return true;
476 : }
477 : constexpr operator std::basic_string_view<char32_t>() const noexcept {
478 : return std::basic_string_view<char32_t>{content, size()};
479 : }
480 : };
481 :
482 : template <> class fixed_string<0> {
483 : static constexpr char32_t empty[1] = {0};
484 : public:
485 : template <typename T> constexpr fixed_string(const T *) noexcept {
486 :
487 : }
488 : constexpr fixed_string(std::initializer_list<char32_t>) noexcept {
489 :
490 : }
491 : constexpr fixed_string(const fixed_string &) noexcept {
492 :
493 : }
494 : constexpr bool correct() const noexcept {
495 : return true;
496 : }
497 : constexpr size_t size() const noexcept {
498 : return 0;
499 : }
500 : constexpr const char32_t * begin() const noexcept {
501 : return empty;
502 : }
503 : constexpr const char32_t * end() const noexcept {
504 : return empty + size();
505 : }
506 : constexpr char32_t operator[](size_t) const noexcept {
507 : return 0;
508 : }
509 : constexpr operator std::basic_string_view<char32_t>() const noexcept {
510 : return std::basic_string_view<char32_t>{empty, 0};
511 : }
512 : };
513 :
514 : template <typename CharT, size_t N> fixed_string(const CharT (&)[N]) -> fixed_string<N-1>;
515 : template <typename CharT, size_t N> fixed_string(const std::array<CharT,N> &) -> fixed_string<N>;
516 :
517 : template <size_t N> fixed_string(fixed_string<N>) -> fixed_string<N>;
518 :
519 : }
520 :
521 : #endif
522 :
523 : #ifndef CTLL__TYPE_STACK__HPP
524 : #define CTLL__TYPE_STACK__HPP
525 :
526 : namespace ctll {
527 :
528 : template <typename... Ts> struct list { };
529 :
530 : struct _nothing { };
531 :
532 : using empty_list = list<>;
533 :
534 : // calculate size of list content
535 : template <typename... Ts> constexpr auto size(list<Ts...>) noexcept { return sizeof...(Ts); }
536 :
537 :
538 : // check if the list is empty
539 : template <typename... Ts> constexpr bool empty(list<Ts...>) noexcept { return false; }
540 : constexpr bool empty(empty_list) { return true; }
541 :
542 : // concat two lists together left to right
543 : template <typename... As, typename... Bs> constexpr auto concat(list<As...>, list<Bs...>) noexcept -> list<As..., Bs...> { return {}; }
544 :
545 : // push something to the front of a list
546 : template <typename T, typename... As> constexpr auto push_front(T, list<As...>) noexcept -> list<T, As...> { return {}; }
547 :
548 : // pop element from the front of a list
549 : template <typename T, typename... As> constexpr auto pop_front(list<T, As...>) noexcept -> list<As...> { return {}; }
550 : constexpr auto pop_front(empty_list) -> empty_list;
551 :
552 : // pop element from the front of a list and return new typelist too
553 : template <typename Front, typename List> struct list_pop_pair {
554 : Front front{};
555 : List list{};
556 : constexpr list_pop_pair() = default;
557 : };
558 :
559 : template <typename Head, typename... As, typename T = _nothing> constexpr auto pop_and_get_front(list<Head, As...>, T = T()) noexcept -> list_pop_pair<Head, list<As...>> { return {}; }
560 : template <typename T = _nothing> constexpr auto pop_and_get_front(empty_list, T = T()) noexcept -> list_pop_pair<T, empty_list> { return {}; }
561 :
562 : // return front of the list
563 : template <typename Head, typename... As, typename T = _nothing> constexpr auto front(list<Head, As...>, T = T()) noexcept -> Head { return {}; }
564 : template <typename T = _nothing> constexpr auto front(empty_list, T = T()) noexcept -> T { return {}; }
565 :
566 : // rotate list
567 : template <typename T> struct rotate_item {
568 : template <typename... Ts> friend constexpr auto operator+(list<Ts...>, rotate_item<T>) noexcept -> list<T, Ts...> { return {}; }
569 : };
570 :
571 : template <typename... Ts> constexpr auto rotate(list<Ts...>) -> decltype((list<>{} + ... + rotate_item<Ts>{})) {
572 : return {};
573 : }
574 :
575 : // set operations
576 : template <typename T> struct item_matcher {
577 : struct not_selected {
578 : template <typename... Ts> friend constexpr auto operator+(list<Ts...>, not_selected) -> list<Ts...>;
579 : };
580 : template <typename Y> struct wrapper {
581 : template <typename... Ts> friend constexpr auto operator+(list<Ts...>, wrapper<Y>) -> list<Ts...,Y>;
582 : };
583 :
584 : static constexpr auto check(T) { return std::true_type{}; }
585 : static constexpr auto check(...) { return std::false_type{}; }
586 : static constexpr auto select(T) { return not_selected{}; }
587 : template <typename Y> static constexpr auto select(Y) { return wrapper<Y>{}; }
588 : };
589 :
590 : template <typename T, typename... Ts> constexpr bool exists_in(T, list<Ts...>) noexcept {
591 : return (item_matcher<T>::check(Ts{}) || ... || false);
592 : }
593 :
594 : template <typename T, typename... Ts> constexpr auto add_item(T item, list<Ts...> l) noexcept {
595 : if constexpr (exists_in(item, l)) {
596 : return l;
597 : } else {
598 : return list<Ts..., T>{};
599 : }
600 : }
601 :
602 : template <typename T, typename... Ts> constexpr auto remove_item(T, list<Ts...>) noexcept {
603 : item_matcher<T> matcher;
604 : return decltype((list<>{} + ... + matcher.select(Ts{}))){};
605 : }
606 :
607 : }
608 :
609 : #endif
610 :
611 : #ifndef CTLL__GRAMMARS__HPP
612 : #define CTLL__GRAMMARS__HPP
613 :
614 : namespace ctll {
615 :
616 : // terminal type representing symbol / character of any type
617 : template <auto v> struct term {
618 : static constexpr auto value = v;
619 : };
620 :
621 : // epsilon = nothing on input tape
622 : // also used as an command for parsing means "do nothing"
623 : struct epsilon {
624 : static constexpr auto value = '-';
625 : };
626 :
627 : // empty_stack_symbol = nothing on stack
628 : struct empty_stack_symbol {};
629 :
630 : // push<T...> is alias to list<T...>
631 : template <typename... Ts> using push = list<Ts...>;
632 :
633 : // accept/reject type for controlling output of LL1 machine
634 : struct accept { constexpr explicit operator bool() noexcept { return true; } };
635 : struct reject { constexpr explicit operator bool() noexcept { return false; } };
636 :
637 : // action type, every action item in grammar must inherit from
638 : struct action {
639 : struct action_tag { };
640 : };
641 :
642 : // move one character forward and pop it from stack command
643 : struct pop_input {
644 : struct pop_input_tag { };
645 : };
646 :
647 : // additional overloads for type list
648 : template <typename... Ts> constexpr auto push_front(pop_input, list<Ts...>) -> list<Ts...> { return {}; }
649 :
650 : template <typename... Ts> constexpr auto push_front(epsilon, list<Ts...>) -> list<Ts...> { return {}; }
651 :
652 : template <typename... As, typename... Bs> constexpr auto push_front(list<As...>, list<Bs...>) -> list<As..., Bs...> { return {}; }
653 :
654 : template <typename T, typename... As> constexpr auto pop_front_and_push_front(T item, list<As...> l) {
655 : return push_front(item, pop_front(l));
656 : }
657 :
658 : // SPECIAL matching types for nicer grammars
659 :
660 : // match any term
661 : struct anything {
662 : constexpr inline anything() noexcept { }
663 : template <auto V> constexpr anything(term<V>) noexcept;
664 : };
665 :
666 : // match range of term A-B
667 : template <auto A, decltype(A) B> struct range {
668 : constexpr inline range() noexcept { }
669 : //template <auto V> constexpr range(term<V>) noexcept requires (A <= V) && (V <= B);
670 : template <auto V, typename = std::enable_if_t<(A <= V) && (V <= B)>> constexpr range(term<V>) noexcept;
671 : };
672 :
673 : #ifdef __EDG__
674 : template <auto V, auto... Set> struct contains {
675 : static constexpr bool value = ((Set == V) || ... || false);
676 : };
677 : #endif
678 :
679 : // match terms defined in set
680 : template <auto... Def> struct set {
681 : constexpr inline set() noexcept { }
682 : #ifdef __EDG__
683 : template <auto V, typename = std::enable_if_t<contains<V, Def...>::value>> constexpr set(term<V>) noexcept;
684 : #else
685 : template <auto V, typename = std::enable_if_t<((Def == V) || ... || false)>> constexpr set(term<V>) noexcept;
686 : #endif
687 : };
688 :
689 : // match terms not defined in set
690 : template <auto... Def> struct neg_set {
691 : constexpr inline neg_set() noexcept { }
692 :
693 : #ifdef __EDG__
694 : template <auto V, typename = std::enable_if_t<!contains<V, Def...>::value>> constexpr neg_set(term<V>) noexcept;
695 : #else
696 : template <auto V, typename = std::enable_if_t<!((Def == V) || ... || false)>> constexpr neg_set(term<V>) noexcept;
697 : #endif
698 : };
699 :
700 : // AUGMENTED grammar which completes user-defined grammar for all other cases
701 : template <typename Grammar> struct augment_grammar: public Grammar {
702 : // start nonterminal is defined in parent type
703 : using typename Grammar::_start;
704 :
705 : // grammar rules are inherited from Grammar parent type
706 : using Grammar::rule;
707 :
708 : // term on stack and on input means pop_input;
709 : template <auto A> static constexpr auto rule(term<A>, term<A>) -> ctll::pop_input;
710 :
711 : // if the type on stack (range, set, neg_set, anything) is constructible from the terminal => pop_input
712 : template <typename Expected, auto V> static constexpr auto rule(Expected, term<V>) -> std::enable_if_t<std::is_constructible_v<Expected, term<V>>, ctll::pop_input>;
713 :
714 : // empty stack and empty input means we are accepting
715 : static constexpr auto rule(empty_stack_symbol, epsilon) -> ctll::accept;
716 :
717 : // not matching anything else => reject
718 : static constexpr auto rule(...) -> ctll::reject;
719 :
720 : // start stack is just a list<Grammar::_start>;
721 : using start_stack = list<typename Grammar::_start>;
722 : };
723 :
724 : }
725 :
726 : #endif
727 :
728 : #ifndef CTLL__ACTIONS__HPP
729 : #define CTLL__ACTIONS__HPP
730 :
731 : namespace ctll {
732 : struct empty_subject { };
733 :
734 : struct empty_actions {
735 : // dummy operator so using Actions::operator() later will not give error
736 : template <typename Action, typename InputSymbol, typename Subject> static constexpr auto apply(Action, InputSymbol, Subject subject) {
737 : return subject;
738 : }
739 : };
740 :
741 : template <typename Actions> struct identity: public Actions {
742 : using Actions::apply;
743 : // allow empty_subject to exists
744 : template <typename Action, auto V> constexpr static auto apply(Action, term<V>, empty_subject) -> empty_subject { return {}; }
745 : template <typename Action> constexpr static auto apply(Action, epsilon, empty_subject) -> empty_subject { return {}; }
746 : };
747 :
748 : template <typename Actions> struct ignore_unknown: public Actions {
749 : using Actions::apply;
750 : // allow flow thru unknown actions
751 : template <typename Action, auto V, typename Subject> constexpr static auto apply(Action, term<V>, Subject) -> Subject { return {}; }
752 : template <typename Action, typename Subject> constexpr static auto apply(Action, epsilon, Subject) -> Subject { return {}; }
753 : };
754 : }
755 :
756 : #endif
757 :
758 : #ifndef CTLL_IN_A_MODULE
759 : #include <limits>
760 : #endif
761 :
762 : namespace ctll {
763 :
764 : enum class decision {
765 : reject,
766 : accept,
767 : undecided
768 : };
769 :
770 : struct placeholder { };
771 :
772 : template <size_t> using index_placeholder = placeholder;
773 :
774 : #if CTLL_CNTTP_COMPILER_CHECK
775 : template <typename Grammar, ctll::fixed_string input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = false> struct parser { // in c++20
776 : #else
777 : template <typename Grammar, const auto & input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = false> struct parser {
778 : #endif
779 :
780 : #ifdef __GNUC__ // workaround to GCC bug
781 : #if CTLL_CNTTP_COMPILER_CHECK
782 : static constexpr auto _input = input; // c++20 mode
783 : #else
784 : static constexpr auto & _input = input; // c++17 mode
785 : #endif
786 : #else
787 : static constexpr auto _input = input; // everyone else
788 : #endif
789 :
790 : using Actions = ctll::conditional<IgnoreUnknownActions, ignore_unknown<ActionSelector>, identity<ActionSelector>>;
791 : using grammar = augment_grammar<Grammar>;
792 :
793 : template <size_t Pos, typename Stack, typename Subject, decision Decision> struct results {
794 :
795 : static constexpr bool is_correct = Decision == decision::accept;
796 :
797 : constexpr inline CTLL_FORCE_INLINE operator bool() const noexcept {
798 : return is_correct;
799 : }
800 :
801 : #ifdef __GNUC__ // workaround to GCC bug
802 : #if CTLL_CNTTP_COMPILER_CHECK
803 : static constexpr auto _input = input; // c++20 mode
804 : #else
805 : static constexpr auto & _input = input; // c++17 mode
806 : #endif
807 : #else
808 : static constexpr auto _input = input; // everyone else
809 : #endif
810 :
811 : using output_type = Subject;
812 : static constexpr size_t position = Pos;
813 :
814 : constexpr auto operator+(placeholder) const noexcept {
815 : if constexpr (Decision == decision::undecided) {
816 : // parse for current char (RPos) with previous stack and subject :)
817 : return parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template decide<Pos, Stack, Subject>({}, {});
818 : } else {
819 : // if there is decision already => just push it to the end of fold expression
820 : return *this;
821 : }
822 : }
823 : };
824 :
825 : template <size_t Pos> static constexpr auto get_current_term() noexcept {
826 : if constexpr (Pos < input.size()) {
827 : constexpr auto value = input[Pos];
828 : if constexpr (value <= static_cast<decltype(value)>((std::numeric_limits<char>::max)())) {
829 : return term<static_cast<char>(value)>{};
830 : } else {
831 : return term<value>{};
832 : }
833 :
834 : } else {
835 : // return epsilon if we are past the input
836 : return epsilon{};
837 : }
838 : }
839 : template <size_t Pos> static constexpr auto get_previous_term() noexcept {
840 : if constexpr (Pos == 0) {
841 : // there is no previous character on input if we are on start
842 : return epsilon{};
843 : } else if constexpr ((Pos-1) < input.size()) {
844 : constexpr auto value = input[Pos-1];
845 : if constexpr (value <= static_cast<decltype(value)>((std::numeric_limits<char>::max)())) {
846 : return term<static_cast<char>(value)>{};
847 : } else {
848 : return term<value>{};
849 : }
850 : } else {
851 : return epsilon{};
852 : }
853 : }
854 : // if rule is accept => return true and subject
855 : template <size_t Pos, typename Terminal, typename Stack, typename Subject>
856 : static constexpr auto move(ctll::accept, Terminal, Stack, Subject) noexcept {
857 : return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos, Stack, Subject, decision::accept>();
858 : }
859 : // if rule is reject => return false and subject
860 : template <size_t Pos, typename Terminal, typename Stack, typename Subject>
861 : static constexpr auto move(ctll::reject, Terminal, Stack, Subject) noexcept {
862 : return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos, Stack, Subject, decision::reject>();
863 : }
864 : // if rule is pop_input => move to next character
865 : template <size_t Pos, typename Terminal, typename Stack, typename Subject>
866 : static constexpr auto move(ctll::pop_input, Terminal, Stack, Subject) noexcept {
867 : return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos+1, Stack, Subject, decision::undecided>();
868 : }
869 : // if rule is string => push it to the front of stack
870 : template <size_t Pos, typename... Content, typename Terminal, typename Stack, typename Subject>
871 : static constexpr auto move(push<Content...> string, Terminal, Stack stack, Subject subject) noexcept {
872 : return decide<Pos>(push_front(string, stack), subject);
873 : }
874 : // if rule is epsilon (empty string) => continue
875 : template <size_t Pos, typename Terminal, typename Stack, typename Subject>
876 : static constexpr auto move(epsilon, Terminal, Stack stack, Subject subject) noexcept {
877 : return decide<Pos>(stack, subject);
878 : }
879 : // if rule is string with current character at the beginning (term<V>) => move to next character
880 : // and push string without the character (quick LL(1))
881 : template <size_t Pos, auto V, typename... Content, typename Stack, typename Subject>
882 : static constexpr auto move(push<term<V>, Content...>, term<V>, Stack stack, Subject) noexcept {
883 : constexpr auto local_input = input;
884 : return typename parser<Grammar, local_input, ActionSelector, IgnoreUnknownActions>::template results<Pos+1, decltype(push_front(list<Content...>(), stack)), Subject, decision::undecided>();
885 : }
886 : // if rule is string with any character at the beginning (compatible with current term<T>) => move to next character
887 : // and push string without the character (quick LL(1))
888 : template <size_t Pos, auto V, typename... Content, auto T, typename Stack, typename Subject>
889 : static constexpr auto move(push<anything, Content...>, term<T>, Stack stack, Subject) noexcept {
890 : constexpr auto local_input = input;
891 : return typename parser<Grammar, local_input, ActionSelector, IgnoreUnknownActions>::template results<Pos+1, decltype(push_front(list<Content...>(), stack)), Subject, decision::undecided>();
892 : }
893 : // decide if we need to take action or move
894 : template <size_t Pos, typename Stack, typename Subject> static constexpr auto decide(Stack previous_stack, Subject previous_subject) noexcept {
895 : // each call means we pop something from stack
896 : auto top_symbol = decltype(ctll::front(previous_stack, empty_stack_symbol()))();
897 : // gcc pedantic warning
898 : [[maybe_unused]] auto stack = decltype(ctll::pop_front(previous_stack))();
899 :
900 : // in case top_symbol is action type (apply it on previous subject and get new one)
901 : if constexpr (std::is_base_of_v<ctll::action, decltype(top_symbol)>) {
902 : auto subject = Actions::apply(top_symbol, get_previous_term<Pos>(), previous_subject);
903 :
904 : // in case that semantic action is error => reject input
905 : if constexpr (std::is_same_v<ctll::reject, decltype(subject)>) {
906 : return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos, Stack, Subject, decision::reject>();
907 : } else {
908 : return decide<Pos>(stack, subject);
909 : }
910 : } else {
911 : // all other cases are ordinary for LL(1) parser
912 : auto current_term = get_current_term<Pos>();
913 : auto rule = decltype(grammar::rule(top_symbol,current_term))();
914 : return move<Pos>(rule, current_term, stack, previous_subject);
915 : }
916 : }
917 :
918 : // trampolines with folded expression
919 : template <typename Subject, size_t... Pos> static constexpr auto trampoline_decide(Subject, std::index_sequence<Pos...>) noexcept {
920 : // parse everything for first char and than for next and next ...
921 : // Pos+1 is needed as we want to finish calculation with epsilons on stack
922 : auto v = (decide<0, typename grammar::start_stack, Subject>({}, {}) + ... + index_placeholder<Pos+1>());
923 : return v;
924 : }
925 :
926 : template <typename Subject = empty_subject> static constexpr auto trampoline_decide(Subject subject = {}) noexcept {
927 : // there will be no recursion, just sequence long as the input
928 : return trampoline_decide(subject, std::make_index_sequence<input.size()>());
929 : }
930 :
931 : template <typename Subject = empty_subject> using output = decltype(trampoline_decide<Subject>());
932 : template <typename Subject = empty_subject> static inline constexpr bool correct_with = trampoline_decide<Subject>();
933 :
934 : };
935 :
936 : } // end of ctll namespace
937 :
938 : #endif
939 :
940 : #endif
941 :
942 : #ifndef CTRE__PCRE_ACTIONS__HPP
943 : #define CTRE__PCRE_ACTIONS__HPP
944 :
945 : #ifndef CTRE__PCRE__HPP
946 : #define CTRE__PCRE__HPP
947 :
948 : // THIS FILE WAS GENERATED BY DESATOMAT TOOL, DO NOT MODIFY THIS FILE
949 :
950 : namespace ctre {
951 :
952 : struct pcre {
953 :
954 : // NONTERMINALS:
955 : struct a {};
956 : struct b {};
957 : struct backslash {};
958 : struct backslash_range {};
959 : struct block {};
960 : struct block_name2 {};
961 : struct block_name {};
962 : struct c {};
963 : struct class_named_name {};
964 : struct content2 {};
965 : struct content_in_capture {};
966 : struct content_or_empty {};
967 : struct d {};
968 : struct e {};
969 : struct f {};
970 : struct g {};
971 : struct h {};
972 : struct hexdec_repeat {};
973 : struct i {};
974 : struct j {};
975 : struct k {};
976 : struct l {};
977 : struct m {};
978 : struct mod {};
979 : struct mode_switch2 {};
980 : struct n {};
981 : struct number2 {};
982 : struct number {};
983 : struct o {};
984 : struct opt_content {};
985 : struct p {};
986 : struct property_name2 {};
987 : struct property_name {};
988 : struct property_value2 {};
989 : struct property_value {};
990 : struct range {};
991 : struct repeat {};
992 : struct s {}; using _start = s;
993 : struct set2a {};
994 : struct set2b {};
995 : struct string2 {};
996 :
997 : // 'action' types:
998 : struct class_digit: ctll::action {};
999 : struct class_horizontal_space: ctll::action {};
1000 : struct class_named_alnum: ctll::action {};
1001 : struct class_named_alpha: ctll::action {};
1002 : struct class_named_ascii: ctll::action {};
1003 : struct class_named_blank: ctll::action {};
1004 : struct class_named_cntrl: ctll::action {};
1005 : struct class_named_digit: ctll::action {};
1006 : struct class_named_graph: ctll::action {};
1007 : struct class_named_lower: ctll::action {};
1008 : struct class_named_print: ctll::action {};
1009 : struct class_named_punct: ctll::action {};
1010 : struct class_named_space: ctll::action {};
1011 : struct class_named_upper: ctll::action {};
1012 : struct class_named_word: ctll::action {};
1013 : struct class_named_xdigit: ctll::action {};
1014 : struct class_non_horizontal_space: ctll::action {};
1015 : struct class_non_vertical_space: ctll::action {};
1016 : struct class_nondigit: ctll::action {};
1017 : struct class_nonnewline: ctll::action {};
1018 : struct class_nonspace: ctll::action {};
1019 : struct class_nonword: ctll::action {};
1020 : struct class_space: ctll::action {};
1021 : struct class_vertical_space: ctll::action {};
1022 : struct class_word: ctll::action {};
1023 : struct create_hexdec: ctll::action {};
1024 : struct create_number: ctll::action {};
1025 : struct finish_hexdec: ctll::action {};
1026 : struct look_finish: ctll::action {};
1027 : struct make_alternate: ctll::action {};
1028 : struct make_atomic: ctll::action {};
1029 : struct make_back_reference: ctll::action {};
1030 : struct make_capture: ctll::action {};
1031 : struct make_capture_with_name: ctll::action {};
1032 : struct make_lazy: ctll::action {};
1033 : struct make_optional: ctll::action {};
1034 : struct make_possessive: ctll::action {};
1035 : struct make_property: ctll::action {};
1036 : struct make_property_negative: ctll::action {};
1037 : struct make_range: ctll::action {};
1038 : struct make_relative_back_reference: ctll::action {};
1039 : struct make_sequence: ctll::action {};
1040 : struct mode_case_insensitive: ctll::action {};
1041 : struct mode_case_sensitive: ctll::action {};
1042 : struct mode_multiline: ctll::action {};
1043 : struct mode_singleline: ctll::action {};
1044 : struct negate_class_named: ctll::action {};
1045 : struct prepare_capture: ctll::action {};
1046 : struct push_assert_begin: ctll::action {};
1047 : struct push_assert_end: ctll::action {};
1048 : struct push_assert_subject_begin: ctll::action {};
1049 : struct push_assert_subject_end: ctll::action {};
1050 : struct push_assert_subject_end_with_lineend: ctll::action {};
1051 : struct push_character: ctll::action {};
1052 : struct push_character_alarm: ctll::action {};
1053 : struct push_character_anything: ctll::action {};
1054 : struct push_character_escape: ctll::action {};
1055 : struct push_character_formfeed: ctll::action {};
1056 : struct push_character_newline: ctll::action {};
1057 : struct push_character_null: ctll::action {};
1058 : struct push_character_return_carriage: ctll::action {};
1059 : struct push_character_tab: ctll::action {};
1060 : struct push_empty: ctll::action {};
1061 : struct push_hexdec: ctll::action {};
1062 : struct push_name: ctll::action {};
1063 : struct push_not_word_boundary: ctll::action {};
1064 : struct push_number: ctll::action {};
1065 : struct push_property_name: ctll::action {};
1066 : struct push_property_value: ctll::action {};
1067 : struct push_word_boundary: ctll::action {};
1068 : struct repeat_ab: ctll::action {};
1069 : struct repeat_at_least: ctll::action {};
1070 : struct repeat_exactly: ctll::action {};
1071 : struct repeat_plus: ctll::action {};
1072 : struct repeat_star: ctll::action {};
1073 : struct reset_capture: ctll::action {};
1074 : struct set_combine: ctll::action {};
1075 : struct set_empty: ctll::action {};
1076 : struct set_make: ctll::action {};
1077 : struct set_make_negative: ctll::action {};
1078 : struct set_start: ctll::action {};
1079 : struct start_atomic: ctll::action {};
1080 : struct start_lookahead_negative: ctll::action {};
1081 : struct start_lookahead_positive: ctll::action {};
1082 : struct start_lookbehind_negative: ctll::action {};
1083 : struct start_lookbehind_positive: ctll::action {};
1084 :
1085 : // (q)LL1 function:
1086 : using _others = ctll::neg_set<'!','$','\x28','\x29','*','+',',','-','.','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','?','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','[','\\','\"',']','^','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\x7B','|','\x7D'>;
1087 : static constexpr auto rule(s, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2>;
1088 : static constexpr auto rule(s, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2>;
1089 : static constexpr auto rule(s, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2>;
1090 : static constexpr auto rule(s, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2>;
1091 : static constexpr auto rule(s, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2>;
1092 : static constexpr auto rule(s, ctll::set<'!',',','-','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\"',']','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
1093 : static constexpr auto rule(s, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
1094 : static constexpr auto rule(s, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2>;
1095 : static constexpr auto rule(s, ctll::term<'|'>) -> ctll::push<ctll::anything, push_empty, opt_content, make_alternate>;
1096 : static constexpr auto rule(s, ctll::epsilon) -> ctll::push<push_empty>;
1097 : static constexpr auto rule(s, ctll::set<'\x29','*','+','?','\x7B','\x7D'>) -> ctll::reject;
1098 :
1099 : static constexpr auto rule(a, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2, make_alternate>;
1100 : static constexpr auto rule(a, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2, make_alternate>;
1101 : static constexpr auto rule(a, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2, make_alternate>;
1102 : static constexpr auto rule(a, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2, make_alternate>;
1103 : static constexpr auto rule(a, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2, make_alternate>;
1104 : static constexpr auto rule(a, ctll::set<'!',',','-','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\"',']','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_character, repeat, string2, content2, make_alternate>;
1105 : static constexpr auto rule(a, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2, make_alternate>;
1106 : static constexpr auto rule(a, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2, make_alternate>;
1107 : static constexpr auto rule(a, ctll::term<'\x29'>) -> ctll::push<push_empty, make_alternate>;
1108 : static constexpr auto rule(a, ctll::epsilon) -> ctll::push<push_empty, make_alternate>;
1109 : static constexpr auto rule(a, ctll::set<'*','+','?','\x7B','|','\x7D'>) -> ctll::reject;
1110 :
1111 : static constexpr auto rule(b, ctll::term<','>) -> ctll::push<ctll::anything, n>;
1112 : static constexpr auto rule(b, ctll::term<'\x7D'>) -> ctll::push<repeat_exactly, ctll::anything>;
1113 :
1114 : static constexpr auto rule(backslash, ctll::term<'d'>) -> ctll::push<ctll::anything, class_digit>;
1115 : static constexpr auto rule(backslash, ctll::term<'h'>) -> ctll::push<ctll::anything, class_horizontal_space>;
1116 : static constexpr auto rule(backslash, ctll::term<'H'>) -> ctll::push<ctll::anything, class_non_horizontal_space>;
1117 : static constexpr auto rule(backslash, ctll::term<'V'>) -> ctll::push<ctll::anything, class_non_vertical_space>;
1118 : static constexpr auto rule(backslash, ctll::term<'D'>) -> ctll::push<ctll::anything, class_nondigit>;
1119 : static constexpr auto rule(backslash, ctll::term<'N'>) -> ctll::push<ctll::anything, class_nonnewline>;
1120 : static constexpr auto rule(backslash, ctll::term<'S'>) -> ctll::push<ctll::anything, class_nonspace>;
1121 : static constexpr auto rule(backslash, ctll::term<'W'>) -> ctll::push<ctll::anything, class_nonword>;
1122 : static constexpr auto rule(backslash, ctll::term<'s'>) -> ctll::push<ctll::anything, class_space>;
1123 : static constexpr auto rule(backslash, ctll::term<'v'>) -> ctll::push<ctll::anything, class_vertical_space>;
1124 : static constexpr auto rule(backslash, ctll::term<'w'>) -> ctll::push<ctll::anything, class_word>;
1125 : static constexpr auto rule(backslash, ctll::set<'1','2','3','4','5','6','7','8','9'>) -> ctll::push<ctll::anything, create_number, make_back_reference>;
1126 : static constexpr auto rule(backslash, ctll::term<'g'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, m>;
1127 : static constexpr auto rule(backslash, ctll::term<'p'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property>;
1128 : static constexpr auto rule(backslash, ctll::term<'P'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property_negative>;
1129 : static constexpr auto rule(backslash, ctll::term<'u'>) -> ctll::push<ctll::anything, k>;
1130 : static constexpr auto rule(backslash, ctll::term<'x'>) -> ctll::push<ctll::anything, l>;
1131 : static constexpr auto rule(backslash, ctll::term<'A'>) -> ctll::push<ctll::anything, push_assert_subject_begin>;
1132 : static constexpr auto rule(backslash, ctll::term<'z'>) -> ctll::push<ctll::anything, push_assert_subject_end>;
1133 : static constexpr auto rule(backslash, ctll::term<'Z'>) -> ctll::push<ctll::anything, push_assert_subject_end_with_lineend>;
1134 : static constexpr auto rule(backslash, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character>;
1135 : static constexpr auto rule(backslash, ctll::term<'a'>) -> ctll::push<ctll::anything, push_character_alarm>;
1136 : static constexpr auto rule(backslash, ctll::term<'e'>) -> ctll::push<ctll::anything, push_character_escape>;
1137 : static constexpr auto rule(backslash, ctll::term<'f'>) -> ctll::push<ctll::anything, push_character_formfeed>;
1138 : static constexpr auto rule(backslash, ctll::term<'n'>) -> ctll::push<ctll::anything, push_character_newline>;
1139 : static constexpr auto rule(backslash, ctll::term<'0'>) -> ctll::push<ctll::anything, push_character_null>;
1140 : static constexpr auto rule(backslash, ctll::term<'r'>) -> ctll::push<ctll::anything, push_character_return_carriage>;
1141 : static constexpr auto rule(backslash, ctll::term<'t'>) -> ctll::push<ctll::anything, push_character_tab>;
1142 : static constexpr auto rule(backslash, ctll::term<'B'>) -> ctll::push<ctll::anything, push_not_word_boundary>;
1143 : static constexpr auto rule(backslash, ctll::term<'b'>) -> ctll::push<ctll::anything, push_word_boundary>;
1144 :
1145 : static constexpr auto rule(backslash_range, ctll::term<'u'>) -> ctll::push<ctll::anything, k>;
1146 : static constexpr auto rule(backslash_range, ctll::term<'x'>) -> ctll::push<ctll::anything, l>;
1147 : static constexpr auto rule(backslash_range, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character>;
1148 : static constexpr auto rule(backslash_range, ctll::term<'a'>) -> ctll::push<ctll::anything, push_character_alarm>;
1149 : static constexpr auto rule(backslash_range, ctll::term<'e'>) -> ctll::push<ctll::anything, push_character_escape>;
1150 : static constexpr auto rule(backslash_range, ctll::term<'f'>) -> ctll::push<ctll::anything, push_character_formfeed>;
1151 : static constexpr auto rule(backslash_range, ctll::term<'n'>) -> ctll::push<ctll::anything, push_character_newline>;
1152 : static constexpr auto rule(backslash_range, ctll::term<'0'>) -> ctll::push<ctll::anything, push_character_null>;
1153 : static constexpr auto rule(backslash_range, ctll::term<'r'>) -> ctll::push<ctll::anything, push_character_return_carriage>;
1154 : static constexpr auto rule(backslash_range, ctll::term<'t'>) -> ctll::push<ctll::anything, push_character_tab>;
1155 :
1156 : static constexpr auto rule(block, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
1157 : static constexpr auto rule(block, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
1158 : static constexpr auto rule(block, ctll::term<'?'>) -> ctll::push<ctll::anything, d>;
1159 : static constexpr auto rule(block, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
1160 : static constexpr auto rule(block, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
1161 : static constexpr auto rule(block, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
1162 : static constexpr auto rule(block, ctll::set<'!',',','-','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\"',']','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_character, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
1163 : static constexpr auto rule(block, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
1164 : static constexpr auto rule(block, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
1165 : static constexpr auto rule(block, ctll::term<'|'>) -> ctll::push<ctll::anything, push_empty, content_or_empty, make_alternate, make_capture, ctll::term<'\x29'>>;
1166 : static constexpr auto rule(block, ctll::term<'\x29'>) -> ctll::push<push_empty, make_capture, ctll::anything>;
1167 : static constexpr auto rule(block, ctll::set<'*','+','\x7B','\x7D'>) -> ctll::reject;
1168 :
1169 : static constexpr auto rule(block_name2, ctll::set<'>','\x7D'>) -> ctll::epsilon;
1170 : static constexpr auto rule(block_name2, ctll::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_name, block_name2>;
1171 :
1172 : static constexpr auto rule(block_name, ctll::set<'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_name, block_name2>;
1173 :
1174 : static constexpr auto rule(c, ctll::term<'['>) -> ctll::push<ctll::anything, ctll::term<':'>, i, range, set_start, set2b, set_make, ctll::term<']'>>;
1175 : static constexpr auto rule(c, ctll::term<'\\'>) -> ctll::push<ctll::anything, e, set_start, set2b, set_make, ctll::term<']'>>;
1176 : static constexpr auto rule(c, ctll::set<'!','$','\x28','\x29','*','+',',','.','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','?','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\"','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character, range, set_start, set2b, set_make, ctll::term<']'>>;
1177 : static constexpr auto rule(c, _others) -> ctll::push<ctll::anything, push_character, range, set_start, set2b, set_make, ctll::term<']'>>;
1178 : static constexpr auto rule(c, ctll::term<'^'>) -> ctll::push<ctll::anything, set2a, set_make_negative, ctll::term<']'>>;
1179 : static constexpr auto rule(c, ctll::set<'-',']'>) -> ctll::reject;
1180 :
1181 : static constexpr auto rule(class_named_name, ctll::term<'x'>) -> ctll::push<ctll::anything, ctll::term<'d'>, ctll::term<'i'>, ctll::term<'g'>, ctll::term<'i'>, ctll::term<'t'>, class_named_xdigit>;
1182 : static constexpr auto rule(class_named_name, ctll::term<'d'>) -> ctll::push<ctll::anything, ctll::term<'i'>, ctll::term<'g'>, ctll::term<'i'>, ctll::term<'t'>, class_named_digit>;
1183 : static constexpr auto rule(class_named_name, ctll::term<'b'>) -> ctll::push<ctll::anything, ctll::term<'l'>, ctll::term<'a'>, ctll::term<'n'>, ctll::term<'k'>, class_named_blank>;
1184 : static constexpr auto rule(class_named_name, ctll::term<'c'>) -> ctll::push<ctll::anything, ctll::term<'n'>, ctll::term<'t'>, ctll::term<'r'>, ctll::term<'l'>, class_named_cntrl>;
1185 : static constexpr auto rule(class_named_name, ctll::term<'w'>) -> ctll::push<ctll::anything, ctll::term<'o'>, ctll::term<'r'>, ctll::term<'d'>, class_named_word>;
1186 : static constexpr auto rule(class_named_name, ctll::term<'l'>) -> ctll::push<ctll::anything, ctll::term<'o'>, ctll::term<'w'>, ctll::term<'e'>, ctll::term<'r'>, class_named_lower>;
1187 : static constexpr auto rule(class_named_name, ctll::term<'s'>) -> ctll::push<ctll::anything, ctll::term<'p'>, ctll::term<'a'>, ctll::term<'c'>, ctll::term<'e'>, class_named_space>;
1188 : static constexpr auto rule(class_named_name, ctll::term<'u'>) -> ctll::push<ctll::anything, ctll::term<'p'>, ctll::term<'p'>, ctll::term<'e'>, ctll::term<'r'>, class_named_upper>;
1189 : static constexpr auto rule(class_named_name, ctll::term<'g'>) -> ctll::push<ctll::anything, ctll::term<'r'>, ctll::term<'a'>, ctll::term<'p'>, ctll::term<'h'>, class_named_graph>;
1190 : static constexpr auto rule(class_named_name, ctll::term<'a'>) -> ctll::push<ctll::anything, g>;
1191 : static constexpr auto rule(class_named_name, ctll::term<'p'>) -> ctll::push<ctll::anything, h>;
1192 :
1193 : static constexpr auto rule(content2, ctll::term<'\x29'>) -> ctll::epsilon;
1194 : static constexpr auto rule(content2, ctll::epsilon) -> ctll::epsilon;
1195 : static constexpr auto rule(content2, ctll::term<'|'>) -> ctll::push<ctll::anything, a>;
1196 :
1197 : static constexpr auto rule(content_in_capture, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2>;
1198 : static constexpr auto rule(content_in_capture, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2>;
1199 : static constexpr auto rule(content_in_capture, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2>;
1200 : static constexpr auto rule(content_in_capture, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2>;
1201 : static constexpr auto rule(content_in_capture, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2>;
1202 : static constexpr auto rule(content_in_capture, ctll::set<'!',',','-','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\"',']','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
1203 : static constexpr auto rule(content_in_capture, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
1204 : static constexpr auto rule(content_in_capture, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2>;
1205 : static constexpr auto rule(content_in_capture, ctll::term<'|'>) -> ctll::push<ctll::anything, push_empty, content_or_empty, make_alternate>;
1206 : static constexpr auto rule(content_in_capture, ctll::term<'\x29'>) -> ctll::push<push_empty>;
1207 : static constexpr auto rule(content_in_capture, ctll::set<'*','+','?','\x7B','\x7D'>) -> ctll::reject;
1208 :
1209 : static constexpr auto rule(content_or_empty, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2>;
1210 : static constexpr auto rule(content_or_empty, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2>;
1211 : static constexpr auto rule(content_or_empty, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2>;
1212 : static constexpr auto rule(content_or_empty, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2>;
1213 : static constexpr auto rule(content_or_empty, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2>;
1214 : static constexpr auto rule(content_or_empty, ctll::set<'!',',','-','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\"',']','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
1215 : static constexpr auto rule(content_or_empty, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
1216 : static constexpr auto rule(content_or_empty, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2>;
1217 : static constexpr auto rule(content_or_empty, ctll::term<'\x29'>) -> ctll::push<push_empty>;
1218 : static constexpr auto rule(content_or_empty, ctll::set<'*','+','?','\x7B','|','\x7D'>) -> ctll::reject;
1219 :
1220 : static constexpr auto rule(d, ctll::term<'i'>) -> ctll::push<ctll::anything, mode_case_insensitive, mode_switch2>;
1221 : static constexpr auto rule(d, ctll::term<'c'>) -> ctll::push<ctll::anything, mode_case_sensitive, mode_switch2>;
1222 : static constexpr auto rule(d, ctll::term<'m'>) -> ctll::push<ctll::anything, mode_multiline, mode_switch2>;
1223 : static constexpr auto rule(d, ctll::term<'s'>) -> ctll::push<ctll::anything, mode_singleline, mode_switch2>;
1224 : static constexpr auto rule(d, ctll::term<'<'>) -> ctll::push<ctll::anything, o>;
1225 : static constexpr auto rule(d, ctll::term<':'>) -> ctll::push<ctll::anything, reset_capture, content_in_capture, ctll::term<'\x29'>>;
1226 : static constexpr auto rule(d, ctll::term<'>'>) -> ctll::push<ctll::anything, reset_capture, start_atomic, content_in_capture, make_atomic, ctll::term<'\x29'>>;
1227 : static constexpr auto rule(d, ctll::term<'!'>) -> ctll::push<ctll::anything, reset_capture, start_lookahead_negative, content_in_capture, look_finish, ctll::term<'\x29'>>;
1228 : static constexpr auto rule(d, ctll::term<'='>) -> ctll::push<ctll::anything, reset_capture, start_lookahead_positive, content_in_capture, look_finish, ctll::term<'\x29'>>;
1229 :
1230 : static constexpr auto rule(e, ctll::term<'d'>) -> ctll::push<ctll::anything, class_digit>;
1231 : static constexpr auto rule(e, ctll::term<'h'>) -> ctll::push<ctll::anything, class_horizontal_space>;
1232 : static constexpr auto rule(e, ctll::term<'H'>) -> ctll::push<ctll::anything, class_non_horizontal_space>;
1233 : static constexpr auto rule(e, ctll::term<'V'>) -> ctll::push<ctll::anything, class_non_vertical_space>;
1234 : static constexpr auto rule(e, ctll::term<'D'>) -> ctll::push<ctll::anything, class_nondigit>;
1235 : static constexpr auto rule(e, ctll::term<'N'>) -> ctll::push<ctll::anything, class_nonnewline>;
1236 : static constexpr auto rule(e, ctll::term<'S'>) -> ctll::push<ctll::anything, class_nonspace>;
1237 : static constexpr auto rule(e, ctll::term<'W'>) -> ctll::push<ctll::anything, class_nonword>;
1238 : static constexpr auto rule(e, ctll::term<'s'>) -> ctll::push<ctll::anything, class_space>;
1239 : static constexpr auto rule(e, ctll::term<'v'>) -> ctll::push<ctll::anything, class_vertical_space>;
1240 : static constexpr auto rule(e, ctll::term<'w'>) -> ctll::push<ctll::anything, class_word>;
1241 : static constexpr auto rule(e, ctll::term<'p'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property>;
1242 : static constexpr auto rule(e, ctll::term<'P'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property_negative>;
1243 : static constexpr auto rule(e, ctll::term<'u'>) -> ctll::push<ctll::anything, k, range>;
1244 : static constexpr auto rule(e, ctll::term<'x'>) -> ctll::push<ctll::anything, l, range>;
1245 : static constexpr auto rule(e, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character, range>;
1246 : static constexpr auto rule(e, ctll::term<'a'>) -> ctll::push<ctll::anything, push_character_alarm, range>;
1247 : static constexpr auto rule(e, ctll::term<'e'>) -> ctll::push<ctll::anything, push_character_escape, range>;
1248 : static constexpr auto rule(e, ctll::term<'f'>) -> ctll::push<ctll::anything, push_character_formfeed, range>;
1249 : static constexpr auto rule(e, ctll::term<'n'>) -> ctll::push<ctll::anything, push_character_newline, range>;
1250 : static constexpr auto rule(e, ctll::term<'0'>) -> ctll::push<ctll::anything, push_character_null, range>;
1251 : static constexpr auto rule(e, ctll::term<'r'>) -> ctll::push<ctll::anything, push_character_return_carriage, range>;
1252 : static constexpr auto rule(e, ctll::term<'t'>) -> ctll::push<ctll::anything, push_character_tab, range>;
1253 :
1254 : static constexpr auto rule(f, ctll::term<'d'>) -> ctll::push<ctll::anything, class_digit>;
1255 : static constexpr auto rule(f, ctll::term<'h'>) -> ctll::push<ctll::anything, class_horizontal_space>;
1256 : static constexpr auto rule(f, ctll::term<'H'>) -> ctll::push<ctll::anything, class_non_horizontal_space>;
1257 : static constexpr auto rule(f, ctll::term<'V'>) -> ctll::push<ctll::anything, class_non_vertical_space>;
1258 : static constexpr auto rule(f, ctll::term<'D'>) -> ctll::push<ctll::anything, class_nondigit>;
1259 : static constexpr auto rule(f, ctll::term<'N'>) -> ctll::push<ctll::anything, class_nonnewline>;
1260 : static constexpr auto rule(f, ctll::term<'S'>) -> ctll::push<ctll::anything, class_nonspace>;
1261 : static constexpr auto rule(f, ctll::term<'W'>) -> ctll::push<ctll::anything, class_nonword>;
1262 : static constexpr auto rule(f, ctll::term<'s'>) -> ctll::push<ctll::anything, class_space>;
1263 : static constexpr auto rule(f, ctll::term<'v'>) -> ctll::push<ctll::anything, class_vertical_space>;
1264 : static constexpr auto rule(f, ctll::term<'w'>) -> ctll::push<ctll::anything, class_word>;
1265 : static constexpr auto rule(f, ctll::term<'p'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property>;
1266 : static constexpr auto rule(f, ctll::term<'P'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property_negative>;
1267 : static constexpr auto rule(f, ctll::term<'u'>) -> ctll::push<ctll::anything, k, range>;
1268 : static constexpr auto rule(f, ctll::term<'x'>) -> ctll::push<ctll::anything, l, range>;
1269 : static constexpr auto rule(f, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character, range>;
1270 : static constexpr auto rule(f, ctll::term<'a'>) -> ctll::push<ctll::anything, push_character_alarm, range>;
1271 : static constexpr auto rule(f, ctll::term<'e'>) -> ctll::push<ctll::anything, push_character_escape, range>;
1272 : static constexpr auto rule(f, ctll::term<'f'>) -> ctll::push<ctll::anything, push_character_formfeed, range>;
1273 : static constexpr auto rule(f, ctll::term<'n'>) -> ctll::push<ctll::anything, push_character_newline, range>;
1274 : static constexpr auto rule(f, ctll::term<'0'>) -> ctll::push<ctll::anything, push_character_null, range>;
1275 : static constexpr auto rule(f, ctll::term<'r'>) -> ctll::push<ctll::anything, push_character_return_carriage, range>;
1276 : static constexpr auto rule(f, ctll::term<'t'>) -> ctll::push<ctll::anything, push_character_tab, range>;
1277 :
1278 : static constexpr auto rule(g, ctll::term<'s'>) -> ctll::push<ctll::anything, ctll::term<'c'>, ctll::term<'i'>, ctll::term<'i'>, class_named_ascii>;
1279 : static constexpr auto rule(g, ctll::term<'l'>) -> ctll::push<ctll::anything, p>;
1280 :
1281 : static constexpr auto rule(h, ctll::term<'r'>) -> ctll::push<ctll::anything, ctll::term<'i'>, ctll::term<'n'>, ctll::term<'t'>, class_named_print>;
1282 : static constexpr auto rule(h, ctll::term<'u'>) -> ctll::push<ctll::anything, ctll::term<'n'>, ctll::term<'c'>, ctll::term<'t'>, class_named_punct>;
1283 :
1284 : static constexpr auto rule(hexdec_repeat, ctll::term<'\x7D'>) -> ctll::epsilon;
1285 : static constexpr auto rule(hexdec_repeat, ctll::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>) -> ctll::push<ctll::anything, push_hexdec, hexdec_repeat>;
1286 :
1287 : static constexpr auto rule(i, ctll::term<'^'>) -> ctll::push<ctll::anything, class_named_name, negate_class_named, ctll::term<':'>, ctll::term<']'>>;
1288 : static constexpr auto rule(i, ctll::term<'x'>) -> ctll::push<ctll::anything, ctll::term<'d'>, ctll::term<'i'>, ctll::term<'g'>, ctll::term<'i'>, ctll::term<'t'>, class_named_xdigit, ctll::term<':'>, ctll::term<']'>>;
1289 : static constexpr auto rule(i, ctll::term<'d'>) -> ctll::push<ctll::anything, ctll::term<'i'>, ctll::term<'g'>, ctll::term<'i'>, ctll::term<'t'>, class_named_digit, ctll::term<':'>, ctll::term<']'>>;
1290 : static constexpr auto rule(i, ctll::term<'b'>) -> ctll::push<ctll::anything, ctll::term<'l'>, ctll::term<'a'>, ctll::term<'n'>, ctll::term<'k'>, class_named_blank, ctll::term<':'>, ctll::term<']'>>;
1291 : static constexpr auto rule(i, ctll::term<'c'>) -> ctll::push<ctll::anything, ctll::term<'n'>, ctll::term<'t'>, ctll::term<'r'>, ctll::term<'l'>, class_named_cntrl, ctll::term<':'>, ctll::term<']'>>;
1292 : static constexpr auto rule(i, ctll::term<'w'>) -> ctll::push<ctll::anything, ctll::term<'o'>, ctll::term<'r'>, ctll::term<'d'>, class_named_word, ctll::term<':'>, ctll::term<']'>>;
1293 : static constexpr auto rule(i, ctll::term<'l'>) -> ctll::push<ctll::anything, ctll::term<'o'>, ctll::term<'w'>, ctll::term<'e'>, ctll::term<'r'>, class_named_lower, ctll::term<':'>, ctll::term<']'>>;
1294 : static constexpr auto rule(i, ctll::term<'s'>) -> ctll::push<ctll::anything, ctll::term<'p'>, ctll::term<'a'>, ctll::term<'c'>, ctll::term<'e'>, class_named_space, ctll::term<':'>, ctll::term<']'>>;
1295 : static constexpr auto rule(i, ctll::term<'u'>) -> ctll::push<ctll::anything, ctll::term<'p'>, ctll::term<'p'>, ctll::term<'e'>, ctll::term<'r'>, class_named_upper, ctll::term<':'>, ctll::term<']'>>;
1296 : static constexpr auto rule(i, ctll::term<'g'>) -> ctll::push<ctll::anything, ctll::term<'r'>, ctll::term<'a'>, ctll::term<'p'>, ctll::term<'h'>, class_named_graph, ctll::term<':'>, ctll::term<']'>>;
1297 : static constexpr auto rule(i, ctll::term<'a'>) -> ctll::push<ctll::anything, g, ctll::term<':'>, ctll::term<']'>>;
1298 : static constexpr auto rule(i, ctll::term<'p'>) -> ctll::push<ctll::anything, h, ctll::term<':'>, ctll::term<']'>>;
1299 :
1300 : static constexpr auto rule(j, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash_range, make_range>;
1301 : static constexpr auto rule(j, ctll::set<'!','$','\x28','\x29','*','+',',','.','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','?','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\"','^','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character, make_range>;
1302 : static constexpr auto rule(j, _others) -> ctll::push<ctll::anything, push_character, make_range>;
1303 : static constexpr auto rule(j, ctll::set<'-','[',']'>) -> ctll::reject;
1304 :
1305 : static constexpr auto rule(k, ctll::term<'\x7B'>) -> ctll::push<create_hexdec, ctll::anything, ctll::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>, push_hexdec, hexdec_repeat, ctll::term<'\x7D'>, finish_hexdec>;
1306 : static constexpr auto rule(k, ctll::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>) -> ctll::push<create_hexdec, ctll::anything, push_hexdec, ctll::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>, push_hexdec, ctll::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>, push_hexdec, ctll::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>, push_hexdec, finish_hexdec>;
1307 :
1308 : static constexpr auto rule(l, ctll::term<'\x7B'>) -> ctll::push<create_hexdec, ctll::anything, ctll::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>, push_hexdec, hexdec_repeat, ctll::term<'\x7D'>, finish_hexdec>;
1309 : static constexpr auto rule(l, ctll::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>) -> ctll::push<create_hexdec, ctll::anything, push_hexdec, ctll::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>, push_hexdec, finish_hexdec>;
1310 :
1311 : static constexpr auto rule(m, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push<ctll::anything, create_number, number2, ctll::term<'\x7D'>, make_back_reference>;
1312 : static constexpr auto rule(m, ctll::term<'-'>) -> ctll::push<ctll::anything, number, ctll::term<'\x7D'>, make_relative_back_reference>;
1313 : static constexpr auto rule(m, ctll::set<'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_name, block_name2, ctll::term<'\x7D'>, make_back_reference>;
1314 :
1315 : static constexpr auto rule(mod, ctll::set<'!','$','\x28','\x29',',','-','.','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','[','\\','\"',']','^','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','|'>) -> ctll::epsilon;
1316 : static constexpr auto rule(mod, ctll::epsilon) -> ctll::epsilon;
1317 : static constexpr auto rule(mod, _others) -> ctll::epsilon;
1318 : static constexpr auto rule(mod, ctll::term<'?'>) -> ctll::push<ctll::anything, make_lazy>;
1319 : static constexpr auto rule(mod, ctll::term<'+'>) -> ctll::push<ctll::anything, make_possessive>;
1320 : static constexpr auto rule(mod, ctll::set<'*','\x7B','\x7D'>) -> ctll::reject;
1321 :
1322 : static constexpr auto rule(mode_switch2, ctll::term<'i'>) -> ctll::push<ctll::anything, mode_case_insensitive, mode_switch2>;
1323 : static constexpr auto rule(mode_switch2, ctll::term<'c'>) -> ctll::push<ctll::anything, mode_case_sensitive, mode_switch2>;
1324 : static constexpr auto rule(mode_switch2, ctll::term<'m'>) -> ctll::push<ctll::anything, mode_multiline, mode_switch2>;
1325 : static constexpr auto rule(mode_switch2, ctll::term<'s'>) -> ctll::push<ctll::anything, mode_singleline, mode_switch2>;
1326 : static constexpr auto rule(mode_switch2, ctll::term<'\x29'>) -> ctll::push<ctll::anything>;
1327 :
1328 : static constexpr auto rule(n, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push<number, repeat_ab, ctll::term<'\x7D'>, mod>;
1329 : static constexpr auto rule(n, ctll::term<'\x7D'>) -> ctll::push<repeat_at_least, ctll::anything, mod>;
1330 :
1331 : static constexpr auto rule(number2, ctll::set<',','\x7D'>) -> ctll::epsilon;
1332 : static constexpr auto rule(number2, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push<ctll::anything, push_number, number2>;
1333 :
1334 : static constexpr auto rule(number, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push<ctll::anything, create_number, number2>;
1335 :
1336 : static constexpr auto rule(o, ctll::set<'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<block_name, ctll::term<'>'>, content_in_capture, make_capture_with_name, ctll::term<'\x29'>>;
1337 : static constexpr auto rule(o, ctll::term<'!'>) -> ctll::push<ctll::anything, reset_capture, start_lookbehind_negative, content_in_capture, look_finish, ctll::term<'\x29'>>;
1338 : static constexpr auto rule(o, ctll::term<'='>) -> ctll::push<ctll::anything, reset_capture, start_lookbehind_positive, content_in_capture, look_finish, ctll::term<'\x29'>>;
1339 :
1340 : static constexpr auto rule(opt_content, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2>;
1341 : static constexpr auto rule(opt_content, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2>;
1342 : static constexpr auto rule(opt_content, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2>;
1343 : static constexpr auto rule(opt_content, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2>;
1344 : static constexpr auto rule(opt_content, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2>;
1345 : static constexpr auto rule(opt_content, ctll::set<'!',',','-','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\"',']','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
1346 : static constexpr auto rule(opt_content, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
1347 : static constexpr auto rule(opt_content, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2>;
1348 : static constexpr auto rule(opt_content, ctll::epsilon) -> ctll::push<push_empty>;
1349 : static constexpr auto rule(opt_content, ctll::set<'\x29','*','+','?','\x7B','|','\x7D'>) -> ctll::reject;
1350 :
1351 : static constexpr auto rule(p, ctll::term<'p'>) -> ctll::push<ctll::anything, ctll::term<'h'>, ctll::term<'a'>, class_named_alpha>;
1352 : static constexpr auto rule(p, ctll::term<'n'>) -> ctll::push<ctll::anything, ctll::term<'u'>, ctll::term<'m'>, class_named_alnum>;
1353 :
1354 : static constexpr auto rule(property_name2, ctll::term<'\x7D'>) -> ctll::epsilon;
1355 : static constexpr auto rule(property_name2, ctll::term<'='>) -> ctll::push<ctll::anything, property_value>;
1356 : static constexpr auto rule(property_name2, ctll::set<'.','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_property_name, property_name2>;
1357 :
1358 : static constexpr auto rule(property_name, ctll::set<'.','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_property_name, property_name2>;
1359 :
1360 : static constexpr auto rule(property_value2, ctll::term<'\x7D'>) -> ctll::epsilon;
1361 : static constexpr auto rule(property_value2, ctll::set<'.','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_property_value, property_value2>;
1362 :
1363 : static constexpr auto rule(property_value, ctll::set<'.','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_property_value, property_value2>;
1364 :
1365 : static constexpr auto rule(range, ctll::set<'!','$','\x28','\x29','*','+',',','.','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','?','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','[','\\','\"',']','^','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\x7B','|','\x7D'>) -> ctll::epsilon;
1366 : static constexpr auto rule(range, ctll::epsilon) -> ctll::epsilon;
1367 : static constexpr auto rule(range, _others) -> ctll::epsilon;
1368 : static constexpr auto rule(range, ctll::term<'-'>) -> ctll::push<ctll::anything, j>;
1369 :
1370 : static constexpr auto rule(repeat, ctll::set<'!','$','\x28','\x29',',','-','.','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','[','\\','\"',']','^','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','|'>) -> ctll::epsilon;
1371 : static constexpr auto rule(repeat, ctll::epsilon) -> ctll::epsilon;
1372 : static constexpr auto rule(repeat, _others) -> ctll::epsilon;
1373 : static constexpr auto rule(repeat, ctll::term<'?'>) -> ctll::push<ctll::anything, make_optional, mod>;
1374 : static constexpr auto rule(repeat, ctll::term<'\x7B'>) -> ctll::push<ctll::anything, number, b>;
1375 : static constexpr auto rule(repeat, ctll::term<'+'>) -> ctll::push<ctll::anything, repeat_plus, mod>;
1376 : static constexpr auto rule(repeat, ctll::term<'*'>) -> ctll::push<ctll::anything, repeat_star, mod>;
1377 : static constexpr auto rule(repeat, ctll::term<'\x7D'>) -> ctll::reject;
1378 :
1379 : static constexpr auto rule(set2a, ctll::term<'['>) -> ctll::push<ctll::anything, ctll::term<':'>, i, range, set_start, set2b>;
1380 : static constexpr auto rule(set2a, ctll::term<'\\'>) -> ctll::push<ctll::anything, f, set_start, set2b>;
1381 : static constexpr auto rule(set2a, ctll::set<'!','$','\x28','\x29','*','+',',','.','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','?','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\"','^','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character, range, set_start, set2b>;
1382 : static constexpr auto rule(set2a, _others) -> ctll::push<ctll::anything, push_character, range, set_start, set2b>;
1383 : static constexpr auto rule(set2a, ctll::term<']'>) -> ctll::push<set_empty>;
1384 : static constexpr auto rule(set2a, ctll::term<'-'>) -> ctll::reject;
1385 :
1386 : static constexpr auto rule(set2b, ctll::term<']'>) -> ctll::epsilon;
1387 : static constexpr auto rule(set2b, ctll::term<'['>) -> ctll::push<ctll::anything, ctll::term<':'>, i, range, set_combine, set2b>;
1388 : static constexpr auto rule(set2b, ctll::term<'\\'>) -> ctll::push<ctll::anything, f, set_combine, set2b>;
1389 : static constexpr auto rule(set2b, ctll::set<'!','$','\x28','\x29','*','+',',','.','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','?','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\"','^','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character, range, set_combine, set2b>;
1390 : static constexpr auto rule(set2b, _others) -> ctll::push<ctll::anything, push_character, range, set_combine, set2b>;
1391 : static constexpr auto rule(set2b, ctll::term<'-'>) -> ctll::reject;
1392 :
1393 : static constexpr auto rule(string2, ctll::set<'\x29','|'>) -> ctll::epsilon;
1394 : static constexpr auto rule(string2, ctll::epsilon) -> ctll::epsilon;
1395 : static constexpr auto rule(string2, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, make_sequence>;
1396 : static constexpr auto rule(string2, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, make_sequence>;
1397 : static constexpr auto rule(string2, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, make_sequence>;
1398 : static constexpr auto rule(string2, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, make_sequence>;
1399 : static constexpr auto rule(string2, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, make_sequence>;
1400 : static constexpr auto rule(string2, ctll::set<'!',',','-','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\"',']','_','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'>) -> ctll::push<ctll::anything, push_character, repeat, string2, make_sequence>;
1401 : static constexpr auto rule(string2, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, make_sequence>;
1402 : static constexpr auto rule(string2, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, make_sequence>;
1403 : static constexpr auto rule(string2, ctll::set<'*','+','?','\x7B','\x7D'>) -> ctll::reject;
1404 :
1405 : };
1406 :
1407 : }
1408 :
1409 : #endif //CTRE__PCRE__HPP
1410 :
1411 : #ifndef CTRE__ROTATE__HPP
1412 : #define CTRE__ROTATE__HPP
1413 :
1414 : #ifndef CTRE__ATOMS__HPP
1415 : #define CTRE__ATOMS__HPP
1416 :
1417 : #ifndef CTRE__ATOMS_CHARACTERS__HPP
1418 : #define CTRE__ATOMS_CHARACTERS__HPP
1419 :
1420 : #ifndef CTRE__UTILITY__HPP
1421 : #define CTRE__UTILITY__HPP
1422 :
1423 : #define CTRE_CNTTP_COMPILER_CHECK CTLL_CNTTP_COMPILER_CHECK
1424 :
1425 : #ifdef CTRE_IN_A_MODULE
1426 : #define CTRE_EXPORT export
1427 : #else
1428 : #define CTRE_EXPORT
1429 : #endif
1430 :
1431 : #if __GNUC__ > 9
1432 : #if __has_cpp_attribute(likely)
1433 : #define CTRE_LIKELY [[likely]]
1434 : #else
1435 : #define CTRE_LIKELY
1436 : #endif
1437 :
1438 : #if __has_cpp_attribute(unlikely)
1439 : #define CTRE_UNLIKELY [[unlikely]]
1440 : #else
1441 : #define CTRE_UNLIKELY
1442 : #endif
1443 : #else
1444 : #define CTRE_LIKELY
1445 : #define CTRE_UNLIKELY
1446 : #endif
1447 :
1448 : #ifdef _MSC_VER
1449 : #define CTRE_FORCE_INLINE __forceinline
1450 : #if __has_cpp_attribute(msvc::flatten)
1451 : #define CTRE_FLATTEN [[msvc::flatten]]
1452 : #elif _MSC_VER >= 1930 && !defined(__clang__)
1453 : #define CTRE_FLATTEN [[msvc::flatten]]
1454 : #else
1455 : #define CTRE_FLATTEN
1456 : #endif
1457 : #else
1458 : #define CTRE_FORCE_INLINE inline __attribute__((always_inline))
1459 : #define CTRE_FLATTEN __attribute__((flatten))
1460 : #endif
1461 :
1462 : #endif
1463 :
1464 : #ifndef CTRE_V2__CTRE__FLAGS_AND_MODES__HPP
1465 : #define CTRE_V2__CTRE__FLAGS_AND_MODES__HPP
1466 :
1467 : namespace ctre {
1468 :
1469 : struct singleline { };
1470 : struct multiline { };
1471 :
1472 : struct case_sensitive { };
1473 : struct case_insensitive { };
1474 :
1475 : using ci = case_insensitive;
1476 : using cs = case_sensitive;
1477 :
1478 : template <typename... Flags> struct flag_list { };
1479 :
1480 : struct flags {
1481 : bool block_empty_match = false;
1482 : bool multiline = false;
1483 : bool case_insensitive = false;
1484 :
1485 : constexpr flags() = default;
1486 : constexpr flags(const flags &) = default;
1487 : constexpr flags(flags &&) = default;
1488 :
1489 : constexpr CTRE_FORCE_INLINE flags(ctre::singleline v) noexcept { set_flag(v); }
1490 : constexpr CTRE_FORCE_INLINE flags(ctre::multiline v) noexcept { set_flag(v); }
1491 : constexpr CTRE_FORCE_INLINE flags(ctre::case_sensitive v) noexcept { set_flag(v); }
1492 : constexpr CTRE_FORCE_INLINE flags(ctre::case_insensitive v) noexcept { set_flag(v); }
1493 :
1494 :
1495 0 : template <typename... Args> constexpr CTRE_FORCE_INLINE flags(ctll::list<Args...>) noexcept {
1496 0 : (this->set_flag(Args{}), ...);
1497 0 : }
1498 :
1499 : constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_case_insensitive) noexcept {
1500 : f.case_insensitive = true;
1501 : return f;
1502 : }
1503 :
1504 : constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_case_sensitive) noexcept {
1505 : f.case_insensitive = false;
1506 : return f;
1507 : }
1508 :
1509 : constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_singleline) noexcept {
1510 : f.multiline = false;
1511 : return f;
1512 : }
1513 :
1514 : constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_multiline) noexcept {
1515 : f.multiline = true;
1516 : return f;
1517 : }
1518 :
1519 : constexpr CTRE_FORCE_INLINE void set_flag(ctre::singleline) noexcept {
1520 0 : multiline = false;
1521 0 : }
1522 :
1523 : constexpr CTRE_FORCE_INLINE void set_flag(ctre::multiline) noexcept {
1524 : multiline = true;
1525 : }
1526 :
1527 : constexpr CTRE_FORCE_INLINE void set_flag(ctre::case_insensitive) noexcept {
1528 : case_insensitive = true;
1529 : }
1530 :
1531 : constexpr CTRE_FORCE_INLINE void set_flag(ctre::case_sensitive) noexcept {
1532 : case_insensitive = false;
1533 : }
1534 : };
1535 :
1536 : constexpr CTRE_FORCE_INLINE auto not_empty_match(flags f) {
1537 0 : f.block_empty_match = true;
1538 0 : return f;
1539 : }
1540 :
1541 : constexpr CTRE_FORCE_INLINE auto consumed_something(flags f, bool condition = true) {
1542 0 : if (condition) f.block_empty_match = false;
1543 0 : return f;
1544 : }
1545 :
1546 : constexpr CTRE_FORCE_INLINE bool cannot_be_empty_match(flags f) {
1547 0 : return f.block_empty_match;
1548 : }
1549 :
1550 : constexpr CTRE_FORCE_INLINE bool multiline_mode(flags f) {
1551 0 : return f.multiline;
1552 : }
1553 :
1554 : constexpr CTRE_FORCE_INLINE bool is_case_insensitive(flags f) {
1555 0 : return f.case_insensitive;
1556 : }
1557 :
1558 : } // namespace ctre
1559 :
1560 : #endif
1561 :
1562 : #ifndef CTRE_IN_A_MODULE
1563 : #include <cstdint>
1564 : #endif
1565 :
1566 : namespace ctre {
1567 :
1568 : // sfinae check for types here
1569 :
1570 : template <typename T> class MatchesCharacter {
1571 : template <typename Y, typename CharT> static auto test(CharT c) -> decltype(Y::match_char(c, std::declval<const flags &>()), std::true_type());
1572 : template <typename> static auto test(...) -> std::false_type;
1573 : public:
1574 : template <typename CharT> static inline constexpr bool value = decltype(test<T>(std::declval<CharT>()))();
1575 : };
1576 :
1577 : template <typename T> constexpr CTRE_FORCE_INLINE bool is_ascii_alpha(T v) {
1578 : return ((v >= static_cast<T>('a') && v <= static_cast<T>('z')) || (v >= static_cast<T>('A') && v <= static_cast<T>('Z')));
1579 : }
1580 :
1581 : template <typename T> constexpr CTRE_FORCE_INLINE bool is_ascii_alpha_lowercase(T v) {
1582 : return (v >= static_cast<T>('a')) && (v <= static_cast<T>('z'));
1583 : }
1584 :
1585 : template <typename T> constexpr CTRE_FORCE_INLINE bool is_ascii_alpha_uppercase(T v) {
1586 : return (v >= static_cast<T>('A')) && v <= (static_cast<T>('Z'));
1587 : }
1588 :
1589 : template <auto V> struct character {
1590 : template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char(CharT value, const flags & f) noexcept {
1591 : if constexpr (is_ascii_alpha(V)) {
1592 0 : if (is_case_insensitive(f)) {
1593 0 : if (value == (V ^ static_cast<decltype(V)>(0x20))) {
1594 0 : return true;//
1595 : }
1596 : }
1597 : }
1598 0 : return static_cast<std::make_unsigned_t<CharT>>(value) == V;
1599 : }
1600 : };
1601 :
1602 : template <typename... Content> struct negative_set {
1603 : template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char([[maybe_unused]] CharT value, const flags & f) noexcept {
1604 : return !(Content::match_char(value, f) || ... || false);
1605 : }
1606 : };
1607 :
1608 : template <typename... Content> struct set {
1609 : template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char([[maybe_unused]] CharT value, const flags & f) noexcept {
1610 0 : return (Content::match_char(value, f) || ... || false);
1611 : }
1612 : };
1613 :
1614 : template <auto... Cs> struct enumeration : set<character<Cs>...> { };
1615 :
1616 : template <typename... Content> struct negate {
1617 : template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char([[maybe_unused]] CharT value, const flags & f) noexcept {
1618 : return !(Content::match_char(value, f) || ... || false);
1619 : }
1620 : };
1621 :
1622 : template <auto A, auto B> struct char_range {
1623 : template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char(CharT value, const flags & f) noexcept {
1624 : if constexpr (is_ascii_alpha_lowercase(A) && is_ascii_alpha_lowercase(B)) {
1625 : if (is_case_insensitive(f)) {
1626 : if (value >= (A ^ static_cast<decltype(A)>(0x20)) && value <= (B ^ static_cast<decltype(B)>(0x20))) {
1627 : return true;//
1628 : }
1629 : }
1630 : } else if constexpr (is_ascii_alpha_uppercase(A) && is_ascii_alpha_uppercase(B)) {
1631 : if (is_case_insensitive(f)) {
1632 : if (value >= (A ^ static_cast<decltype(A)>(0x20)) && value <= (B ^ static_cast<decltype(B)>(0x20))) {
1633 : return true;//
1634 : }
1635 : }
1636 : }
1637 0 : return (static_cast<std::make_unsigned_t<CharT>>(value) >= A) && (static_cast<std::make_unsigned_t<CharT>>(value) <= B);
1638 : }
1639 : };
1640 : using word_chars = set<char_range<'A','Z'>, char_range<'a','z'>, char_range<'0','9'>, character<'_'> >;
1641 :
1642 : using space_chars = enumeration<' ', '\t', '\n', '\v', '\f', '\r'>;
1643 :
1644 : using vertical_space_chars = enumeration<
1645 : char{0x000A}, // Linefeed (LF)
1646 : char{0x000B}, // Vertical tab (VT)
1647 : char{0x000C}, // Form feed (FF)
1648 : char{0x000D}, // Carriage return (CR)
1649 : char32_t{0x0085}, // Next line (NEL)
1650 : char32_t{0x2028}, // Line separator
1651 : char32_t{0x2029} // Paragraph separator
1652 : >;
1653 :
1654 : using horizontal_space_chars = enumeration<
1655 : char{0x0009}, // Horizontal tab (HT)
1656 : char{0x0020}, // Space
1657 : char32_t{0x00A0}, // Non-break space
1658 : char32_t{0x1680}, // Ogham space mark
1659 : char32_t{0x180E}, // Mongolian vowel separator
1660 : char32_t{0x2000}, // En quad
1661 : char32_t{0x2001}, // Em quad
1662 : char32_t{0x2002}, // En space
1663 : char32_t{0x2003}, // Em space
1664 : char32_t{0x2004}, // Three-per-em space
1665 : char32_t{0x2005}, // Four-per-em space
1666 : char32_t{0x2006}, // Six-per-em space
1667 : char32_t{0x2007}, // Figure space
1668 : char32_t{0x2008}, // Punctuation space
1669 : char32_t{0x2009}, // Thin space
1670 : char32_t{0x200A}, // Hair space
1671 : char32_t{0x202F}, // Narrow no-break space
1672 : char32_t{0x205F}, // Medium mathematical space
1673 : char32_t{0x3000} // Ideographic space
1674 : >;
1675 :
1676 : using alphanum_chars = set<char_range<'A','Z'>, char_range<'a','z'>, char_range<'0','9'> >;
1677 :
1678 : using alpha_chars = set<char_range<'A','Z'>, char_range<'a','z'> >;
1679 :
1680 : using xdigit_chars = set<char_range<'A','F'>, char_range<'a','f'>, char_range<'0','9'> >;
1681 :
1682 : using punct_chars
1683 : = enumeration<'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-',
1684 : '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']',
1685 : '^', '_', '`', '{', '|', '}', '~'>;
1686 :
1687 : using digit_chars = char_range<'0','9'>;
1688 :
1689 : using ascii_chars = char_range<'\x00','\x7F'>;
1690 :
1691 : }
1692 :
1693 : #endif
1694 :
1695 : #ifndef CTRE_IN_A_MODULE
1696 : #include <cstdint>
1697 : #endif
1698 :
1699 : namespace ctre {
1700 :
1701 : // special helpers for matching
1702 : struct accept { };
1703 : struct reject { };
1704 : struct start_mark { };
1705 : struct end_mark { };
1706 : struct end_cycle_mark { };
1707 : struct end_lookahead_mark { };
1708 : struct end_lookbehind_mark { };
1709 : template <size_t Id> struct numeric_mark { };
1710 :
1711 : struct any { };
1712 :
1713 : // actual AST of regexp
1714 : template <auto... Str> struct string { };
1715 : template <typename... Opts> struct select { };
1716 : template <typename... Content> struct sequence { };
1717 : struct empty { };
1718 :
1719 : template <size_t a, size_t b, typename... Content> struct repeat { };
1720 : template <typename... Content> using plus = repeat<1,0,Content...>;
1721 : template <typename... Content> using star = repeat<0,0,Content...>;
1722 :
1723 : template <size_t a, size_t b, typename... Content> struct lazy_repeat { };
1724 : template <typename... Content> using lazy_plus = lazy_repeat<1,0,Content...>;
1725 : template <typename... Content> using lazy_star = lazy_repeat<0,0,Content...>;
1726 :
1727 : template <size_t a, size_t b, typename... Content> struct possessive_repeat { };
1728 : template <typename... Content> using possessive_plus = possessive_repeat<1,0,Content...>;
1729 : template <typename... Content> using possessive_star = possessive_repeat<0,0,Content...>;
1730 :
1731 : template <typename... Content> using optional = repeat<0,1,Content...>;
1732 : template <typename... Content> using lazy_optional = lazy_repeat<0,1,Content...>;
1733 : template <typename... Content> using possessive_optional = possessive_repeat<0,1,Content...>;
1734 :
1735 : template <size_t Index, typename... Content> struct capture { };
1736 :
1737 : template <size_t Index, typename Name, typename... Content> struct capture_with_name { };
1738 :
1739 : template <size_t Index> struct back_reference { };
1740 : template <typename Name> struct back_reference_with_name { };
1741 :
1742 : template <typename Type> struct look_start { };
1743 :
1744 : template <typename... Content> struct lookahead_positive { };
1745 : template <typename... Content> struct lookahead_negative { };
1746 :
1747 : template <typename... Content> struct lookbehind_positive { };
1748 : template <typename... Content> struct lookbehind_negative { };
1749 :
1750 : struct atomic_start { };
1751 :
1752 : template <typename... Content> struct atomic_group { };
1753 :
1754 : template <typename... Content> struct boundary { };
1755 : template <typename... Content> struct not_boundary { };
1756 :
1757 : using word_boundary = boundary<word_chars>;
1758 : using not_word_boundary = not_boundary<word_chars>;
1759 :
1760 : struct assert_subject_begin { };
1761 : struct assert_subject_end { };
1762 : struct assert_subject_end_line{ };
1763 : struct assert_line_begin { };
1764 : struct assert_line_end { };
1765 :
1766 : template <typename> struct mode_switch { };
1767 :
1768 : }
1769 :
1770 : #endif
1771 :
1772 : #ifndef CTRE__ATOMS_UNICODE__HPP
1773 : #define CTRE__ATOMS_UNICODE__HPP
1774 :
1775 : // master branch is not including unicode db (for now)
1776 : #ifndef H_COR3NTIN_UNICODE_SYNOPSYS
1777 : #define H_COR3NTIN_UNICODE_SYNOPSYS
1778 :
1779 : #ifndef UNICODE_DB_IN_A_MODULE
1780 : #include <string_view>
1781 : #endif
1782 :
1783 : namespace uni
1784 : {
1785 : enum class category;
1786 : enum class property;
1787 : enum class version : unsigned char;
1788 : enum class script ;
1789 : enum class block;
1790 :
1791 : struct script_extensions_view {
1792 : constexpr script_extensions_view(char32_t);
1793 :
1794 : struct sentinel {};
1795 : struct iterator {
1796 :
1797 : constexpr iterator(char32_t c);
1798 : constexpr script operator*() const;
1799 :
1800 : constexpr iterator& operator++(int);
1801 :
1802 : constexpr iterator operator++();
1803 :
1804 : constexpr bool operator==(sentinel) const;
1805 : constexpr bool operator!=(sentinel) const;
1806 :
1807 : private:
1808 : char32_t m_c;
1809 : script m_script;
1810 : int idx = 1;
1811 : };
1812 :
1813 : constexpr iterator begin() const;
1814 : constexpr sentinel end() const;
1815 :
1816 : private:
1817 : char32_t c;
1818 : };
1819 :
1820 : struct numeric_value {
1821 :
1822 : constexpr double value() const;
1823 : constexpr long long numerator() const;
1824 : constexpr int denominator() const;
1825 : constexpr bool is_valid() const;
1826 :
1827 : protected:
1828 : constexpr numeric_value() = default;
1829 : constexpr numeric_value(long long n, int16_t d);
1830 :
1831 : long long _n = 0;
1832 : int16_t _d = 0;
1833 : friend constexpr numeric_value cp_numeric_value(char32_t cp);
1834 : };
1835 :
1836 : constexpr category cp_category(char32_t cp);
1837 : constexpr script cp_script(char32_t cp);
1838 : constexpr script_extensions_view cp_script_extensions(char32_t cp);
1839 : constexpr version cp_age(char32_t cp);
1840 : constexpr block cp_block(char32_t cp);
1841 : constexpr bool cp_is_valid(char32_t cp);
1842 : constexpr bool cp_is_assigned(char32_t cp);
1843 : constexpr bool cp_is_ascii(char32_t cp);
1844 : constexpr numeric_value cp_numeric_value(char32_t cp);
1845 :
1846 : template<script>
1847 : constexpr bool cp_script_is(char32_t);
1848 : template<property>
1849 : constexpr bool cp_property_is(char32_t);
1850 : template<category>
1851 : constexpr bool cp_category_is(char32_t);
1852 :
1853 : namespace detail
1854 : {
1855 : enum class binary_prop;
1856 : constexpr int propnamecomp(std::string_view sa, std::string_view sb);
1857 : constexpr binary_prop binary_prop_from_string(std::string_view s);
1858 :
1859 : template<binary_prop p>
1860 : constexpr bool get_binary_prop(char32_t) = delete;
1861 :
1862 : constexpr script script_from_string(std::string_view s);
1863 : constexpr block block_from_string(std::string_view s);
1864 : constexpr version age_from_string(std::string_view a);
1865 : constexpr category category_from_string(std::string_view a);
1866 :
1867 : constexpr bool is_unassigned(category cat);
1868 : constexpr bool is_unknown(script s);
1869 : constexpr bool is_unknown(block b);
1870 : constexpr bool is_unassigned(version v);
1871 : constexpr bool is_unknown(binary_prop s);
1872 : }
1873 : }
1874 :
1875 : #endif
1876 :
1877 : namespace ctre {
1878 :
1879 : // properties name & value
1880 :
1881 : template <auto... Str> struct property_name { };
1882 : template <auto... Str> struct property_value { };
1883 :
1884 : template <size_t Sz> constexpr std::string_view get_string_view(const char (& arr)[Sz]) noexcept {
1885 : return std::string_view(arr, Sz);
1886 : }
1887 :
1888 : // basic support for binary and type-value properties
1889 :
1890 : template <typename T, T Type> struct binary_property;
1891 : template <typename T, T Type, auto Value> struct property;
1892 :
1893 : template <auto Type> using make_binary_property = binary_property<std::remove_const_t<decltype(Type)>, Type>;
1894 : template <auto Type, auto Value> using make_property = property<std::remove_const_t<decltype(Type)>, Type, Value>;
1895 :
1896 : // unicode TS#18 level 1.2 general_category
1897 : template <uni::detail::binary_prop Property> struct binary_property<uni::detail::binary_prop, Property> {
1898 : template <typename CharT> inline static constexpr bool match_char(CharT c, const flags &) noexcept {
1899 : return uni::detail::get_binary_prop<Property>(static_cast<char32_t>(static_cast<std::make_unsigned_t<CharT>>(c)));
1900 : }
1901 : };
1902 :
1903 : // unicode TS#18 level 1.2.2
1904 :
1905 : enum class property_type {
1906 : script, script_extension, age, block, unknown
1907 : };
1908 :
1909 : // unicode TS#18 level 1.2.2
1910 :
1911 : template <uni::script Script> struct binary_property<uni::script, Script> {
1912 : template <typename CharT> inline static constexpr bool match_char(CharT c, const flags &) noexcept {
1913 : return uni::cp_script(c) == Script;
1914 : }
1915 : };
1916 :
1917 : template <uni::script Script> struct property<property_type, property_type::script_extension, Script> {
1918 : template <typename CharT> inline static constexpr bool match_char(CharT c, const flags &) noexcept {
1919 : for (uni::script sc: uni::cp_script_extensions(c)) {
1920 : if (sc == Script) return true;
1921 : }
1922 : return false;
1923 : }
1924 : };
1925 :
1926 : template <uni::version Age> struct binary_property<uni::version, Age> {
1927 : template <typename CharT> inline static constexpr bool match_char(CharT c, const flags &) noexcept {
1928 : return uni::cp_age(c) <= Age;
1929 : }
1930 : };
1931 :
1932 : template <uni::block Block> struct binary_property<uni::block, Block> {
1933 : template <typename CharT> inline static constexpr bool match_char(CharT c, const flags &) noexcept {
1934 : return uni::cp_block(c) == Block;
1935 : }
1936 : };
1937 :
1938 : // nonbinary properties
1939 :
1940 : template <typename = void> // Make it always a template as propnamecomp isn't defined yet
1941 : constexpr property_type property_type_from_name(std::string_view str) noexcept {
1942 : using namespace std::string_view_literals;
1943 : if (uni::detail::propnamecomp(str, "script"sv) == 0 || uni::detail::propnamecomp(str, "sc"sv) == 0) {
1944 : return property_type::script;
1945 : } else if (uni::detail::propnamecomp(str, "script_extension"sv) == 0 || uni::detail::propnamecomp(str, "scx"sv) == 0) {
1946 : return property_type::script_extension;
1947 : } else if (uni::detail::propnamecomp(str, "age"sv) == 0) {
1948 : return property_type::age;
1949 : } else if (uni::detail::propnamecomp(str, "block"sv) == 0) {
1950 : return property_type::block;
1951 : } else {
1952 : return property_type::unknown;
1953 : }
1954 : }
1955 :
1956 : template <property_type Property> struct property_type_builder {
1957 : template <auto... Value> static constexpr auto get() {
1958 : return ctll::reject{};
1959 : }
1960 : };
1961 :
1962 : template <auto... Name> struct property_builder {
1963 : static constexpr char name[sizeof...(Name)]{static_cast<char>(Name)...};
1964 : static constexpr property_type type = property_type_from_name(get_string_view(name));
1965 :
1966 : using helper = property_type_builder<type>;
1967 :
1968 : template <auto... Value> static constexpr auto get() {
1969 : return helper::template get<Value...>();
1970 : }
1971 : };
1972 :
1973 : // unicode TS#18 level 1.2.2 script support
1974 :
1975 : template <> struct property_type_builder<property_type::script> {
1976 : template <auto... Value> static constexpr auto get() {
1977 : constexpr char value[sizeof...(Value)]{static_cast<char>(Value)...};
1978 : constexpr auto sc = uni::detail::script_from_string(get_string_view(value));
1979 : if constexpr (uni::detail::is_unknown(sc)) {
1980 : return ctll::reject{};
1981 : } else {
1982 : return make_binary_property<sc>();
1983 : }
1984 : }
1985 : };
1986 :
1987 : template <> struct property_type_builder<property_type::script_extension> {
1988 : template <auto... Value> static constexpr auto get() {
1989 : constexpr char value[sizeof...(Value)]{static_cast<char>(Value)...};
1990 : constexpr auto sc = uni::detail::script_from_string(get_string_view(value));
1991 : if constexpr (uni::detail::is_unknown(sc)) {
1992 : return ctll::reject{};
1993 : } else {
1994 : return make_property<property_type::script_extension, sc>();
1995 : }
1996 : }
1997 : };
1998 :
1999 : template <> struct property_type_builder<property_type::age> {
2000 : template <auto... Value> static constexpr auto get() {
2001 : constexpr char value[sizeof...(Value)]{static_cast<char>(Value)...};
2002 : constexpr auto age = uni::detail::age_from_string(get_string_view(value));
2003 : if constexpr (uni::detail::is_unassigned(age)) {
2004 : return ctll::reject{};
2005 : } else {
2006 : return make_binary_property<age>();
2007 : }
2008 : }
2009 : };
2010 :
2011 : template <> struct property_type_builder<property_type::block> {
2012 : template <auto... Value> static constexpr auto get() {
2013 : constexpr char value[sizeof...(Value)]{static_cast<char>(Value)...};
2014 : constexpr auto block = uni::detail::block_from_string(get_string_view(value));
2015 : if constexpr (uni::detail::is_unknown(block)) {
2016 : return ctll::reject{};
2017 : } else {
2018 : return make_binary_property<block>();
2019 : }
2020 : }
2021 : };
2022 :
2023 : }
2024 :
2025 : #endif
2026 :
2027 : namespace ctre {
2028 :
2029 : // helper functions
2030 : template <size_t Index, typename... Content> auto convert_to_capture(ctll::list<Content...>) -> capture<Index, Content...>;
2031 : template <size_t Index, typename Name, typename... Content> auto convert_to_named_capture(ctll::list<Content...>) -> capture_with_name<Index, Name, Content...>;
2032 : template <template <size_t, size_t, typename...> typename CycleType, size_t A, size_t B, typename... Content> auto convert_to_repeat(ctll::list<Content...>) -> CycleType<A, B, Content...>;
2033 : template <template <typename...> typename ListType, typename... Content> auto convert_to_basic_list(ctll::list<Content...>) -> ListType<Content...>;
2034 :
2035 : template <auto V> struct rotate_value {
2036 : template <auto... Vs> friend constexpr auto operator+(string<Vs...>, rotate_value<V>) noexcept -> string<V, Vs...> { return {}; }
2037 : };
2038 :
2039 : struct rotate_for_lookbehind {
2040 :
2041 : // from atoms_characters.hpp
2042 : template <auto V> static auto rotate(character<V>) -> character<V>;
2043 : template <typename... Content> static auto rotate(negative_set<Content...>) -> negative_set<Content...>;
2044 : template <typename... Content> static auto rotate(set<Content...>) -> set<Content...>;
2045 : template <auto... Cs> static auto rotate(enumeration<Cs...>) -> enumeration<Cs...>;
2046 : template <typename... Content> static auto rotate(negate<Content...>) -> negate<Content...>;
2047 : template <auto A, auto B> static auto rotate(char_range<A,B>) -> char_range<A,B>;
2048 :
2049 : // from atoms_unicode.hpp
2050 : template <auto... Str> static auto rotate(property_name<Str...>) -> property_name<Str...>;
2051 : template <auto... Str> static auto rotate(property_value<Str...>) -> property_value<Str...>;
2052 : template <typename T, T Type> static auto rotate(binary_property<T, Type>) -> binary_property<T, Type>;
2053 : template <typename T, T Type, auto Value> static auto rotate(property<T, Type, Value>) -> property<T, Type, Value>;
2054 :
2055 : // from atoms.hpp
2056 : static auto rotate(accept) -> accept;
2057 : static auto rotate(reject) -> reject;
2058 : static auto rotate(start_mark) -> start_mark;
2059 : static auto rotate(end_mark) -> end_mark;
2060 : static auto rotate(end_cycle_mark) -> end_cycle_mark;
2061 : static auto rotate(end_lookahead_mark) -> end_lookahead_mark;
2062 : static auto rotate(end_lookbehind_mark) -> end_lookbehind_mark;
2063 : template <size_t Id> static auto rotate(numeric_mark<Id>) -> numeric_mark<Id>;
2064 : static auto rotate(any) -> any;
2065 :
2066 : static auto rotate(empty) -> empty;
2067 :
2068 : // select rotates only insides of selection, not select itself
2069 : template <typename... Content> static auto rotate(select<Content...>) {
2070 : return select<decltype(rotate(Content{}))...>{};
2071 : }
2072 :
2073 : template <size_t a, size_t b, typename... Content> static auto rotate(repeat<a,b,Content...>) -> decltype(ctre::convert_to_repeat<repeat, a, b>(ctll::rotate(ctll::list<decltype(rotate(Content{}))...>{})));
2074 : template <size_t a, size_t b, typename... Content> static auto rotate(lazy_repeat<a,b,Content...>) -> decltype(ctre::convert_to_repeat<lazy_repeat, a, b>(ctll::rotate(ctll::list<decltype(rotate(Content{}))...>{})));
2075 : template <size_t a, size_t b, typename... Content> static auto rotate(possessive_repeat<a,b,Content...>) -> decltype(ctre::convert_to_repeat<possessive_repeat, a, b>(ctll::rotate(ctll::list<decltype(rotate(Content{}))...>{})));
2076 :
2077 : template <size_t Index, typename... Content> static auto rotate(capture<Index, Content...>) {
2078 : return ctre::convert_to_capture<Index>(ctll::rotate(ctll::list<decltype(rotate(Content{}))...>{}));
2079 : }
2080 :
2081 : template <size_t Index, typename Name, typename... Content> static auto rotate(capture_with_name<Index, Name, Content...>) {
2082 : return ctre::convert_to_named_capture<Index, Name>(ctll::rotate(ctll::list<decltype(rotate(Content{}))...>{}));
2083 : }
2084 :
2085 : template <size_t Index> static auto rotate(back_reference<Index>) -> back_reference<Index>;
2086 : template <typename Name> static auto rotate(back_reference_with_name<Name>) -> back_reference_with_name<Name>;
2087 :
2088 : template <typename... Content> static auto rotate(look_start<Content...>) -> look_start<Content...>;
2089 :
2090 : template <auto... Str> static auto rotate(string<Str...>) -> decltype((string<>{} + ... + rotate_value<Str>{}));
2091 :
2092 : template <typename... Content> static auto rotate(sequence<Content...>) {
2093 : return ctre::convert_to_basic_list<sequence>(ctll::rotate(ctll::list<decltype(rotate(Content{}))...>{}));
2094 : }
2095 :
2096 : // we don't rotate lookaheads
2097 : template <typename... Content> static auto rotate(lookahead_positive<Content...>) -> lookahead_positive<Content...>;
2098 : template <typename... Content> static auto rotate(lookahead_negative<Content...>) -> lookahead_negative<Content...>;
2099 : template <typename... Content> static auto rotate(lookbehind_positive<Content...>) -> lookbehind_positive<Content...>;
2100 : template <typename... Content> static auto rotate(lookbehind_negative<Content...>) -> lookbehind_negative<Content...>;
2101 :
2102 : static auto rotate(atomic_start) -> atomic_start;
2103 :
2104 : template <typename... Content> static auto rotate(atomic_group<Content...>) {
2105 : return ctre::convert_to_basic_list<atomic_group>(ctll::rotate(ctll::list<decltype(rotate(Content{}))...>{}));
2106 : }
2107 :
2108 : template <typename... Content> static auto rotate(boundary<Content...>) -> boundary<Content...>;
2109 : template <typename... Content> static auto rotate(not_boundary<Content...>) -> not_boundary<Content...>;
2110 :
2111 : static auto rotate(assert_subject_begin) -> assert_subject_begin;
2112 : static auto rotate(assert_subject_end) -> assert_subject_end;
2113 : static auto rotate(assert_subject_end_line) -> assert_subject_end_line;
2114 : static auto rotate(assert_line_begin) -> assert_line_begin;
2115 : static auto rotate(assert_line_end) -> assert_line_end;
2116 :
2117 : };
2118 :
2119 : }
2120 :
2121 : #endif
2122 :
2123 : #ifndef CTRE__ID__HPP
2124 : #define CTRE__ID__HPP
2125 :
2126 : #ifndef CTRE_IN_A_MODULE
2127 : #include <type_traits>
2128 : #endif
2129 :
2130 : namespace ctre {
2131 :
2132 : template <auto... Name> struct id {
2133 : static constexpr auto name = ctll::fixed_string<sizeof...(Name)>{{Name...}};
2134 :
2135 : friend constexpr auto operator==(id<Name...>, id<Name...>) noexcept -> std::true_type { return {}; }
2136 :
2137 : template <auto... Other> friend constexpr auto operator==(id<Name...>, id<Other...>) noexcept -> std::false_type { return {}; }
2138 :
2139 : template <typename T> friend constexpr auto operator==(id<Name...>, T) noexcept -> std::false_type { return {}; }
2140 :
2141 : template <typename T> friend constexpr auto operator==(T, id<Name...>) noexcept -> std::false_type { return {}; }
2142 : };
2143 :
2144 : }
2145 :
2146 : #endif
2147 :
2148 : #ifndef CTRE_IN_A_MODULE
2149 : #include <cstdint>
2150 : #include <limits>
2151 : #endif
2152 :
2153 : namespace ctre {
2154 :
2155 : template <size_t Counter> struct pcre_parameters {
2156 : static constexpr size_t current_counter = Counter;
2157 : };
2158 :
2159 : template <typename Stack = ctll::list<>, typename Parameters = pcre_parameters<0>, typename Mode = ctll::list<>> struct pcre_context {
2160 : using stack_type = Stack;
2161 : using parameters_type = Parameters;
2162 : using mode_list = Mode;
2163 : static constexpr inline auto stack = stack_type();
2164 : static constexpr inline auto parameters = parameters_type();
2165 : static constexpr inline auto mode = mode_list();
2166 : constexpr pcre_context() noexcept { }
2167 : constexpr pcre_context(Stack, Parameters) noexcept { }
2168 : constexpr pcre_context(Stack, Parameters, Mode) noexcept { }
2169 : };
2170 :
2171 : template <typename... Content, typename Parameters> pcre_context(ctll::list<Content...>, Parameters) -> pcre_context<ctll::list<Content...>, Parameters>;
2172 :
2173 : template <size_t Value> struct number { };
2174 :
2175 : template <size_t Id> struct capture_id { };
2176 :
2177 : struct pcre_actions {
2178 : // i know it's ugly, but it's more readable
2179 : #ifndef CTRE__ACTIONS__ASSERTS__HPP
2180 : #define CTRE__ACTIONS__ASSERTS__HPP
2181 :
2182 : // push_assert_begin
2183 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_assert_begin, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2184 : return pcre_context{ctll::push_front(assert_line_begin(), subject.stack), subject.parameters};
2185 : }
2186 :
2187 : // push_assert_end
2188 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_assert_end, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2189 : return pcre_context{ctll::push_front(assert_line_end(), subject.stack), subject.parameters};
2190 : }
2191 :
2192 : // push_assert_begin
2193 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_assert_subject_begin, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2194 : return pcre_context{ctll::push_front(assert_subject_begin(), subject.stack), subject.parameters};
2195 : }
2196 :
2197 : // push_assert_subject_end
2198 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_assert_subject_end, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2199 : return pcre_context{ctll::push_front(assert_subject_end(), subject.stack), subject.parameters};
2200 : }
2201 :
2202 : // push_assert_subject_end_with_lineend
2203 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_assert_subject_end_with_lineend, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2204 : return pcre_context{ctll::push_front(assert_subject_end_line(), subject.stack), subject.parameters};
2205 : }
2206 :
2207 : #endif
2208 :
2209 : #ifndef CTRE__ACTIONS__ATOMIC_GROUP__HPP
2210 : #define CTRE__ACTIONS__ATOMIC_GROUP__HPP
2211 :
2212 : // atomic start
2213 : template <auto V, typename... Ts, size_t Counter> static constexpr auto apply(pcre::start_atomic, ctll::term<V>, pcre_context<ctll::list<Ts...>, pcre_parameters<Counter>>) {
2214 : return pcre_context{ctll::list<atomic_start, Ts...>(), pcre_parameters<Counter>()};
2215 : }
2216 :
2217 : // atomic
2218 : template <auto V, typename Atomic, typename... Ts, size_t Counter> static constexpr auto apply(pcre::make_atomic, ctll::term<V>, pcre_context<ctll::list<Atomic, atomic_start, Ts...>, pcre_parameters<Counter>>) {
2219 : return pcre_context{ctll::list<atomic_group<Atomic>, Ts...>(), pcre_parameters<Counter>()};
2220 : }
2221 :
2222 : // atomic sequence
2223 : template <auto V, typename... Atomic, typename... Ts, size_t Counter> static constexpr auto apply(pcre::make_atomic, ctll::term<V>, pcre_context<ctll::list<sequence<Atomic...>, atomic_start, Ts...>, pcre_parameters<Counter>>) {
2224 : return pcre_context{ctll::list<atomic_group<Atomic...>, Ts...>(), pcre_parameters<Counter>()};
2225 : }
2226 :
2227 : #endif
2228 :
2229 : #ifndef CTRE__ACTIONS__BACKREFERENCE__HPP
2230 : #define CTRE__ACTIONS__BACKREFERENCE__HPP
2231 :
2232 : // backreference with name
2233 : template <auto... Str, auto V, typename... Ts, size_t Counter> static constexpr auto apply(pcre::make_back_reference, ctll::term<V>, pcre_context<ctll::list<id<Str...>, Ts...>, pcre_parameters<Counter>>) {
2234 : return pcre_context{ctll::push_front(back_reference_with_name<id<Str...>>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
2235 : }
2236 :
2237 : // with just a number
2238 : template <auto V, size_t Id, typename... Ts, size_t Counter> static constexpr auto apply(pcre::make_back_reference, ctll::term<V>, pcre_context<ctll::list<number<Id>, Ts...>, pcre_parameters<Counter>>) {
2239 : // if we are looking outside of existing list of Ids ... reject input during parsing
2240 : if constexpr (Counter < Id) {
2241 : return ctll::reject{};
2242 : } else {
2243 : return pcre_context{ctll::push_front(back_reference<Id>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
2244 : }
2245 : }
2246 :
2247 : // relative backreference
2248 : template <auto V, size_t Id, typename... Ts, size_t Counter> static constexpr auto apply(pcre::make_relative_back_reference, ctll::term<V>, [[maybe_unused]] pcre_context<ctll::list<number<Id>, Ts...>, pcre_parameters<Counter>>) {
2249 : // if we are looking outside of existing list of Ids ... reject input during parsing
2250 : if constexpr (Counter < Id) {
2251 : return ctll::reject{};
2252 : } else {
2253 : constexpr size_t absolute_id = (Counter + 1) - Id;
2254 : return pcre_context{ctll::push_front(back_reference<absolute_id>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
2255 : }
2256 : }
2257 :
2258 : #endif
2259 :
2260 : #ifndef CTRE__ACTIONS__BOUNDARIES__HPP
2261 : #define CTRE__ACTIONS__BOUNDARIES__HPP
2262 :
2263 : // push_word_boundary
2264 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_word_boundary, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2265 : return pcre_context{ctll::push_front(boundary<word_chars>(), subject.stack), subject.parameters};
2266 : }
2267 :
2268 : // push_not_word_boundary
2269 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_not_word_boundary, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2270 : return pcre_context{ctll::push_front(boundary<negative_set<word_chars>>(), subject.stack), subject.parameters};
2271 : }
2272 :
2273 : #endif
2274 :
2275 : #ifndef CTRE__ACTIONS__CAPTURE__HPP
2276 : #define CTRE__ACTIONS__CAPTURE__HPP
2277 :
2278 : // prepare_capture
2279 : template <auto V, typename... Ts, size_t Counter> static constexpr auto apply(pcre::prepare_capture, ctll::term<V>, pcre_context<ctll::list<Ts...>, pcre_parameters<Counter>>) {
2280 : return pcre_context{ctll::push_front(capture_id<Counter+1>(), ctll::list<Ts...>()), pcre_parameters<Counter+1>()};
2281 : }
2282 :
2283 : // reset_capture
2284 : template <auto V, typename... Ts, size_t Id, size_t Counter> static constexpr auto apply(pcre::reset_capture, ctll::term<V>, pcre_context<ctll::list<capture_id<Id>, Ts...>, pcre_parameters<Counter>>) {
2285 : return pcre_context{ctll::list<Ts...>(), pcre_parameters<Counter-1>()};
2286 : }
2287 :
2288 : // capture
2289 : template <auto V, typename A, size_t Id, typename... Ts, size_t Counter> static constexpr auto apply(pcre::make_capture, ctll::term<V>, pcre_context<ctll::list<A, capture_id<Id>, Ts...>, pcre_parameters<Counter>>) {
2290 : return pcre_context{ctll::push_front(capture<Id, A>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
2291 : }
2292 : // capture (sequence)
2293 : template <auto V, typename... Content, size_t Id, typename... Ts, size_t Counter> static constexpr auto apply(pcre::make_capture, ctll::term<V>, pcre_context<ctll::list<sequence<Content...>, capture_id<Id>, Ts...>, pcre_parameters<Counter>>) {
2294 : return pcre_context{ctll::push_front(capture<Id, Content...>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
2295 : }
2296 : // push_name
2297 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_name, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2298 : return pcre_context{ctll::push_front(id<V>(), subject.stack), subject.parameters};
2299 : }
2300 : // push_name (concat)
2301 : template <auto... Str, auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_name, ctll::term<V>, pcre_context<ctll::list<id<Str...>, Ts...>, Parameters> subject) {
2302 : return pcre_context{ctll::push_front(id<Str..., V>(), ctll::list<Ts...>()), subject.parameters};
2303 : }
2304 : // capture with name
2305 : template <auto... Str, auto V, typename A, size_t Id, typename... Ts, size_t Counter> static constexpr auto apply(pcre::make_capture_with_name, ctll::term<V>, pcre_context<ctll::list<A, id<Str...>, capture_id<Id>, Ts...>, pcre_parameters<Counter>>) {
2306 : return pcre_context{ctll::push_front(capture_with_name<Id, id<Str...>, A>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
2307 : }
2308 : // capture with name (sequence)
2309 : template <auto... Str, auto V, typename... Content, size_t Id, typename... Ts, size_t Counter> static constexpr auto apply(pcre::make_capture_with_name, ctll::term<V>, pcre_context<ctll::list<sequence<Content...>, id<Str...>, capture_id<Id>, Ts...>, pcre_parameters<Counter>>) {
2310 : return pcre_context{ctll::push_front(capture_with_name<Id, id<Str...>, Content...>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
2311 : }
2312 :
2313 : #endif
2314 :
2315 : #ifndef CTRE__ACTIONS__CHARACTERS__HPP
2316 : #define CTRE__ACTIONS__CHARACTERS__HPP
2317 :
2318 : // push character
2319 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_character, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2320 : return pcre_context{ctll::push_front(character<V>(), subject.stack), subject.parameters};
2321 : }
2322 : // push_any_character
2323 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_character_anything, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2324 : return pcre_context{ctll::push_front(any(), subject.stack), subject.parameters};
2325 : }
2326 : // character_alarm
2327 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_character_alarm, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2328 : return pcre_context{ctll::push_front(character<'\x07'>(), subject.stack), subject.parameters};
2329 : }
2330 : // character_escape
2331 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_character_escape, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2332 : return pcre_context{ctll::push_front(character<'\x14'>(), subject.stack), subject.parameters};
2333 : }
2334 : // character_formfeed
2335 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_character_formfeed, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2336 : return pcre_context{ctll::push_front(character<'\x0C'>(), subject.stack), subject.parameters};
2337 : }
2338 : // push_character_newline
2339 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_character_newline, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2340 : return pcre_context{ctll::push_front(character<'\x0A'>(), subject.stack), subject.parameters};
2341 : }
2342 : // push_character_null
2343 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_character_null, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2344 : return pcre_context{ctll::push_front(character<'\0'>(), subject.stack), subject.parameters};
2345 : }
2346 : // push_character_return_carriage
2347 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_character_return_carriage, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2348 : return pcre_context{ctll::push_front(character<'\x0D'>(), subject.stack), subject.parameters};
2349 : }
2350 : // push_character_tab
2351 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_character_tab, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2352 : return pcre_context{ctll::push_front(character<'\x09'>(), subject.stack), subject.parameters};
2353 : }
2354 :
2355 : #endif
2356 :
2357 : #ifndef CTRE__ACTIONS__CLASS__HPP
2358 : #define CTRE__ACTIONS__CLASS__HPP
2359 :
2360 : // class_digit
2361 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_digit, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2362 : return pcre_context{ctll::push_front(ctre::set<ctre::digit_chars>(), subject.stack), subject.parameters};
2363 : }
2364 : // class_non_digit
2365 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_nondigit, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2366 : return pcre_context{ctll::push_front(ctre::negative_set<ctre::digit_chars>(), subject.stack), subject.parameters};
2367 : }
2368 : // class_space
2369 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_space, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2370 : return pcre_context{ctll::push_front(ctre::set<ctre::space_chars>(), subject.stack), subject.parameters};
2371 : }
2372 : // class_nonspace
2373 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_nonspace, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2374 : return pcre_context{ctll::push_front(ctre::negative_set<ctre::space_chars>(), subject.stack), subject.parameters};
2375 : }
2376 :
2377 : // class_horizontal_space
2378 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_horizontal_space, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2379 : return pcre_context{ctll::push_front(ctre::set<ctre::horizontal_space_chars>(), subject.stack), subject.parameters};
2380 : }
2381 : // class_horizontal_nonspace
2382 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_non_horizontal_space, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2383 : return pcre_context{ctll::push_front(ctre::negative_set<ctre::horizontal_space_chars>(), subject.stack), subject.parameters};
2384 : }
2385 : // class_vertical_space
2386 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_vertical_space, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2387 : return pcre_context{ctll::push_front(ctre::set<ctre::vertical_space_chars>(), subject.stack), subject.parameters};
2388 : }
2389 : // class_vertical_nonspace
2390 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_non_vertical_space, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2391 : return pcre_context{ctll::push_front(ctre::negative_set<ctre::vertical_space_chars>(), subject.stack), subject.parameters};
2392 : }
2393 :
2394 : // class_word
2395 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_word, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2396 : return pcre_context{ctll::push_front(ctre::set<ctre::word_chars>(), subject.stack), subject.parameters};
2397 : }
2398 : // class_nonword
2399 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_nonword, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2400 : return pcre_context{ctll::push_front(ctre::negative_set<ctre::word_chars>(), subject.stack), subject.parameters};
2401 : }
2402 : // class_nonnewline
2403 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_nonnewline, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2404 : return pcre_context{ctll::push_front(ctre::negative_set<character<'\n'>>(), subject.stack), subject.parameters};
2405 : }
2406 :
2407 : #endif
2408 :
2409 : #ifndef CTRE__ACTIONS__FUSION__HPP
2410 : #define CTRE__ACTIONS__FUSION__HPP
2411 :
2412 : static constexpr size_t combine_max_repeat_length(size_t A, size_t B) {
2413 : if (A && B) return A+B;
2414 : else return 0;
2415 : }
2416 :
2417 : template <size_t MinA, size_t MaxA, size_t MinB, size_t MaxB, typename... Content> static constexpr auto combine_repeat(repeat<MinA, MaxA, Content...>, repeat<MinB, MaxB, Content...>) {
2418 : return repeat<MinA + MinB, combine_max_repeat_length(MaxA, MaxB), Content...>();
2419 : }
2420 :
2421 : template <size_t MinA, size_t MaxA, size_t MinB, size_t MaxB, typename... Content> static constexpr auto combine_repeat(lazy_repeat<MinA, MaxA, Content...>, lazy_repeat<MinB, MaxB, Content...>) {
2422 : return lazy_repeat<MinA + MinB, combine_max_repeat_length(MaxA, MaxB), Content...>();
2423 : }
2424 :
2425 : template <size_t MinA, size_t MaxA, size_t MinB, size_t MaxB, typename... Content> static constexpr auto combine_repeat(possessive_repeat<MinA, MaxA, Content...>, possessive_repeat<MinB, MaxB, Content...>) {
2426 : [[maybe_unused]] constexpr bool first_is_unbounded = (MaxA == 0);
2427 : [[maybe_unused]] constexpr bool second_is_nonempty = (MinB > 0);
2428 : [[maybe_unused]] constexpr bool second_can_be_empty = (MinB == 0);
2429 :
2430 : if constexpr (first_is_unbounded && second_is_nonempty) {
2431 : // will always reject, but I keep the content, so I have some amount of captures
2432 : return sequence<reject, Content...>();
2433 : } else if constexpr (first_is_unbounded) {
2434 : return possessive_repeat<MinA, MaxA, Content...>();
2435 : } else if constexpr (second_can_be_empty) {
2436 : return possessive_repeat<MinA, combine_max_repeat_length(MaxA, MaxB), Content...>();
2437 : } else {
2438 : return possessive_repeat<MaxA + MinB, combine_max_repeat_length(MaxA, MaxB), Content...>();
2439 : }
2440 : }
2441 :
2442 : // concat repeat sequences
2443 : template <auto V, size_t MinA, size_t MaxA, size_t MinB, size_t MaxB, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<repeat<MinB, MaxB, Content...>, repeat<MinA, MaxA, Content...>, Ts...>, Parameters> subject) {
2444 : return pcre_context{ctll::push_front(combine_repeat(repeat<MinA, MaxA, Content...>(), repeat<MinB, MaxB, Content...>()), ctll::list<Ts...>()), subject.parameters};
2445 : }
2446 :
2447 : // concat lazy repeat sequences
2448 : template <auto V, size_t MinA, size_t MaxA, size_t MinB, size_t MaxB, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<lazy_repeat<MinB, MaxB, Content...>, lazy_repeat<MinA, MaxA, Content...>, Ts...>, Parameters> subject) {
2449 : return pcre_context{ctll::push_front(combine_repeat(lazy_repeat<MinA, MaxA, Content...>(), lazy_repeat<MinB, MaxB, Content...>()), ctll::list<Ts...>()), subject.parameters};
2450 : }
2451 :
2452 : // concat possessive repeat seqeunces
2453 : template <auto V, size_t MinA, size_t MaxA, size_t MinB, size_t MaxB, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<possessive_repeat<MinB, MaxB, Content...>, possessive_repeat<MinA, MaxA, Content...>, Ts...>, Parameters> subject) {
2454 : return pcre_context{ctll::push_front(combine_repeat(possessive_repeat<MinA, MaxA, Content...>(), possessive_repeat<MinB, MaxB, Content...>()), ctll::list<Ts...>()), subject.parameters};
2455 : }
2456 :
2457 : // concat repeat sequences into sequence
2458 : template <auto V, size_t MinA, size_t MaxA, size_t MinB, size_t MaxB, typename... Content, typename... As, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<sequence<repeat<MinB, MaxB, Content...>, As...>,repeat<MinA, MaxA, Content...>,Ts...>, Parameters> subject) {
2459 : using result = decltype(combine_repeat(repeat<MinB, MaxB, Content...>(), repeat<MinA, MaxA, Content...>()));
2460 :
2461 : return pcre_context{ctll::push_front(sequence<result,As...>(), ctll::list<Ts...>()), subject.parameters};
2462 : }
2463 :
2464 : // concat lazy repeat sequences into sequence
2465 : template <auto V, size_t MinA, size_t MaxA, size_t MinB, size_t MaxB, typename... Content, typename... As, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<sequence<lazy_repeat<MinB, MaxB, Content...>, As...>,lazy_repeat<MinA, MaxA, Content...>,Ts...>, Parameters> subject) {
2466 : using result = decltype(combine_repeat(lazy_repeat<MinB, MaxB, Content...>(), lazy_repeat<MinA, MaxA, Content...>()));
2467 :
2468 : return pcre_context{ctll::push_front(sequence<result,As...>(), ctll::list<Ts...>()), subject.parameters};
2469 : }
2470 :
2471 : // concat possessive repeat sequences into sequence
2472 : template <auto V, size_t MinA, size_t MaxA, size_t MinB, size_t MaxB, typename... Content, typename... As, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<sequence<possessive_repeat<MinB, MaxB, Content...>, As...>,possessive_repeat<MinA, MaxA, Content...>,Ts...>, Parameters> subject) {
2473 : using result = decltype(combine_repeat(possessive_repeat<MinB, MaxB, Content...>(), possessive_repeat<MinA, MaxA, Content...>()));
2474 :
2475 : return pcre_context{ctll::push_front(sequence<result,As...>(), ctll::list<Ts...>()), subject.parameters};
2476 : }
2477 :
2478 : #endif
2479 :
2480 : #ifndef CTRE__ACTIONS__HEXDEC__HPP
2481 : #define CTRE__ACTIONS__HEXDEC__HPP
2482 :
2483 : // hexdec character support (seed)
2484 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::create_hexdec, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2485 : return pcre_context{ctll::push_front(number<0ull>(), subject.stack), subject.parameters};
2486 : }
2487 : // hexdec character support (push value)
2488 : template <auto V, size_t N, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_hexdec, ctll::term<V>, pcre_context<ctll::list<number<N>, Ts...>, Parameters> subject) {
2489 : constexpr auto previous = N << 4ull;
2490 : if constexpr (V >= 'a' && V <= 'f') {
2491 : return pcre_context{ctll::push_front(number<(previous + (V - 'a' + 10))>(), ctll::list<Ts...>()), subject.parameters};
2492 : } else if constexpr (V >= 'A' && V <= 'F') {
2493 : return pcre_context{ctll::push_front(number<(previous + (V - 'A' + 10))>(), ctll::list<Ts...>()), subject.parameters};
2494 : } else {
2495 : return pcre_context{ctll::push_front(number<(previous + (V - '0'))>(), ctll::list<Ts...>()), subject.parameters};
2496 : }
2497 : }
2498 : // hexdec character support (convert to character)
2499 : template <auto V, size_t N, typename... Ts, typename Parameters> static constexpr auto apply(pcre::finish_hexdec, ctll::term<V>, pcre_context<ctll::list<number<N>, Ts...>, Parameters> subject) {
2500 : constexpr size_t max_char = (std::numeric_limits<char>::max)();
2501 : if constexpr (N <= max_char) {
2502 : return pcre_context{ctll::push_front(character<char{N}>(), ctll::list<Ts...>()), subject.parameters};
2503 : } else {
2504 : return pcre_context{ctll::push_front(character<char32_t{N}>(), ctll::list<Ts...>()), subject.parameters};
2505 : }
2506 : }
2507 :
2508 : #endif
2509 :
2510 : #ifndef CTRE__ACTIONS__LOOKAHEAD__HPP
2511 : #define CTRE__ACTIONS__LOOKAHEAD__HPP
2512 :
2513 : // lookahead positive start
2514 : template <auto V, typename... Ts, size_t Counter> static constexpr auto apply(pcre::start_lookahead_positive, ctll::term<V>, pcre_context<ctll::list<Ts...>, pcre_parameters<Counter>>) {
2515 : return pcre_context{ctll::list<look_start<lookahead_positive<>>, Ts...>(), pcre_parameters<Counter>()};
2516 : }
2517 :
2518 : // lookahead positive end
2519 : template <auto V, typename Look, typename... Ts, size_t Counter> static constexpr auto apply(pcre::look_finish, ctll::term<V>, pcre_context<ctll::list<Look, look_start<lookahead_positive<>>, Ts...>, pcre_parameters<Counter>>) {
2520 : return pcre_context{ctll::list<lookahead_positive<Look>, Ts...>(), pcre_parameters<Counter>()};
2521 : }
2522 :
2523 : // lookahead positive end (sequence)
2524 : template <auto V, typename... Look, typename... Ts, size_t Counter> static constexpr auto apply(pcre::look_finish, ctll::term<V>, pcre_context<ctll::list<ctre::sequence<Look...>, look_start<lookahead_positive<>>, Ts...>, pcre_parameters<Counter>>) {
2525 : return pcre_context{ctll::list<lookahead_positive<Look...>, Ts...>(), pcre_parameters<Counter>()};
2526 : }
2527 :
2528 : // lookahead negative start
2529 : template <auto V, typename... Ts, size_t Counter> static constexpr auto apply(pcre::start_lookahead_negative, ctll::term<V>, pcre_context<ctll::list<Ts...>, pcre_parameters<Counter>>) {
2530 : return pcre_context{ctll::list<look_start<lookahead_negative<>>, Ts...>(), pcre_parameters<Counter>()};
2531 : }
2532 :
2533 : // lookahead negative end
2534 : template <auto V, typename Look, typename... Ts, size_t Counter> static constexpr auto apply(pcre::look_finish, ctll::term<V>, pcre_context<ctll::list<Look, look_start<lookahead_negative<>>, Ts...>, pcre_parameters<Counter>>) {
2535 : return pcre_context{ctll::list<lookahead_negative<Look>, Ts...>(), pcre_parameters<Counter>()};
2536 : }
2537 :
2538 : // lookahead negative end (sequence)
2539 : template <auto V, typename... Look, typename... Ts, size_t Counter> static constexpr auto apply(pcre::look_finish, ctll::term<V>, pcre_context<ctll::list<ctre::sequence<Look...>, look_start<lookahead_negative<>>, Ts...>, pcre_parameters<Counter>>) {
2540 : return pcre_context{ctll::list<lookahead_negative<Look...>, Ts...>(), pcre_parameters<Counter>()};
2541 : }
2542 :
2543 : // LOOKBEHIND
2544 :
2545 : // lookbehind positive start
2546 : template <auto V, typename... Ts, size_t Counter> static constexpr auto apply(pcre::start_lookbehind_positive, ctll::term<V>, pcre_context<ctll::list<Ts...>, pcre_parameters<Counter>>) {
2547 : return pcre_context{ctll::list<look_start<lookbehind_positive<>>, Ts...>(), pcre_parameters<Counter>()};
2548 : }
2549 :
2550 : // lookbehind positive end
2551 : template <auto V, typename Look, typename... Ts, size_t Counter> static constexpr auto apply(pcre::look_finish, ctll::term<V>, pcre_context<ctll::list<Look, look_start<lookbehind_positive<>>, Ts...>, pcre_parameters<Counter>>) {
2552 : return pcre_context{ctll::list<lookbehind_positive<decltype(ctre::rotate_for_lookbehind::rotate(Look{}))>, Ts...>(), pcre_parameters<Counter>()};
2553 : }
2554 :
2555 : // lookbehind positive end (sequence)
2556 : template <auto V, typename... Look, typename... Ts, size_t Counter> static constexpr auto apply(pcre::look_finish, ctll::term<V>, pcre_context<ctll::list<ctre::sequence<Look...>, look_start<lookbehind_positive<>>, Ts...>, pcre_parameters<Counter>>) {
2557 : using my_lookbehind = decltype(ctre::convert_to_basic_list<lookbehind_positive>(ctll::rotate(ctll::list<decltype(ctre::rotate_for_lookbehind::rotate(Look{}))...>{})));
2558 : return pcre_context{ctll::list<my_lookbehind, Ts...>(), pcre_parameters<Counter>()};
2559 : }
2560 :
2561 : // lookbehind negative start
2562 : template <auto V, typename... Ts, size_t Counter> static constexpr auto apply(pcre::start_lookbehind_negative, ctll::term<V>, pcre_context<ctll::list<Ts...>, pcre_parameters<Counter>>) {
2563 : return pcre_context{ctll::list<look_start<lookbehind_negative<>>, Ts...>(), pcre_parameters<Counter>()};
2564 : }
2565 :
2566 : // lookbehind negative end
2567 : template <auto V, typename Look, typename... Ts, size_t Counter> static constexpr auto apply(pcre::look_finish, ctll::term<V>, pcre_context<ctll::list<Look, look_start<lookbehind_negative<>>, Ts...>, pcre_parameters<Counter>>) {
2568 : return pcre_context{ctll::list<lookbehind_negative<decltype(ctre::rotate_for_lookbehind::rotate(Look{}))>, Ts...>(), pcre_parameters<Counter>()};
2569 : }
2570 :
2571 : // lookbehind negative end (sequence)
2572 : template <auto V, typename... Look, typename... Ts, size_t Counter> static constexpr auto apply(pcre::look_finish, ctll::term<V>, pcre_context<ctll::list<ctre::sequence<Look...>, look_start<lookbehind_negative<>>, Ts...>, pcre_parameters<Counter>>) {
2573 : using my_lookbehind = decltype(ctre::convert_to_basic_list<lookbehind_negative>(ctll::rotate(ctll::list<decltype(ctre::rotate_for_lookbehind::rotate(Look{}))...>{})));
2574 : return pcre_context{ctll::list<my_lookbehind, Ts...>(), pcre_parameters<Counter>()};
2575 : }
2576 :
2577 : #endif
2578 :
2579 : #ifndef CTRE__ACTIONS__NAMED_CLASS__HPP
2580 : #define CTRE__ACTIONS__NAMED_CLASS__HPP
2581 :
2582 : // class_named_alnum
2583 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_alnum, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2584 : return pcre_context{ctll::push_front(ctre::alphanum_chars(), subject.stack), subject.parameters};
2585 : }
2586 : // class_named_alpha
2587 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_alpha, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2588 : return pcre_context{ctll::push_front(ctre::alpha_chars(), subject.stack), subject.parameters};
2589 : }
2590 : // class_named_digit
2591 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_digit, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2592 : return pcre_context{ctll::push_front(ctre::digit_chars(), subject.stack), subject.parameters};
2593 : }
2594 : // class_named_ascii
2595 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_ascii, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2596 : return pcre_context{ctll::push_front(ctre::ascii_chars(), subject.stack), subject.parameters};
2597 : }
2598 : // class_named_blank
2599 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_blank, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2600 : return pcre_context{ctll::push_front(ctre::enumeration<' ','\t'>(), subject.stack), subject.parameters};
2601 : }
2602 : // class_named_cntrl
2603 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_cntrl, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2604 : return pcre_context{ctll::push_front(ctre::set<ctre::char_range<'\x00','\x1F'>, ctre::character<'\x7F'>>(), subject.stack), subject.parameters};
2605 : }
2606 : // class_named_graph
2607 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_graph, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2608 : return pcre_context{ctll::push_front(ctre::char_range<'\x21','\x7E'>(), subject.stack), subject.parameters};
2609 : }
2610 : // class_named_lower
2611 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_lower, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2612 : return pcre_context{ctll::push_front(ctre::char_range<'a','z'>(), subject.stack), subject.parameters};
2613 : }
2614 : // class_named_upper
2615 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_upper, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2616 : return pcre_context{ctll::push_front(ctre::char_range<'A','Z'>(), subject.stack), subject.parameters};
2617 : }
2618 : // class_named_print
2619 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_print, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2620 : return pcre_context{ctll::push_front(ctre::char_range<'\x20','\x7E'>(), subject.stack), subject.parameters};
2621 : }
2622 : // class_named_space
2623 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_space, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2624 : return pcre_context{ctll::push_front(space_chars(), subject.stack), subject.parameters};
2625 : }
2626 : // class_named_word
2627 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_word, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2628 : return pcre_context{ctll::push_front(word_chars(), subject.stack), subject.parameters};
2629 : }
2630 : // class_named_punct
2631 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_punct, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2632 : return pcre_context{ctll::push_front(punct_chars(), subject.stack), subject.parameters};
2633 : }
2634 : // class_named_xdigit
2635 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_named_xdigit, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2636 : return pcre_context{ctll::push_front(xdigit_chars(), subject.stack), subject.parameters};
2637 : }
2638 :
2639 : #endif
2640 :
2641 : #ifndef CTRE__ACTIONS__OPTIONS__HPP
2642 : #define CTRE__ACTIONS__OPTIONS__HPP
2643 :
2644 : // empty option for alternate
2645 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_empty, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2646 : return pcre_context{ctll::push_front(empty(), subject.stack), subject.parameters};
2647 : }
2648 :
2649 : // empty option for empty regex
2650 : template <typename Parameters> static constexpr auto apply(pcre::push_empty, ctll::epsilon, pcre_context<ctll::list<>, Parameters> subject) {
2651 : return pcre_context{ctll::push_front(empty(), subject.stack), subject.parameters};
2652 : }
2653 :
2654 : // make_alternate (A|B)
2655 : template <auto V, typename A, typename B, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_alternate, ctll::term<V>, pcre_context<ctll::list<B, A, Ts...>, Parameters> subject) {
2656 : return pcre_context{ctll::push_front(select<A,B>(), ctll::list<Ts...>()), subject.parameters};
2657 : }
2658 : // make_alternate (As..)|B => (As..|B)
2659 : template <auto V, typename A, typename... Bs, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_alternate, ctll::term<V>, pcre_context<ctll::list<ctre::select<Bs...>, A, Ts...>, Parameters> subject) {
2660 : return pcre_context{ctll::push_front(select<A,Bs...>(), ctll::list<Ts...>()), subject.parameters};
2661 : }
2662 :
2663 : // make_optional
2664 : template <auto V, typename A, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_optional, ctll::term<V>, pcre_context<ctll::list<A, Ts...>, Parameters> subject) {
2665 : return pcre_context{ctll::push_front(optional<A>(), ctll::list<Ts...>()), subject.parameters};
2666 : }
2667 :
2668 : template <auto V, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_optional, ctll::term<V>, pcre_context<ctll::list<sequence<Content...>, Ts...>, Parameters> subject) {
2669 : return pcre_context{ctll::push_front(optional<Content...>(), ctll::list<Ts...>()), subject.parameters};
2670 : }
2671 :
2672 : // prevent from creating wrapped optionals
2673 : template <auto V, typename A, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_optional, ctll::term<V>, pcre_context<ctll::list<optional<A>, Ts...>, Parameters> subject) {
2674 : return pcre_context{ctll::push_front(optional<A>(), ctll::list<Ts...>()), subject.parameters};
2675 : }
2676 :
2677 : // in case inner optional is lazy, result should be lazy too
2678 : template <auto V, typename A, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_optional, ctll::term<V>, pcre_context<ctll::list<lazy_optional<A>, Ts...>, Parameters> subject) {
2679 : return pcre_context{ctll::push_front(lazy_optional<A>(), ctll::list<Ts...>()), subject.parameters};
2680 : }
2681 :
2682 : // make_lazy (optional)
2683 : template <auto V, typename... Subject, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_lazy, ctll::term<V>, pcre_context<ctll::list<optional<Subject...>, Ts...>, Parameters> subject) {
2684 : return pcre_context{ctll::push_front(lazy_optional<Subject...>(), ctll::list<Ts...>()), subject.parameters};
2685 : }
2686 :
2687 : // if you already got a lazy optional, make_lazy is no-op
2688 : template <auto V, typename... Subject, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_lazy, ctll::term<V>, pcre_context<ctll::list<lazy_optional<Subject...>, Ts...>, Parameters> subject) {
2689 : return pcre_context{ctll::push_front(lazy_optional<Subject...>(), ctll::list<Ts...>()), subject.parameters};
2690 : }
2691 :
2692 : #endif
2693 :
2694 : #ifndef CTRE__ACTIONS__PROPERTIES__HPP
2695 : #define CTRE__ACTIONS__PROPERTIES__HPP
2696 :
2697 : // push_property_name
2698 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_property_name, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2699 : return pcre_context{ctll::push_front(property_name<V>(), subject.stack), subject.parameters};
2700 : }
2701 : // push_property_name (concat)
2702 : template <auto... Str, auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_property_name, ctll::term<V>, pcre_context<ctll::list<property_name<Str...>, Ts...>, Parameters> subject) {
2703 : return pcre_context{ctll::push_front(property_name<Str..., V>(), ctll::list<Ts...>()), subject.parameters};
2704 : }
2705 :
2706 : // push_property_value
2707 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_property_value, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2708 : return pcre_context{ctll::push_front(property_value<V>(), subject.stack), subject.parameters};
2709 : }
2710 : // push_property_value (concat)
2711 : template <auto... Str, auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_property_value, ctll::term<V>, pcre_context<ctll::list<property_value<Str...>, Ts...>, Parameters> subject) {
2712 : return pcre_context{ctll::push_front(property_value<Str..., V>(), ctll::list<Ts...>()), subject.parameters};
2713 : }
2714 :
2715 : // make_property
2716 : template <auto V, auto... Name, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_property, ctll::term<V>, [[maybe_unused]] pcre_context<ctll::list<property_name<Name...>, Ts...>, Parameters> subject) {
2717 : //return ctll::reject{};
2718 : constexpr char name[sizeof...(Name)]{static_cast<char>(Name)...};
2719 : constexpr auto p = uni::detail::binary_prop_from_string(get_string_view(name));
2720 :
2721 : if constexpr (uni::detail::is_unknown(p)) {
2722 : return ctll::reject{};
2723 : } else {
2724 : return pcre_context{ctll::push_front(make_binary_property<p>(), ctll::list<Ts...>()), subject.parameters};
2725 : }
2726 : }
2727 :
2728 : // make_property
2729 : template <auto V, auto... Value, auto... Name, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_property, ctll::term<V>, [[maybe_unused]] pcre_context<ctll::list<property_value<Value...>, property_name<Name...>, Ts...>, Parameters> subject) {
2730 : //return ctll::reject{};
2731 : constexpr auto prop = property_builder<Name...>::template get<Value...>();
2732 :
2733 : if constexpr (std::is_same_v<decltype(prop), ctll::reject>) {
2734 : return ctll::reject{};
2735 : } else {
2736 : return pcre_context{ctll::push_front(prop, ctll::list<Ts...>()), subject.parameters};
2737 : }
2738 : }
2739 :
2740 : // make_property_negative
2741 : template <auto V, auto... Name, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_property_negative, ctll::term<V>, [[maybe_unused]] pcre_context<ctll::list<property_name<Name...>, Ts...>, Parameters> subject) {
2742 : //return ctll::reject{};
2743 : constexpr char name[sizeof...(Name)]{static_cast<char>(Name)...};
2744 : constexpr auto p = uni::detail::binary_prop_from_string(get_string_view(name));
2745 :
2746 : if constexpr (uni::detail::is_unknown(p)) {
2747 : return ctll::reject{};
2748 : } else {
2749 : return pcre_context{ctll::push_front(negate<make_binary_property<p>>(), ctll::list<Ts...>()), subject.parameters};
2750 : }
2751 : }
2752 :
2753 : // make_property_negative
2754 : template <auto V, auto... Value, auto... Name, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_property_negative, ctll::term<V>, [[maybe_unused]] pcre_context<ctll::list<property_value<Value...>, property_name<Name...>, Ts...>, Parameters> subject) {
2755 : //return ctll::reject{};
2756 : constexpr auto prop = property_builder<Name...>::template get<Value...>();
2757 :
2758 : if constexpr (std::is_same_v<decltype(prop), ctll::reject>) {
2759 : return ctll::reject{};
2760 : } else {
2761 : return pcre_context{ctll::push_front(negate<decltype(prop)>(), ctll::list<Ts...>()), subject.parameters};
2762 : }
2763 : }
2764 :
2765 : #endif
2766 :
2767 : #ifndef CTRE__ACTIONS__REPEAT__HPP
2768 : #define CTRE__ACTIONS__REPEAT__HPP
2769 :
2770 : // repeat 1..N
2771 : template <auto V, typename A, typename... Ts, typename Parameters> static constexpr auto apply(pcre::repeat_plus, ctll::term<V>, pcre_context<ctll::list<A, Ts...>, Parameters> subject) {
2772 : return pcre_context{ctll::push_front(plus<A>(), ctll::list<Ts...>()), subject.parameters};
2773 : }
2774 : // repeat 1..N (sequence)
2775 : template <auto V, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::repeat_plus, ctll::term<V>, pcre_context<ctll::list<sequence<Content...>, Ts...>, Parameters> subject) {
2776 : return pcre_context{ctll::push_front(plus<Content...>(), ctll::list<Ts...>()), subject.parameters};
2777 : }
2778 :
2779 : // repeat 0..N
2780 : template <auto V, typename A, typename... Ts, typename Parameters> static constexpr auto apply(pcre::repeat_star, ctll::term<V>, pcre_context<ctll::list<A, Ts...>, Parameters> subject) {
2781 : return pcre_context{ctll::push_front(star<A>(), ctll::list<Ts...>()), subject.parameters};
2782 : }
2783 : // repeat 0..N (sequence)
2784 : template <auto V, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::repeat_star, ctll::term<V>, pcre_context<ctll::list<sequence<Content...>, Ts...>, Parameters> subject) {
2785 : return pcre_context{ctll::push_front(star<Content...>(), ctll::list<Ts...>()), subject.parameters};
2786 : }
2787 :
2788 : // create_number (seed)
2789 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::create_number, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2790 : return pcre_context{ctll::push_front(number<static_cast<size_t>(V - '0')>(), subject.stack), subject.parameters};
2791 : }
2792 : // push_number
2793 : template <auto V, size_t N, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_number, ctll::term<V>, pcre_context<ctll::list<number<N>, Ts...>, Parameters> subject) {
2794 : constexpr size_t previous = N * 10ull;
2795 : return pcre_context{ctll::push_front(number<(previous + (V - '0'))>(), ctll::list<Ts...>()), subject.parameters};
2796 : }
2797 :
2798 : // repeat A..B
2799 : template <auto V, typename Subject, size_t A, size_t B, typename... Ts, typename Parameters> static constexpr auto apply(pcre::repeat_ab, ctll::term<V>, pcre_context<ctll::list<number<B>, number<A>, Subject, Ts...>, Parameters> subject) {
2800 : return pcre_context{ctll::push_front(repeat<A,B,Subject>(), ctll::list<Ts...>()), subject.parameters};
2801 : }
2802 : // repeat A..B (sequence)
2803 : template <auto V, typename... Content, size_t A, size_t B, typename... Ts, typename Parameters> static constexpr auto apply(pcre::repeat_ab, ctll::term<V>, pcre_context<ctll::list<number<B>, number<A>, sequence<Content...>, Ts...>, Parameters> subject) {
2804 : return pcre_context{ctll::push_front(repeat<A,B,Content...>(), ctll::list<Ts...>()), subject.parameters};
2805 : }
2806 :
2807 : // repeat_exactly
2808 : template <auto V, typename Subject, size_t A, typename... Ts, typename Parameters> static constexpr auto apply(pcre::repeat_exactly, ctll::term<V>, pcre_context<ctll::list<number<A>, Subject, Ts...>, Parameters> subject) {
2809 : return pcre_context{ctll::push_front(repeat<A,A,Subject>(), ctll::list<Ts...>()), subject.parameters};
2810 : }
2811 : // repeat_exactly A..B (sequence)
2812 : template <auto V, typename... Content, size_t A, typename... Ts, typename Parameters> static constexpr auto apply(pcre::repeat_exactly, ctll::term<V>, pcre_context<ctll::list<number<A>, sequence<Content...>, Ts...>, Parameters> subject) {
2813 : return pcre_context{ctll::push_front(repeat<A,A,Content...>(), ctll::list<Ts...>()), subject.parameters};
2814 : }
2815 :
2816 : // repeat_at_least (A+)
2817 : template <auto V, typename Subject, size_t A, typename... Ts, typename Parameters> static constexpr auto apply(pcre::repeat_at_least, ctll::term<V>, pcre_context<ctll::list<number<A>, Subject, Ts...>, Parameters> subject) {
2818 : return pcre_context{ctll::push_front(repeat<A,0,Subject>(), ctll::list<Ts...>()), subject.parameters};
2819 : }
2820 : // repeat_at_least (A+) (sequence)
2821 : template <auto V, typename... Content, size_t A, typename... Ts, typename Parameters> static constexpr auto apply(pcre::repeat_at_least, ctll::term<V>, pcre_context<ctll::list<number<A>, sequence<Content...>, Ts...>, Parameters> subject) {
2822 : return pcre_context{ctll::push_front(repeat<A,0,Content...>(), ctll::list<Ts...>()), subject.parameters};
2823 : }
2824 :
2825 : // make_lazy (plus)
2826 : template <auto V, typename... Subject, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_lazy, ctll::term<V>, pcre_context<ctll::list<plus<Subject...>, Ts...>, Parameters> subject) {
2827 : return pcre_context{ctll::push_front(lazy_plus<Subject...>(), ctll::list<Ts...>()), subject.parameters};
2828 : }
2829 :
2830 : // make_lazy (star)
2831 : template <auto V, typename... Subject, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_lazy, ctll::term<V>, pcre_context<ctll::list<star<Subject...>, Ts...>, Parameters> subject) {
2832 : return pcre_context{ctll::push_front(lazy_star<Subject...>(), ctll::list<Ts...>()), subject.parameters};
2833 : }
2834 :
2835 : // make_lazy (repeat<A,B>)
2836 : template <auto V, typename... Subject, size_t A, size_t B, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_lazy, ctll::term<V>, pcre_context<ctll::list<repeat<A,B,Subject...>, Ts...>, Parameters> subject) {
2837 : return pcre_context{ctll::push_front(lazy_repeat<A,B,Subject...>(), ctll::list<Ts...>()), subject.parameters};
2838 : }
2839 :
2840 : // make_possessive (plus)
2841 : template <auto V, typename... Subject, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_possessive, ctll::term<V>, pcre_context<ctll::list<plus<Subject...>, Ts...>, Parameters> subject) {
2842 : return pcre_context{ctll::push_front(possessive_plus<Subject...>(), ctll::list<Ts...>()), subject.parameters};
2843 : }
2844 :
2845 : // make_possessive (star)
2846 : template <auto V, typename... Subject, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_possessive, ctll::term<V>, pcre_context<ctll::list<star<Subject...>, Ts...>, Parameters> subject) {
2847 : return pcre_context{ctll::push_front(possessive_star<Subject...>(), ctll::list<Ts...>()), subject.parameters};
2848 : }
2849 :
2850 : // make_possessive (repeat<A,B>)
2851 : template <auto V, typename... Subject, size_t A, size_t B, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_possessive, ctll::term<V>, pcre_context<ctll::list<repeat<A,B,Subject...>, Ts...>, Parameters> subject) {
2852 : return pcre_context{ctll::push_front(possessive_repeat<A,B,Subject...>(), ctll::list<Ts...>()), subject.parameters};
2853 : }
2854 :
2855 : #endif
2856 :
2857 : #ifndef CTRE__ACTIONS__SEQUENCE__HPP
2858 : #define CTRE__ACTIONS__SEQUENCE__HPP
2859 :
2860 : // make_sequence
2861 : template <auto V, typename A, typename B, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<B,A,Ts...>, Parameters> subject) {
2862 : return pcre_context{ctll::push_front(sequence<A,B>(), ctll::list<Ts...>()), subject.parameters};
2863 : }
2864 : // make_sequence (concat)
2865 : template <auto V, typename A, typename... Bs, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<sequence<Bs...>,A,Ts...>, Parameters> subject) {
2866 : return pcre_context{ctll::push_front(sequence<A,Bs...>(), ctll::list<Ts...>()), subject.parameters};
2867 : }
2868 :
2869 : // make_sequence (make string)
2870 : template <auto V, auto A, auto B, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<character<B>,character<A>,Ts...>, Parameters> subject) {
2871 : return pcre_context{ctll::push_front(string<A,B>(), ctll::list<Ts...>()), subject.parameters};
2872 : }
2873 : // make_sequence (concat string)
2874 : template <auto V, auto A, auto... Bs, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<string<Bs...>,character<A>,Ts...>, Parameters> subject) {
2875 : return pcre_context{ctll::push_front(string<A,Bs...>(), ctll::list<Ts...>()), subject.parameters};
2876 : }
2877 :
2878 : // make_sequence (make string in front of different items)
2879 : template <auto V, auto A, auto B, typename... Sq, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<sequence<character<B>,Sq...>,character<A>,Ts...>, Parameters> subject) {
2880 : return pcre_context{ctll::push_front(sequence<string<A,B>,Sq...>(), ctll::list<Ts...>()), subject.parameters};
2881 : }
2882 : // make_sequence (concat string in front of different items)
2883 : template <auto V, auto A, auto... Bs, typename... Sq, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_sequence, ctll::term<V>, pcre_context<ctll::list<sequence<string<Bs...>,Sq...>,character<A>,Ts...>, Parameters> subject) {
2884 : return pcre_context{ctll::push_front(sequence<string<A,Bs...>,Sq...>(), ctll::list<Ts...>()), subject.parameters};
2885 : }
2886 :
2887 : #endif
2888 :
2889 : #ifndef CTRE__ACTIONS__SET__HPP
2890 : #define CTRE__ACTIONS__SET__HPP
2891 :
2892 : // UTILITY
2893 : // add into set if not exists
2894 : template <template <typename...> typename SetType, typename T, typename... As, bool Exists = (std::is_same_v<T, As> || ... || false)> static constexpr auto push_back_into_set(T, SetType<As...>) -> ctll::conditional<Exists, SetType<As...>, SetType<As...,T>> { return {}; }
2895 :
2896 : //template <template <typename...> typename SetType, typename A, typename BHead, typename... Bs> struct set_merge_helper {
2897 : // using step = decltype(push_back_into_set<SetType>(BHead(), A()));
2898 : // using type = ctll::conditional<(sizeof...(Bs) > 0), set_merge_helper<SetType, step, Bs...>, step>;
2899 : //};
2900 : //
2901 : //// add set into set if not exists
2902 : //template <template <typename...> typename SetType, typename... As, typename... Bs> static constexpr auto push_back_into_set(SetType<As...>, SetType<Bs...>) -> typename set_merge_helper<SetType, SetType<As...>, Bs...>::type { return pcre_context{{};), subject.parameters}}
2903 : //
2904 : //template <template <typename...> typename SetType, typename... As> static constexpr auto push_back_into_set(SetType<As...>, SetType<>) -> SetType<As...> { return pcre_context{{};), subject.parameters}}
2905 :
2906 : // END OF UTILITY
2907 :
2908 : // set_start
2909 : template <auto V, typename A,typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_start, ctll::term<V>, pcre_context<ctll::list<A,Ts...>, Parameters> subject) {
2910 : return pcre_context{ctll::push_front(set<A>(), ctll::list<Ts...>()), subject.parameters};
2911 : }
2912 :
2913 : // set_empty
2914 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_empty, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2915 : return pcre_context{ctll::push_front(set<>(), ctll::list<Ts...>()), subject.parameters};
2916 : }
2917 :
2918 : // set_make
2919 : template <auto V, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_make, ctll::term<V>, pcre_context<ctll::list<set<Content...>, Ts...>, Parameters> subject) {
2920 : return pcre_context{ctll::push_front(set<Content...>(), ctll::list<Ts...>()), subject.parameters};
2921 : }
2922 : // set_make_negative
2923 : template <auto V, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_make_negative, ctll::term<V>, pcre_context<ctll::list<set<Content...>, Ts...>, Parameters> subject) {
2924 : return pcre_context{ctll::push_front(negative_set<Content...>(), ctll::list<Ts...>()), subject.parameters};
2925 : }
2926 : // set{A...} + B = set{A,B}
2927 : template <auto V, typename A, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_combine, ctll::term<V>, pcre_context<ctll::list<A,set<Content...>,Ts...>, Parameters> subject) {
2928 : auto new_set = push_back_into_set<set>(A(), set<Content...>());
2929 : return pcre_context{ctll::push_front(new_set, ctll::list<Ts...>()), subject.parameters};
2930 : }
2931 : // TODO checkme
2932 : //// set{A...} + set{B...} = set{A...,B...}
2933 : //template <auto V, typename... As, typename... Bs, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_combine, ctll::term<V>, pcre_context<ctll::list<set<As...>,set<Bs...>,Ts...>, Parameters> subject) {
2934 : // auto new_set = push_back_into_set<set>(set<As...>(), set<Bs...>());
2935 : // return pcre_context{ctll::push_front(new_set, ctll::list<Ts...>()), subject.parameters};
2936 : //}
2937 :
2938 : // negative_set{A...} + B = negative_set{A,B}
2939 : template <auto V, typename A, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_combine, ctll::term<V>, pcre_context<ctll::list<A,negative_set<Content...>,Ts...>, Parameters> subject) {
2940 : auto new_set = push_back_into_set<set>(A(), set<Content...>());
2941 : return pcre_context{ctll::push_front(new_set, ctll::list<Ts...>()), subject.parameters};
2942 : }
2943 : // TODO checkme
2944 : //// negative_set{A...} + negative_set{B...} = negative_set{A...,B...}
2945 : //template <auto V, typename... As, typename... Bs, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_combine, ctll::term<V>, pcre_context<ctll::list<negative_set<As...>,negative_set<Bs...>,Ts...>, Parameters> subject) {
2946 : // auto new_set = push_back_into_set<negative_set>(negative_set<As...>(), negative_set<Bs...>());
2947 : // return pcre_context{ctll::push_front(new_set, ctll::list<Ts...>()), subject.parameters};
2948 : //}
2949 : // negate_class_named: [[^:digit:]] = [^[:digit:]]
2950 : template <auto V, typename A, typename... Ts, typename Parameters> static constexpr auto apply(pcre::negate_class_named, ctll::term<V>, pcre_context<ctll::list<A, Ts...>, Parameters> subject) {
2951 : return pcre_context{ctll::push_front(negate<A>(), ctll::list<Ts...>()), subject.parameters};
2952 : }
2953 :
2954 : // add range to set
2955 : template <auto V, auto B, auto A, typename... Ts, typename Parameters> static constexpr auto apply(pcre::make_range, ctll::term<V>, pcre_context<ctll::list<character<B>,character<A>, Ts...>, Parameters> subject) {
2956 : return pcre_context{ctll::push_front(char_range<A,B>(), ctll::list<Ts...>()), subject.parameters};
2957 : }
2958 :
2959 : #endif
2960 :
2961 : #ifndef CTRE__ACTIONS__MODE__HPP
2962 : #define CTRE__ACTIONS__MODE__HPP
2963 :
2964 : // we need to reset counter and wrap Mode into mode_switch
2965 : template <typename Mode, typename... Ts, typename Parameters> static constexpr auto apply_mode(Mode, ctll::list<Ts...>, Parameters) {
2966 : return pcre_context<ctll::list<mode_switch<Mode>, Ts...>, Parameters>{};
2967 : }
2968 :
2969 : template <typename Mode, typename... Ts, size_t Id, size_t Counter> static constexpr auto apply_mode(Mode, ctll::list<capture_id<Id>, Ts...>, pcre_parameters<Counter>) {
2970 : return pcre_context<ctll::list<mode_switch<Mode>, Ts...>, pcre_parameters<Counter-1>>{};
2971 : }
2972 :
2973 : // catch a semantic action into mode
2974 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_case_insensitive mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
2975 : return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
2976 : }
2977 :
2978 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_case_sensitive mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
2979 : return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
2980 : }
2981 :
2982 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_singleline mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
2983 : return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
2984 : }
2985 :
2986 : template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_multiline mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
2987 : return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
2988 : }
2989 :
2990 : // to properly reset capture
2991 :
2992 : #endif
2993 :
2994 : };
2995 :
2996 : }
2997 :
2998 : #endif
2999 :
3000 : #ifndef CTRE__EVALUATION__HPP
3001 : #define CTRE__EVALUATION__HPP
3002 :
3003 : #ifndef CTRE__STARTS_WITH_ANCHOR__HPP
3004 : #define CTRE__STARTS_WITH_ANCHOR__HPP
3005 :
3006 : namespace ctre {
3007 :
3008 : template <typename... Content>
3009 : constexpr bool starts_with_anchor(const flags &, ctll::list<Content...>) noexcept {
3010 : return false;
3011 : }
3012 :
3013 : template <typename... Content>
3014 : constexpr bool starts_with_anchor(const flags &, ctll::list<assert_subject_begin, Content...>) noexcept {
3015 : // yes! start subject anchor is here
3016 : return true;
3017 : }
3018 :
3019 : template <typename... Content>
3020 : constexpr bool starts_with_anchor(const flags & f, ctll::list<assert_line_begin, Content...>) noexcept {
3021 : // yes! start line anchor is here
3022 : return !ctre::multiline_mode(f) || starts_with_anchor(f, ctll::list<Content...>{});
3023 : }
3024 :
3025 : template <typename CharLike, typename... Content>
3026 : constexpr bool starts_with_anchor(const flags & f, ctll::list<boundary<CharLike>, Content...>) noexcept {
3027 : // check if all options starts with anchor or if they are empty, there is an anchor behind them
3028 : return starts_with_anchor(f, ctll::list<Content...>{});
3029 : }
3030 :
3031 : template <typename... Options, typename... Content>
3032 : constexpr bool starts_with_anchor(const flags & f, ctll::list<select<Options...>, Content...>) noexcept {
3033 : // check if all options starts with anchor or if they are empty, there is an anchor behind them
3034 : return (starts_with_anchor(f, ctll::list<Options, Content...>{}) && ... && true);
3035 : }
3036 :
3037 : template <typename... Optional, typename... Content>
3038 : constexpr bool starts_with_anchor(const flags & f, ctll::list<optional<Optional...>, Content...>) noexcept {
3039 : // check if all options starts with anchor or if they are empty, there is an anchor behind them
3040 : return starts_with_anchor(f, ctll::list<Optional..., Content...>{}) && starts_with_anchor(f, ctll::list<Content...>{});
3041 : }
3042 :
3043 : template <typename... Optional, typename... Content>
3044 : constexpr bool starts_with_anchor(const flags & f, ctll::list<lazy_optional<Optional...>, Content...>) noexcept {
3045 : // check if all options starts with anchor or if they are empty, there is an anchor behind them
3046 : return starts_with_anchor(f, ctll::list<Optional..., Content...>{}) && starts_with_anchor(f, ctll::list<Content...>{});
3047 : }
3048 :
3049 : template <typename... Seq, typename... Content>
3050 : constexpr bool starts_with_anchor(const flags & f, ctll::list<sequence<Seq...>, Content...>) noexcept {
3051 : // check if all options starts with anchor or if they are empty, there is an anchor behind them
3052 : return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
3053 : }
3054 :
3055 : template <size_t A, size_t B, typename... Seq, typename... Content>
3056 : constexpr bool starts_with_anchor(const flags & f, ctll::list<repeat<A, B, Seq...>, Content...>) noexcept {
3057 : // check if all options starts with anchor or if they are empty, there is an anchor behind them
3058 : return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
3059 : }
3060 :
3061 : template <size_t A, size_t B, typename... Seq, typename... Content>
3062 : constexpr bool starts_with_anchor(const flags & f, ctll::list<lazy_repeat<A, B, Seq...>, Content...>) noexcept {
3063 : // check if all options starts with anchor or if they are empty, there is an anchor behind them
3064 : return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
3065 : }
3066 :
3067 : template <size_t A, size_t B, typename... Seq, typename... Content>
3068 : constexpr bool starts_with_anchor(const flags & f, ctll::list<possessive_repeat<A, B, Seq...>, Content...>) noexcept {
3069 : // check if all options starts with anchor or if they are empty, there is an anchor behind them
3070 : return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
3071 : }
3072 :
3073 : template <size_t Index, typename... Seq, typename... Content>
3074 : constexpr bool starts_with_anchor(const flags & f, ctll::list<capture<Index, Seq...>, Content...>) noexcept {
3075 : // check if all options starts with anchor or if they are empty, there is an anchor behind them
3076 : return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
3077 : }
3078 :
3079 : template <size_t Index, typename... Seq, typename... Content>
3080 : constexpr bool starts_with_anchor(const flags & f, ctll::list<capture_with_name<Index, Seq...>, Content...>) noexcept {
3081 : // check if all options starts with anchor or if they are empty, there is an anchor behind them
3082 : return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
3083 : }
3084 :
3085 : }
3086 :
3087 : #endif
3088 :
3089 : #ifndef CTRE__RETURN_TYPE__HPP
3090 : #define CTRE__RETURN_TYPE__HPP
3091 :
3092 : #ifndef CTRE__UTF8__HPP
3093 : #define CTRE__UTF8__HPP
3094 :
3095 : #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
3096 :
3097 : #ifndef CTRE_IN_A_MODULE
3098 : #include <string_view>
3099 : #include <iterator>
3100 : #endif
3101 :
3102 : #if defined(__cpp_char8_t) &&__cpp_lib_char8_t >= 201811L
3103 : #define CTRE_ENABLE_UTF8_RANGE
3104 : #endif
3105 :
3106 : #if defined(__cpp_impl_three_way_comparison) && (__cpp_impl_three_way_comparison >= 201907L)
3107 : #define CTRE_NO_NEED_FOR_ADDITIONAL_COMPARISONS
3108 : #endif
3109 :
3110 : namespace ctre {
3111 :
3112 : struct utf8_iterator {
3113 : using self_type = utf8_iterator;
3114 : using value_type = char8_t;
3115 : using reference = char8_t;
3116 : using pointer = const char8_t *;
3117 : using iterator_category = std::bidirectional_iterator_tag;
3118 : using difference_type = int;
3119 :
3120 : struct sentinel {
3121 : // this is here only because I want to support std::make_reverse_iterator
3122 : using self_type = sentinel;
3123 : using value_type = char8_t;
3124 : using reference = char8_t &;
3125 : using pointer = const char8_t *;
3126 : using iterator_category = std::bidirectional_iterator_tag;
3127 : using difference_type = int;
3128 :
3129 : // it's just sentinel it won't be ever called
3130 : auto operator++() noexcept -> self_type &;
3131 : auto operator++(int) noexcept -> self_type;
3132 : auto operator--() noexcept -> self_type &;
3133 : auto operator--(int) noexcept -> self_type;
3134 : friend auto operator==(self_type, self_type) noexcept -> bool;
3135 : auto operator*() noexcept -> reference;
3136 :
3137 : friend constexpr auto operator==(self_type, const char8_t * other_ptr) noexcept {
3138 : return *other_ptr == char8_t{0};
3139 : }
3140 : #ifndef CTRE_NO_NEED_FOR_ADDITIONAL_COMPARISONS
3141 : friend constexpr auto operator!=(self_type, const char8_t * other_ptr) noexcept {
3142 : return *other_ptr != char8_t{0};
3143 : }
3144 :
3145 : friend constexpr auto operator==(const char8_t * other_ptr, self_type) noexcept {
3146 : return *other_ptr == char8_t{0};
3147 : }
3148 :
3149 : friend constexpr auto operator!=(const char8_t * other_ptr, self_type) noexcept {
3150 : return *other_ptr != char8_t{0};
3151 : }
3152 : #endif
3153 : };
3154 :
3155 : const char8_t * ptr{nullptr};
3156 : const char8_t * end{nullptr};
3157 : #ifndef CTRE_NO_NEED_FOR_ADDITIONAL_COMPARISONS
3158 : constexpr friend bool operator!=(const utf8_iterator & lhs, sentinel) {
3159 : return lhs.ptr < lhs.end;
3160 : }
3161 :
3162 : constexpr friend bool operator!=(const utf8_iterator & lhs, const char8_t * rhs) {
3163 : return lhs.ptr != rhs;
3164 : }
3165 :
3166 : constexpr friend bool operator!=(const utf8_iterator & lhs, const utf8_iterator & rhs) {
3167 : return lhs.ptr != rhs.ptr;
3168 : }
3169 : #endif
3170 : constexpr friend bool operator==(const utf8_iterator & lhs, sentinel) {
3171 : return lhs.ptr >= lhs.end;
3172 : }
3173 :
3174 : constexpr friend bool operator==(const utf8_iterator & lhs, const char8_t * rhs) {
3175 : return lhs.ptr == rhs;
3176 : }
3177 :
3178 : constexpr friend bool operator==(const utf8_iterator & lhs, const utf8_iterator & rhs) {
3179 : return lhs.ptr == rhs.ptr;
3180 : }
3181 :
3182 : #ifndef CTRE_NO_NEED_FOR_ADDITIONAL_COMPARISONS
3183 : constexpr friend bool operator!=(sentinel, const utf8_iterator & rhs) {
3184 : return rhs.ptr < rhs.end;
3185 : }
3186 :
3187 : constexpr friend bool operator!=(const char8_t * lhs, const utf8_iterator & rhs) {
3188 : return lhs == rhs.ptr;
3189 : }
3190 :
3191 : constexpr friend bool operator==(sentinel, const utf8_iterator & rhs) {
3192 : return rhs.ptr >= rhs.end;
3193 : }
3194 :
3195 : constexpr friend bool operator==(const char8_t * lhs, const utf8_iterator & rhs) {
3196 : return lhs == rhs.ptr;
3197 : }
3198 : #endif
3199 :
3200 :
3201 : constexpr utf8_iterator & operator=(const char8_t * rhs) {
3202 : ptr = rhs;
3203 : return *this;
3204 : }
3205 :
3206 : constexpr operator const char8_t *() const noexcept {
3207 : return ptr;
3208 : }
3209 :
3210 : constexpr utf8_iterator & operator++() noexcept {
3211 : // the contant is mapping from first 5 bits of first code unit to length of UTF8 code point -1
3212 : // xxxxx -> yy (5 bits to 2 bits)
3213 : // 5 bits are 32 combination, and for each I need 2 bits, hence 64 bit constant
3214 : // (*ptr >> 2) & 0b111110 look at the left 5 bits ignoring the least significant
3215 : // & 0b11u selects only needed two bits
3216 : // +1 because each iteration is at least one code unit forward
3217 :
3218 : ptr += ((0x3A55000000000000ull >> ((*ptr >> 2) & 0b111110u)) & 0b11u) + 1;
3219 : return *this;
3220 : }
3221 :
3222 : constexpr utf8_iterator & operator--() noexcept {
3223 : if (ptr > end) {
3224 : ptr = end-1;
3225 : } else {
3226 : --ptr;
3227 : }
3228 :
3229 : while ((*ptr & 0b11000000u) == 0b10'000000) {
3230 : --ptr;
3231 : }
3232 :
3233 : return *this;
3234 : }
3235 :
3236 : constexpr utf8_iterator operator--(int) noexcept {
3237 : auto self = *this;
3238 : this->operator--();
3239 : return self;
3240 : }
3241 :
3242 : constexpr utf8_iterator operator++(int) noexcept {
3243 : auto self = *this;
3244 : this->operator++();
3245 : return self;
3246 : }
3247 :
3248 : constexpr utf8_iterator operator+(unsigned step) const noexcept {
3249 : utf8_iterator result = *this;
3250 : while (step > 0) {
3251 : ++result;
3252 : step--;
3253 : }
3254 : return result;
3255 : }
3256 :
3257 : constexpr utf8_iterator operator-(unsigned step) const noexcept {
3258 : utf8_iterator result = *this;
3259 : while (step > 0) {
3260 : --result;
3261 : step--;
3262 : }
3263 : return result;
3264 : }
3265 :
3266 : constexpr char32_t operator*() const noexcept {
3267 : constexpr char32_t mojibake = 0xFFFDull;
3268 :
3269 : // quickpath
3270 : if (!(*ptr & 0b1000'0000u)) CTRE_LIKELY {
3271 : return static_cast<char32_t>(*ptr);
3272 : }
3273 :
3274 : // calculate length based on first 5 bits
3275 : const unsigned length = ((0x3A55000000000000ull >> ((*ptr >> 2) & 0b111110u)) & 0b11u);
3276 :
3277 : // actual length is number + 1 bytes
3278 :
3279 : // length 0 here means it's a bad front unit
3280 : if (!length) CTRE_UNLIKELY {
3281 : return mojibake;
3282 : }
3283 :
3284 : // if part of the utf-8 sequence is past the end
3285 : if (((ptr + length) >= end)) CTRE_UNLIKELY {
3286 : return mojibake;
3287 : }
3288 :
3289 : if ((ptr[1] & 0b1100'0000u) != 0b1000'0000) CTRE_UNLIKELY {
3290 : return mojibake;
3291 : }
3292 :
3293 : const char8_t mask = static_cast<char8_t>(0b0011'1111u >> length);
3294 :
3295 : // length = 1 (2 bytes) mask = 0b0001'1111u
3296 : // length = 2 (3 bytes) mask = 0b0000'1111u
3297 : // length = 3 (4 bytes) mask = 0b0000'0111u
3298 :
3299 : // remove utf8 front bits, get only significant part
3300 : // and add first trailing unit
3301 :
3302 : char32_t result = static_cast<char32_t>((ptr[0] & mask) << 6u) | (ptr[1] & 0b0011'1111u);
3303 :
3304 : // add rest of trailing units
3305 : if (length == 1) CTRE_LIKELY {
3306 : return result;
3307 : }
3308 :
3309 : if ((ptr[2] & 0b1100'0000u) != 0b1000'0000) CTRE_UNLIKELY {
3310 : return mojibake;
3311 : }
3312 :
3313 : result = (result << 6) | (ptr[2] & 0b0011'1111u);
3314 :
3315 : if (length == 2) CTRE_LIKELY {
3316 : return result;
3317 : }
3318 :
3319 : if ((ptr[3] & 0b1100'0000u) != 0b1000'0000) CTRE_UNLIKELY {
3320 : return mojibake;
3321 : }
3322 :
3323 : return (result << 6) | (ptr[3] & 0b0011'1111u);
3324 : }
3325 : };
3326 :
3327 : #ifdef CTRE_ENABLE_UTF8_RANGE
3328 : struct utf8_range {
3329 : std::u8string_view range;
3330 : constexpr utf8_range(std::u8string_view r) noexcept: range{r} { }
3331 :
3332 : constexpr auto begin() const noexcept {
3333 : return utf8_iterator{range.data(), range.data() + range.size()};
3334 : }
3335 : constexpr auto end() const noexcept {
3336 : return utf8_iterator::sentinel{};
3337 : }
3338 : };
3339 : #endif
3340 :
3341 : }
3342 :
3343 : #endif
3344 :
3345 : #endif
3346 :
3347 : #ifndef CTRE_IN_A_MODULE
3348 : #include <type_traits>
3349 : #include <tuple>
3350 : #include <string_view>
3351 : #include <string>
3352 : #include <iterator>
3353 : #include <optional>
3354 : #ifdef _MSC_VER
3355 : #include <memory>
3356 : #endif
3357 : #include <iosfwd>
3358 : #if __has_include(<charconv>)
3359 : #include <charconv>
3360 : #endif
3361 : #if defined(__cpp_concepts) && __cpp_concepts >= 202002L
3362 : #include <concepts>
3363 : #endif
3364 : #endif
3365 :
3366 : namespace ctre {
3367 :
3368 : constexpr auto is_random_accessible_f(const std::random_access_iterator_tag &) { return std::true_type{}; }
3369 : constexpr auto is_random_accessible_f(...) { return std::false_type{}; }
3370 :
3371 : template <typename T> constexpr auto is_reverse_iterator_f(const std::reverse_iterator<T> &) { return std::true_type{}; }
3372 : constexpr auto is_reverse_iterator_f(...) { return std::false_type{}; }
3373 :
3374 : template <typename T> constexpr bool is_random_accessible = decltype(is_random_accessible_f(std::declval<const T &>())){};
3375 : template <typename T> constexpr bool is_reverse_iterator = decltype(is_reverse_iterator_f(std::declval<const T &>())){};
3376 :
3377 : struct not_matched_tag_t { };
3378 :
3379 : constexpr inline auto not_matched = not_matched_tag_t{};
3380 :
3381 : template <size_t Id, typename Name = void> struct captured_content {
3382 : template <typename Iterator> class storage {
3383 : Iterator _begin{};
3384 : Iterator _end{};
3385 :
3386 : bool _matched{false};
3387 : public:
3388 : using char_type = typename std::iterator_traits<Iterator>::value_type;
3389 :
3390 : using name = Name;
3391 :
3392 0 : constexpr CTRE_FORCE_INLINE storage() noexcept {}
3393 :
3394 : constexpr CTRE_FORCE_INLINE void matched() noexcept {
3395 0 : _matched = true;
3396 0 : }
3397 : constexpr CTRE_FORCE_INLINE void unmatch() noexcept {
3398 0 : _matched = false;
3399 0 : }
3400 : constexpr CTRE_FORCE_INLINE void set_start(Iterator pos) noexcept {
3401 0 : _begin = pos;
3402 0 : }
3403 : constexpr CTRE_FORCE_INLINE storage & set_end(Iterator pos) noexcept {
3404 0 : _end = pos;
3405 0 : return *this;
3406 : }
3407 : constexpr CTRE_FORCE_INLINE Iterator get_end() const noexcept {
3408 0 : return _end;
3409 : }
3410 :
3411 :
3412 : constexpr auto begin() const noexcept {
3413 : return _begin;
3414 : }
3415 : constexpr auto end() const noexcept {
3416 : return _end;
3417 : }
3418 :
3419 : constexpr explicit CTRE_FORCE_INLINE operator bool() const noexcept {
3420 0 : return _matched;
3421 : }
3422 :
3423 : template <typename It = Iterator> constexpr CTRE_FORCE_INLINE const auto * data_unsafe() const noexcept {
3424 : static_assert(!is_reverse_iterator<It>, "Iterator in your capture must not be reverse!");
3425 :
3426 : #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
3427 : if constexpr (std::is_same_v<Iterator, utf8_iterator>) {
3428 : return _begin.ptr;
3429 : } else { // I'm doing this to avoid warning about dead code
3430 : #endif
3431 :
3432 : #ifdef _MSC_VER
3433 : return std::to_address(_begin); // I'm enabling this only for MSVC for now, as some clang old versions with various libraries (random combinations) has different problems
3434 : #else
3435 : return &*_begin;
3436 : #endif
3437 :
3438 : #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
3439 : }
3440 : #endif
3441 : }
3442 :
3443 : template <typename It = Iterator> constexpr CTRE_FORCE_INLINE const auto * data() const noexcept {
3444 : constexpr bool must_be_contiguous_nonreverse_iterator = is_random_accessible<typename std::iterator_traits<It>::iterator_category> && !is_reverse_iterator<It>;
3445 :
3446 : static_assert(must_be_contiguous_nonreverse_iterator, "To access result as a pointer you need to provide a random access iterator/range to regex (which is not reverse iterator based).");
3447 :
3448 : return data_unsafe();
3449 : }
3450 :
3451 : constexpr CTRE_FORCE_INLINE auto size() const noexcept {
3452 : return static_cast<size_t>(std::distance(begin(), end()));
3453 : }
3454 :
3455 : constexpr CTRE_FORCE_INLINE size_t unit_size() const noexcept {
3456 : #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
3457 : if constexpr (std::is_same_v<Iterator, utf8_iterator>) {
3458 : return static_cast<size_t>(std::distance(_begin.ptr, _end.ptr));
3459 : } else {
3460 : return static_cast<size_t>(std::distance(begin(), end()));
3461 : }
3462 : #else
3463 : return static_cast<size_t>(std::distance(begin(), end()));
3464 : #endif
3465 : }
3466 :
3467 : #if __has_include(<charconv>)
3468 : template <typename R = int, typename... Ts> constexpr CTRE_FORCE_INLINE auto to_number(Ts && ... args) const noexcept -> R {
3469 : R result{0};
3470 : const auto view = to_view();
3471 : std::from_chars(view.data(), view.data() + view.size(), result, std::forward<Ts>(args)...);
3472 : return result;
3473 : }
3474 :
3475 : template <typename R = int, typename... Ts> constexpr CTRE_FORCE_INLINE auto to_optional_number(Ts && ... args) const noexcept -> std::optional<R> {
3476 : if (!static_cast<bool>(*this)) {
3477 : return std::nullopt;
3478 : }
3479 :
3480 : return to_number<R>(std::forward<Ts>(args)...);
3481 : }
3482 : #endif
3483 :
3484 : template <typename It = Iterator> constexpr CTRE_FORCE_INLINE auto to_view() const noexcept {
3485 : // random access, because C++ (waving hands around)
3486 : constexpr bool must_be_nonreverse_contiguous_iterator = is_random_accessible<typename std::iterator_traits<std::remove_const_t<It>>::iterator_category> && !is_reverse_iterator<It>;
3487 :
3488 : static_assert(must_be_nonreverse_contiguous_iterator, "To convert capture into a basic_string_view you need to provide a pointer or a contiguous non-reverse iterator/range to regex.");
3489 :
3490 : return std::basic_string_view<char_type>(data_unsafe(), static_cast<size_t>(unit_size()));
3491 : }
3492 :
3493 : constexpr CTRE_FORCE_INLINE auto view() const noexcept {
3494 : return to_view();
3495 : }
3496 :
3497 : template <typename It = Iterator> constexpr CTRE_FORCE_INLINE auto to_optional_view() const noexcept -> std::optional<std::basic_string_view<char_type>> {
3498 : if (!static_cast<bool>(*this)) {
3499 : return std::nullopt;
3500 : }
3501 : return to_view();
3502 : }
3503 :
3504 : constexpr CTRE_FORCE_INLINE std::basic_string<char_type> to_string() const noexcept {
3505 : #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
3506 : if constexpr (std::is_same_v<Iterator, utf8_iterator>) {
3507 : return std::basic_string<char_type>(data_unsafe(), static_cast<size_t>(unit_size()));
3508 : } else {
3509 : return std::basic_string<char_type>(begin(), end());
3510 : }
3511 : #else
3512 : return std::basic_string<char_type>(begin(), end());
3513 : #endif
3514 : }
3515 :
3516 : constexpr CTRE_FORCE_INLINE auto str() const noexcept {
3517 : return to_string();
3518 : }
3519 :
3520 : template <typename It = Iterator> constexpr CTRE_FORCE_INLINE auto to_optional_string() const noexcept -> std::optional<std::basic_string<char_type>> {
3521 : if (!static_cast<bool>(*this)) {
3522 : return std::nullopt;
3523 : }
3524 : return to_string();
3525 : }
3526 :
3527 : constexpr CTRE_FORCE_INLINE operator std::basic_string_view<char_type>() const noexcept {
3528 : return to_view();
3529 : }
3530 :
3531 : constexpr CTRE_FORCE_INLINE explicit operator std::basic_string<char_type>() const noexcept {
3532 : return to_string();
3533 : }
3534 :
3535 : constexpr CTRE_FORCE_INLINE operator std::optional<std::basic_string_view<char_type>>() const noexcept {
3536 : return to_optional_view();
3537 : }
3538 :
3539 : constexpr CTRE_FORCE_INLINE explicit operator std::optional<std::basic_string<char_type>>() const noexcept {
3540 : return to_optional_string();
3541 : }
3542 :
3543 : constexpr CTRE_FORCE_INLINE static size_t get_id() noexcept {
3544 : return Id;
3545 : }
3546 :
3547 : friend CTRE_FORCE_INLINE constexpr bool operator==(const storage & lhs, std::basic_string_view<char_type> rhs) noexcept {
3548 : return bool(lhs) ? lhs.view() == rhs : false;
3549 : }
3550 : friend CTRE_FORCE_INLINE constexpr bool operator!=(const storage & lhs, std::basic_string_view<char_type> rhs) noexcept {
3551 : return bool(lhs) ? lhs.view() != rhs : false;
3552 : }
3553 : friend CTRE_FORCE_INLINE constexpr bool operator==(std::basic_string_view<char_type> lhs, const storage & rhs) noexcept {
3554 : return bool(rhs) ? lhs == rhs.view() : false;
3555 : }
3556 : friend CTRE_FORCE_INLINE constexpr bool operator!=(std::basic_string_view<char_type> lhs, const storage & rhs) noexcept {
3557 : return bool(rhs) ? lhs != rhs.view() : false;
3558 : }
3559 : friend CTRE_FORCE_INLINE std::ostream & operator<<(std::ostream & str, const storage & rhs) {
3560 : return str << rhs.view();
3561 : }
3562 : };
3563 : };
3564 :
3565 : #if defined(__cpp_concepts) && __cpp_concepts >= 202002L
3566 : template <typename T> concept capture_group = requires(const T & cap) {
3567 : { T::get_id() } -> std::same_as<size_t>;
3568 : { cap.view() };
3569 : { cap.str() };
3570 : { cap.to_string() };
3571 : { cap.to_view() };
3572 : { cap.unit_size() } -> std::same_as<size_t>;
3573 : { cap.size() } -> std::same_as<size_t>;
3574 : { static_cast<bool>(cap) };
3575 : { cap.data() };
3576 : { cap.data_unsafe() };
3577 : { cap.begin() };
3578 : { cap.end() };
3579 : };
3580 : #endif
3581 :
3582 : struct capture_not_exists_tag { };
3583 :
3584 : constexpr auto capture_not_exists = capture_not_exists_tag{};
3585 :
3586 : template <typename... Captures> struct captures;
3587 :
3588 : template <typename Head, typename... Tail> struct captures<Head, Tail...>: captures<Tail...> {
3589 : Head head{};
3590 0 : constexpr CTRE_FORCE_INLINE captures() noexcept { }
3591 : template <size_t id> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
3592 : if constexpr (id == Head::get_id()) {
3593 : return true;
3594 : } else {
3595 : return captures<Tail...>::template exists<id>();
3596 : }
3597 : }
3598 : template <typename Name> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
3599 : if constexpr (std::is_same_v<Name, typename Head::name>) {
3600 : return true;
3601 : } else {
3602 : return captures<Tail...>::template exists<Name>();
3603 : }
3604 : }
3605 : #if CTRE_CNTTP_COMPILER_CHECK
3606 : template <ctll::fixed_string Name> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
3607 : #else
3608 : template <const auto & Name> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
3609 : #endif
3610 : if constexpr (std::is_same_v<typename Head::name, void>) {
3611 : return captures<Tail...>::template exists<Name>();
3612 : } else {
3613 : if constexpr (Head::name::name.is_same_as(Name)) {
3614 : return true;
3615 : } else {
3616 : return captures<Tail...>::template exists<Name>();
3617 : }
3618 : }
3619 : }
3620 : template <size_t id> CTRE_FORCE_INLINE constexpr auto & select() noexcept {
3621 : if constexpr (id == Head::get_id()) {
3622 0 : return head;
3623 : } else {
3624 : return captures<Tail...>::template select<id>();
3625 : }
3626 : }
3627 : template <typename Name> CTRE_FORCE_INLINE constexpr auto & select() noexcept {
3628 : if constexpr (std::is_same_v<Name, typename Head::name>) {
3629 : return head;
3630 : } else {
3631 : return captures<Tail...>::template select<Name>();
3632 : }
3633 : }
3634 : template <size_t id> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
3635 : if constexpr (id == Head::get_id()) {
3636 0 : return head;
3637 : } else {
3638 : return captures<Tail...>::template select<id>();
3639 : }
3640 : }
3641 : template <typename Name> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
3642 : if constexpr (std::is_same_v<Name, typename Head::name>) {
3643 : return head;
3644 : } else {
3645 : return captures<Tail...>::template select<Name>();
3646 : }
3647 : }
3648 : #if CTRE_CNTTP_COMPILER_CHECK
3649 : template <ctll::fixed_string Name> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
3650 : #else
3651 : template <const auto & Name> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
3652 : #endif
3653 : if constexpr (std::is_same_v<typename Head::name, void>) {
3654 : return captures<Tail...>::template select<Name>();
3655 : } else {
3656 : if constexpr (Head::name::name.is_same_as(Name)) {
3657 : return head;
3658 : } else {
3659 : return captures<Tail...>::template select<Name>();
3660 : }
3661 : }
3662 : }
3663 : };
3664 :
3665 : template <> struct captures<> {
3666 0 : constexpr CTRE_FORCE_INLINE captures() noexcept { }
3667 : template <size_t> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
3668 : return false;
3669 : }
3670 : template <typename> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
3671 : return false;
3672 : }
3673 : #if CTRE_CNTTP_COMPILER_CHECK
3674 : template <ctll::fixed_string> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
3675 : #else
3676 : template <const auto &> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
3677 : #endif
3678 : return false;
3679 : }
3680 : template <size_t> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
3681 : return capture_not_exists;
3682 : }
3683 : template <typename> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
3684 : return capture_not_exists;
3685 : }
3686 : #if CTRE_CNTTP_COMPILER_CHECK
3687 : template <ctll::fixed_string> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
3688 : #else
3689 : template <const auto &> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
3690 : #endif
3691 : return capture_not_exists;
3692 : }
3693 : };
3694 :
3695 : template <typename Iterator, typename... Captures> class regex_results {
3696 : captures<captured_content<0>::template storage<Iterator>, typename Captures::template storage<Iterator>...> _captures{};
3697 : public:
3698 : using char_type = typename std::iterator_traits<Iterator>::value_type;
3699 :
3700 0 : constexpr CTRE_FORCE_INLINE regex_results() noexcept { }
3701 0 : constexpr CTRE_FORCE_INLINE regex_results(not_matched_tag_t) noexcept { }
3702 :
3703 : // special constructor for deducting
3704 : constexpr CTRE_FORCE_INLINE regex_results(Iterator, ctll::list<Captures...>) noexcept { }
3705 :
3706 : template <size_t Id> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
3707 : constexpr bool capture_of_provided_id_must_exists = decltype(_captures)::template exists<Id>();
3708 : static_assert(capture_of_provided_id_must_exists);
3709 :
3710 : if constexpr (capture_of_provided_id_must_exists) {
3711 : return _captures.template select<Id>();
3712 : } else {
3713 : return false;
3714 : }
3715 : }
3716 : template <typename Name> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
3717 : constexpr bool capture_of_provided_name_must_exists = decltype(_captures)::template exists<Name>();
3718 : static_assert(capture_of_provided_name_must_exists);
3719 :
3720 : if constexpr (capture_of_provided_name_must_exists) {
3721 : return _captures.template select<Name>();
3722 : } else {
3723 : return false;
3724 : }
3725 : }
3726 : #if CTRE_CNTTP_COMPILER_CHECK
3727 : template <ctll::fixed_string Name> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
3728 : #else
3729 : template <const auto & Name> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
3730 : #endif
3731 : constexpr bool capture_of_provided_name_must_exists = decltype(_captures)::template exists<Name>();
3732 : static_assert(capture_of_provided_name_must_exists);
3733 :
3734 : if constexpr (capture_of_provided_name_must_exists) {
3735 : return _captures.template select<Name>();
3736 : } else {
3737 : return false;
3738 : }
3739 : }
3740 : static constexpr size_t count() noexcept {
3741 : return sizeof...(Captures) + 1;
3742 : }
3743 : constexpr CTRE_FORCE_INLINE regex_results & matched() noexcept {
3744 0 : _captures.template select<0>().matched();
3745 0 : return *this;
3746 : }
3747 : constexpr CTRE_FORCE_INLINE regex_results & unmatch() noexcept {
3748 0 : _captures.template select<0>().unmatch();
3749 0 : return *this;
3750 : }
3751 : constexpr CTRE_FORCE_INLINE operator bool() const noexcept {
3752 0 : return bool(_captures.template select<0>());
3753 : }
3754 :
3755 : // implicit conversions
3756 : constexpr CTRE_FORCE_INLINE operator std::basic_string_view<char_type>() const noexcept {
3757 : return to_view();
3758 : }
3759 :
3760 : constexpr CTRE_FORCE_INLINE explicit operator std::basic_string<char_type>() const noexcept {
3761 : return to_string();
3762 : }
3763 :
3764 : constexpr CTRE_FORCE_INLINE operator std::optional<std::basic_string_view<char_type>>() const noexcept {
3765 : return to_optional_view();
3766 : }
3767 :
3768 : constexpr CTRE_FORCE_INLINE explicit operator std::optional<std::basic_string<char_type>>() const noexcept {
3769 : return to_optional_string();
3770 : }
3771 :
3772 : // conversion to numbers
3773 : #if __has_include(<charconv>)
3774 : template <typename R = int, typename... Ts> constexpr CTRE_FORCE_INLINE auto to_number(Ts && ... args) const noexcept -> R {
3775 : return _captures.template select<0>().template to_number<R>(std::forward<Ts>(args)...);
3776 : }
3777 :
3778 : template <typename R = int, typename... Ts> constexpr CTRE_FORCE_INLINE auto to_optional_number(Ts && ... args) const noexcept -> std::optional<R> {
3779 : return _captures.template select<0>().template to_optional_number<R>(std::forward<Ts>(args)...);
3780 : }
3781 : #endif
3782 :
3783 : // conversion to basic_string_view
3784 : constexpr CTRE_FORCE_INLINE auto to_view() const noexcept {
3785 : return _captures.template select<0>().to_view();
3786 : }
3787 :
3788 : constexpr CTRE_FORCE_INLINE auto view() const noexcept {
3789 : return _captures.template select<0>().view(); // this should be deprecated (??)
3790 : }
3791 :
3792 : constexpr CTRE_FORCE_INLINE auto to_optional_view() const noexcept {
3793 : return _captures.template select<0>().to_optional_view();
3794 : }
3795 :
3796 : // conversion to basic_string
3797 : constexpr CTRE_FORCE_INLINE auto to_string() const noexcept {
3798 : return _captures.template select<0>().to_string();
3799 : }
3800 :
3801 : constexpr CTRE_FORCE_INLINE auto str() const noexcept {
3802 : return _captures.template select<0>().to_string(); // this should be deprecated (??)
3803 : }
3804 :
3805 : constexpr CTRE_FORCE_INLINE auto to_optional_string() const noexcept {
3806 : return _captures.template select<0>().to_optional_string();
3807 : }
3808 :
3809 :
3810 :
3811 :
3812 :
3813 : constexpr CTRE_FORCE_INLINE size_t size() const noexcept {
3814 : return _captures.template select<0>().size();
3815 : }
3816 :
3817 : constexpr CTRE_FORCE_INLINE const auto * data() const noexcept {
3818 : return _captures.template select<0>().data();
3819 : }
3820 :
3821 : constexpr CTRE_FORCE_INLINE regex_results & set_start_mark(Iterator pos) noexcept {
3822 0 : _captures.template select<0>().set_start(pos);
3823 0 : return *this;
3824 : }
3825 : constexpr CTRE_FORCE_INLINE regex_results & set_end_mark(Iterator pos) noexcept {
3826 0 : _captures.template select<0>().set_end(pos);
3827 0 : return *this;
3828 : }
3829 : constexpr CTRE_FORCE_INLINE Iterator get_end_position() const noexcept {
3830 0 : return _captures.template select<0>().get_end();
3831 : }
3832 : template <size_t Id> CTRE_FORCE_INLINE constexpr regex_results & start_capture(Iterator pos) noexcept {
3833 : _captures.template select<Id>().set_start(pos);
3834 : return *this;
3835 : }
3836 : template <size_t Id> CTRE_FORCE_INLINE constexpr regex_results & end_capture(Iterator pos) noexcept {
3837 : _captures.template select<Id>().set_end(pos).matched();
3838 : return *this;
3839 : }
3840 : constexpr auto begin() const noexcept {
3841 : return _captures.template select<0>().begin();
3842 : }
3843 : constexpr auto end() const noexcept {
3844 : return _captures.template select<0>().end();
3845 : }
3846 : friend CTRE_FORCE_INLINE constexpr bool operator==(const regex_results & lhs, std::basic_string_view<char_type> rhs) noexcept {
3847 : return bool(lhs) ? lhs.view() == rhs : false;
3848 : }
3849 : friend CTRE_FORCE_INLINE constexpr bool operator!=(const regex_results & lhs, std::basic_string_view<char_type> rhs) noexcept {
3850 : return bool(lhs) ? lhs.view() != rhs : true;
3851 : }
3852 : friend CTRE_FORCE_INLINE constexpr bool operator==(std::basic_string_view<char_type> lhs, const regex_results & rhs) noexcept {
3853 : return bool(rhs) ? lhs == rhs.view() : false;
3854 : }
3855 : friend CTRE_FORCE_INLINE constexpr bool operator!=(std::basic_string_view<char_type> lhs, const regex_results & rhs) noexcept {
3856 : return bool(rhs) ? lhs != rhs.view() : true;
3857 : }
3858 : friend CTRE_FORCE_INLINE std::ostream & operator<<(std::ostream & str, const regex_results & rhs) {
3859 : #ifdef CTRE_IN_A_MODULE
3860 : auto view = rhs.view();
3861 : str.write(view.data(), view.size());
3862 : return str;
3863 : #else
3864 : return str << rhs.view();
3865 : #endif
3866 : }
3867 : };
3868 :
3869 : template <size_t Id, typename Iterator, typename... Captures> constexpr auto get(const regex_results<Iterator, Captures...> & results) noexcept {
3870 : return results.template get<Id>();
3871 : }
3872 :
3873 : template <typename Iterator, typename... Captures> regex_results(Iterator, ctll::list<Captures...>) -> regex_results<Iterator, Captures...>;
3874 :
3875 : template <typename> struct is_regex_results_t: std::false_type { };
3876 :
3877 : template <typename Iterator, typename... Captures> struct is_regex_results_t<regex_results<Iterator, Captures...>>: std::true_type { };
3878 :
3879 : template <typename T> constexpr bool is_regex_results_v = is_regex_results_t<T>();
3880 :
3881 : #if defined(__cpp_concepts) && __cpp_concepts >= 201907L
3882 : template <typename T> concept capture_groups = is_regex_results_v<T>;
3883 : #endif
3884 :
3885 : template <typename ResultIterator, typename Pattern> using return_type = decltype(regex_results(std::declval<ResultIterator>(), find_captures(Pattern{})));
3886 :
3887 : }
3888 :
3889 : // support for structured bindings
3890 :
3891 : #ifndef __EDG__
3892 : #ifdef __clang__
3893 : #pragma clang diagnostic push
3894 : #pragma clang diagnostic ignored "-Wmismatched-tags"
3895 : #endif
3896 :
3897 : namespace std {
3898 : template <typename... Captures> struct tuple_size<ctre::regex_results<Captures...>> : public std::integral_constant<size_t, ctre::regex_results<Captures...>::count()> { };
3899 :
3900 : template <size_t N, typename... Captures> struct tuple_element<N, ctre::regex_results<Captures...>> {
3901 : public:
3902 : using type = decltype(
3903 : std::declval<const ctre::regex_results<Captures...> &>().template get<N>()
3904 : );
3905 : };
3906 : }
3907 :
3908 : #ifdef __clang__
3909 : #pragma clang diagnostic pop
3910 : #endif
3911 : #endif
3912 :
3913 : #endif
3914 :
3915 : #ifndef CTRE__FIND_CAPTURES__HPP
3916 : #define CTRE__FIND_CAPTURES__HPP
3917 :
3918 : namespace ctre {
3919 :
3920 : CTRE_EXPORT template <typename Pattern> constexpr auto find_captures(Pattern) noexcept {
3921 : return find_captures(ctll::list<Pattern>(), ctll::list<>());
3922 : }
3923 :
3924 : CTRE_EXPORT template <typename... Output> constexpr auto find_captures(ctll::list<>, ctll::list<Output...> output) noexcept {
3925 : return output;
3926 : }
3927 :
3928 : CTRE_EXPORT template <auto... String, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<string<String...>, Tail...>, Output output) noexcept {
3929 : return find_captures(ctll::list<Tail...>(), output);
3930 : }
3931 :
3932 : CTRE_EXPORT template <typename... Options, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<select<Options...>, Tail...>, Output output) noexcept {
3933 : return find_captures(ctll::list<Options..., Tail...>(), output);
3934 : }
3935 :
3936 : CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<optional<Content...>, Tail...>, Output output) noexcept {
3937 : return find_captures(ctll::list<Content..., Tail...>(), output);
3938 : }
3939 :
3940 : CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<lazy_optional<Content...>, Tail...>, Output output) noexcept {
3941 : return find_captures(ctll::list<Content..., Tail...>(), output);
3942 : }
3943 :
3944 : CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<sequence<Content...>, Tail...>, Output output) noexcept {
3945 : return find_captures(ctll::list<Content..., Tail...>(), output);
3946 : }
3947 :
3948 : CTRE_EXPORT template <typename... Tail, typename Output> constexpr auto find_captures(ctll::list<empty, Tail...>, Output output) noexcept {
3949 : return find_captures(ctll::list<Tail...>(), output);
3950 : }
3951 :
3952 : CTRE_EXPORT template <typename... Tail, typename Output> constexpr auto find_captures(ctll::list<assert_subject_begin, Tail...>, Output output) noexcept {
3953 : return find_captures(ctll::list<Tail...>(), output);
3954 : }
3955 :
3956 : CTRE_EXPORT template <typename... Tail, typename Output> constexpr auto find_captures(ctll::list<assert_subject_end, Tail...>, Output output) noexcept {
3957 : return find_captures(ctll::list<Tail...>(), output);
3958 : }
3959 :
3960 : // , typename = std::enable_if_t<(MatchesCharacter<CharacterLike>::template value<char>)
3961 : CTRE_EXPORT template <typename CharacterLike, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<CharacterLike, Tail...>, Output output) noexcept {
3962 : return find_captures(ctll::list<Tail...>(), output);
3963 : }
3964 :
3965 : CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<plus<Content...>, Tail...>, Output output) noexcept {
3966 : return find_captures(ctll::list<Content..., Tail...>(), output);
3967 : }
3968 :
3969 : CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<star<Content...>, Tail...>, Output output) noexcept {
3970 : return find_captures(ctll::list<Content..., Tail...>(), output);
3971 : }
3972 :
3973 : CTRE_EXPORT template <size_t A, size_t B, typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<repeat<A,B,Content...>, Tail...>, Output output) noexcept {
3974 : return find_captures(ctll::list<Content..., Tail...>(), output);
3975 : }
3976 :
3977 : CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<lazy_plus<Content...>, Tail...>, Output output) noexcept {
3978 : return find_captures(ctll::list<Content..., Tail...>(), output);
3979 : }
3980 :
3981 : CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<lazy_star<Content...>, Tail...>, Output output) noexcept {
3982 : return find_captures(ctll::list<Content..., Tail...>(), output);
3983 : }
3984 :
3985 : CTRE_EXPORT template <size_t A, size_t B, typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<lazy_repeat<A,B,Content...>, Tail...>, Output output) noexcept {
3986 : return find_captures(ctll::list<Content..., Tail...>(), output);
3987 : }
3988 :
3989 : CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<possessive_plus<Content...>, Tail...>, Output output) noexcept {
3990 : return find_captures(ctll::list<Content..., Tail...>(), output);
3991 : }
3992 :
3993 : CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<possessive_star<Content...>, Tail...>, Output output) noexcept {
3994 : return find_captures(ctll::list<Content..., Tail...>(), output);
3995 : }
3996 :
3997 : CTRE_EXPORT template <size_t A, size_t B, typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<possessive_repeat<A,B,Content...>, Tail...>, Output output) noexcept {
3998 : return find_captures(ctll::list<Content..., Tail...>(), output);
3999 : }
4000 :
4001 : CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<lookahead_positive<Content...>, Tail...>, Output output) noexcept {
4002 : return find_captures(ctll::list<Content..., Tail...>(), output);
4003 : }
4004 :
4005 : CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<lookahead_negative<Content...>, Tail...>, Output output) noexcept {
4006 : return find_captures(ctll::list<Content..., Tail...>(), output);
4007 : }
4008 :
4009 : CTRE_EXPORT template <size_t Id, typename... Content, typename... Tail, typename... Output> constexpr auto find_captures(ctll::list<capture<Id,Content...>, Tail...>, ctll::list<Output...>) noexcept {
4010 : return find_captures(ctll::list<Content..., Tail...>(), ctll::list<Output..., captured_content<Id>>());
4011 : }
4012 :
4013 : CTRE_EXPORT template <size_t Id, typename Name, typename... Content, typename... Tail, typename... Output> constexpr auto find_captures(ctll::list<capture_with_name<Id,Name,Content...>, Tail...>, ctll::list<Output...>) noexcept {
4014 : return find_captures(ctll::list<Content..., Tail...>(), ctll::list<Output..., captured_content<Id, Name>>());
4015 : }
4016 :
4017 : }
4018 :
4019 : #endif
4020 :
4021 : #ifndef CTRE__FIRST__HPP
4022 : #define CTRE__FIRST__HPP
4023 :
4024 : namespace ctre {
4025 :
4026 : struct can_be_anything {};
4027 :
4028 :
4029 : template <typename... Content>
4030 : constexpr auto first(ctll::list<Content...> l, ctll::list<>) noexcept {
4031 : return l;
4032 : }
4033 :
4034 : template <typename... Content, typename... Tail>
4035 : constexpr auto first(ctll::list<Content...> l, ctll::list<accept, Tail...>) noexcept {
4036 : return l;
4037 : }
4038 :
4039 : template <typename... Content, typename... Tail>
4040 : constexpr auto first(ctll::list<Content...> l, ctll::list<end_mark, Tail...>) noexcept {
4041 : return l;
4042 : }
4043 :
4044 : template <typename... Content, typename... Tail>
4045 : constexpr auto first(ctll::list<Content...> l, ctll::list<end_cycle_mark, Tail...>) noexcept {
4046 : return l;
4047 : }
4048 :
4049 : template <typename... Content, typename... Tail>
4050 : constexpr auto first(ctll::list<Content...> l, ctll::list<end_lookahead_mark, Tail...>) noexcept {
4051 : return l;
4052 : }
4053 :
4054 : template <typename... Content, size_t Id, typename... Tail>
4055 : constexpr auto first(ctll::list<Content...> l, ctll::list<numeric_mark<Id>, Tail...>) noexcept {
4056 : return first(l, ctll::list<Tail...>{});
4057 : }
4058 :
4059 : // empty
4060 : template <typename... Content, typename... Tail>
4061 : constexpr auto first(ctll::list<Content...> l, ctll::list<empty, Tail...>) noexcept {
4062 : return first(l, ctll::list<Tail...>{});
4063 : }
4064 :
4065 : // boundary
4066 : template <typename... Content, typename CharLike, typename... Tail>
4067 : constexpr auto first(ctll::list<Content...> l, ctll::list<boundary<CharLike>, Tail...>) noexcept {
4068 : return first(l, ctll::list<Tail...>{});
4069 : }
4070 :
4071 : // asserts
4072 : template <typename... Content, typename... Tail>
4073 : constexpr auto first(ctll::list<Content...> l, ctll::list<assert_subject_begin, Tail...>) noexcept {
4074 : return first(l, ctll::list<Tail...>{});
4075 : }
4076 :
4077 : template <typename... Content, typename... Tail>
4078 : constexpr auto first(ctll::list<Content...> l, ctll::list<assert_subject_end, Tail...>) noexcept {
4079 : return l;
4080 : }
4081 :
4082 : template <typename... Content, typename... Tail>
4083 : constexpr auto first(ctll::list<Content...> l, ctll::list<assert_subject_end_line, Tail...>) noexcept {
4084 : // FIXME allow endline here
4085 : return l;
4086 : }
4087 :
4088 : template <typename... Content, typename... Tail>
4089 : constexpr auto first(ctll::list<Content...> l, ctll::list<assert_line_begin, Tail...>) noexcept {
4090 : // FIXME line begin is a bit different than subject begin
4091 : return first(l, ctll::list<Tail...>{});
4092 : }
4093 :
4094 : template <typename... Content, typename... Tail>
4095 : constexpr auto first(ctll::list<Content...> l, ctll::list<assert_line_end, Tail...>) noexcept {
4096 : // FIXME line end is a bit different than subject begin
4097 : return l;
4098 : }
4099 :
4100 : // sequence
4101 : template <typename... Content, typename... Seq, typename... Tail>
4102 : constexpr auto first(ctll::list<Content...> l, ctll::list<sequence<Seq...>, Tail...>) noexcept {
4103 : return first(l, ctll::list<Seq..., Tail...>{});
4104 : }
4105 :
4106 : // atomic group
4107 : template <typename... Content, typename... Seq, typename... Tail>
4108 : constexpr auto first(ctll::list<Content...> l, ctll::list<atomic_group<Seq...>, Tail...>) noexcept {
4109 : return first(l, ctll::list<possessive_repeat<1, 1, Seq...>, Tail...>{});
4110 : }
4111 :
4112 : // plus
4113 : template <typename... Content, typename... Seq, typename... Tail>
4114 : constexpr auto first(ctll::list<Content...> l, ctll::list<plus<Seq...>, Tail...>) noexcept {
4115 : return first(l, ctll::list<Seq..., Tail...>{});
4116 : }
4117 :
4118 : // lazy_plus
4119 : template <typename... Content, typename... Seq, typename... Tail>
4120 : constexpr auto first(ctll::list<Content...> l, ctll::list<lazy_plus<Seq...>, Tail...>) noexcept {
4121 : return first(l, ctll::list<Seq..., Tail...>{});
4122 : }
4123 :
4124 : // possessive_plus
4125 : template <typename... Content, typename... Seq, typename... Tail>
4126 : constexpr auto first(ctll::list<Content...> l, ctll::list<possessive_plus<Seq...>, Tail...>) noexcept {
4127 : return first(l, ctll::list<Seq..., Tail...>{});
4128 : }
4129 :
4130 : // star
4131 : template <typename... Content, typename... Seq, typename... Tail>
4132 : constexpr auto first(ctll::list<Content...> l, ctll::list<star<Seq...>, Tail...>) noexcept {
4133 : return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
4134 : }
4135 :
4136 : // lazy_star
4137 : template <typename... Content, typename... Seq, typename... Tail>
4138 : constexpr auto first(ctll::list<Content...> l, ctll::list<lazy_star<Seq...>, Tail...>) noexcept {
4139 : return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
4140 : }
4141 :
4142 : // possessive_star
4143 : template <typename... Content, typename... Seq, typename... Tail>
4144 : constexpr auto first(ctll::list<Content...> l, ctll::list<possessive_star<Seq...>, Tail...>) noexcept {
4145 : return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
4146 : }
4147 :
4148 : // lazy_repeat
4149 : template <typename... Content, size_t A, size_t B, typename... Seq, typename... Tail>
4150 : constexpr auto first(ctll::list<Content...> l, ctll::list<lazy_repeat<A, B, Seq...>, Tail...>) noexcept {
4151 : return first(l, ctll::list<Seq..., Tail...>{});
4152 : }
4153 :
4154 : template <typename... Content, size_t B, typename... Seq, typename... Tail>
4155 : constexpr auto first(ctll::list<Content...> l, ctll::list<lazy_repeat<0, B, Seq...>, Tail...>) noexcept {
4156 : return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
4157 : }
4158 :
4159 : // possessive_repeat
4160 : template <typename... Content, size_t A, size_t B, typename... Seq, typename... Tail>
4161 : constexpr auto first(ctll::list<Content...> l, ctll::list<possessive_repeat<A, B, Seq...>, Tail...>) noexcept {
4162 : return first(l, ctll::list<Seq..., Tail...>{});
4163 : }
4164 :
4165 : template <typename... Content, size_t B, typename... Seq, typename... Tail>
4166 : constexpr auto first(ctll::list<Content...> l, ctll::list<possessive_repeat<0, B, Seq...>, Tail...>) noexcept {
4167 : return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
4168 : }
4169 :
4170 : // repeat
4171 : template <typename... Content, size_t A, size_t B, typename... Seq, typename... Tail>
4172 : constexpr auto first(ctll::list<Content...> l, ctll::list<repeat<A, B, Seq...>, Tail...>) noexcept {
4173 : return first(l, ctll::list<Seq..., Tail...>{});
4174 : }
4175 :
4176 : template <typename... Content, size_t B, typename... Seq, typename... Tail>
4177 : constexpr auto first(ctll::list<Content...> l, ctll::list<repeat<0, B, Seq...>, Tail...>) noexcept {
4178 : return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
4179 : }
4180 :
4181 : // lookahead_positive
4182 : template <typename... Content, typename... Seq, typename... Tail>
4183 : constexpr auto first(ctll::list<Content...>, ctll::list<lookahead_positive<Seq...>, Tail...>) noexcept {
4184 : return ctll::list<can_be_anything>{};
4185 : }
4186 :
4187 : // lookbehind_negative TODO fixme
4188 : template <typename... Content, typename... Seq, typename... Tail>
4189 : constexpr auto first(ctll::list<Content...>, ctll::list<lookbehind_negative<Seq...>, Tail...>) noexcept {
4190 : return ctll::list<can_be_anything>{};
4191 : }
4192 :
4193 : // lookbehind_positive
4194 : template <typename... Content, typename... Seq, typename... Tail>
4195 : constexpr auto first(ctll::list<Content...>, ctll::list<lookbehind_positive<Seq...>, Tail...>) noexcept {
4196 : return ctll::list<can_be_anything>{};
4197 : }
4198 :
4199 : // lookahead_negative TODO fixme
4200 : template <typename... Content, typename... Seq, typename... Tail>
4201 : constexpr auto first(ctll::list<Content...>, ctll::list<lookahead_negative<Seq...>, Tail...>) noexcept {
4202 : return ctll::list<can_be_anything>{};
4203 : }
4204 :
4205 : // capture
4206 : template <typename... Content, size_t Id, typename... Seq, typename... Tail>
4207 : constexpr auto first(ctll::list<Content...> l, ctll::list<capture<Id, Seq...>, Tail...>) noexcept {
4208 : return first(l, ctll::list<Seq..., Tail...>{});
4209 : }
4210 :
4211 : template <typename... Content, size_t Id, typename Name, typename... Seq, typename... Tail>
4212 : constexpr auto first(ctll::list<Content...> l, ctll::list<capture_with_name<Id, Name, Seq...>, Tail...>) noexcept {
4213 : return first(l, ctll::list<Seq..., Tail...>{});
4214 : }
4215 :
4216 : // backreference
4217 : template <typename... Content, size_t Id, typename... Tail>
4218 : constexpr auto first(ctll::list<Content...>, ctll::list<back_reference<Id>, Tail...>) noexcept {
4219 : return ctll::list<can_be_anything>{};
4220 : }
4221 :
4222 : template <typename... Content, typename Name, typename... Tail>
4223 : constexpr auto first(ctll::list<Content...>, ctll::list<back_reference_with_name<Name>, Tail...>) noexcept {
4224 : return ctll::list<can_be_anything>{};
4225 : }
4226 :
4227 : // string First extraction
4228 : template <typename... Content, auto First, auto... String, typename... Tail>
4229 : constexpr auto first(ctll::list<Content...>, ctll::list<string<First, String...>, Tail...>) noexcept {
4230 : return ctll::list<Content..., character<First>>{};
4231 : }
4232 :
4233 : template <typename... Content, typename... Tail>
4234 : constexpr auto first(ctll::list<Content...> l, ctll::list<string<>, Tail...>) noexcept {
4235 : return first(l, ctll::list<Tail...>{});
4236 : }
4237 :
4238 : // optional
4239 : template <typename... Content, typename... Opt, typename... Tail>
4240 : constexpr auto first(ctll::list<Content...> l, ctll::list<optional<Opt...>, Tail...>) noexcept {
4241 : return first(first(l, ctll::list<Opt..., Tail...>{}), ctll::list<Tail...>{});
4242 : }
4243 :
4244 : template <typename... Content, typename... Opt, typename... Tail>
4245 : constexpr auto first(ctll::list<Content...> l, ctll::list<lazy_optional<Opt...>, Tail...>) noexcept {
4246 : return first(first(l, ctll::list<Opt..., Tail...>{}), ctll::list<Tail...>{});
4247 : }
4248 :
4249 : // select (alternation)
4250 : template <typename... Content, typename SHead, typename... STail, typename... Tail>
4251 : constexpr auto first(ctll::list<Content...> l, ctll::list<select<SHead, STail...>, Tail...>) noexcept {
4252 : return first(first(l, ctll::list<SHead, Tail...>{}), ctll::list<select<STail...>, Tail...>{});
4253 : }
4254 :
4255 : template <typename... Content, typename... Tail>
4256 : constexpr auto first(ctll::list<Content...> l, ctll::list<select<>, Tail...>) noexcept {
4257 : return l;
4258 : }
4259 :
4260 : // unicode property => anything
4261 : template <typename... Content, typename PropertyType, PropertyType Property, typename... Tail>
4262 : constexpr auto first(ctll::list<Content...>, ctll::list<ctre::binary_property<PropertyType, Property>, Tail...>) noexcept {
4263 : return ctll::list<can_be_anything>{};
4264 : }
4265 :
4266 : template <typename... Content, typename PropertyType, PropertyType Property, auto Value, typename... Tail>
4267 : constexpr auto first(ctll::list<Content...>, ctll::list<ctre::property<PropertyType, Property, Value>, Tail...>) noexcept {
4268 : return ctll::list<can_be_anything>{};
4269 : }
4270 :
4271 : // characters / sets
4272 :
4273 : template <typename... Content, auto V, typename... Tail>
4274 : constexpr auto first(ctll::list<Content...>, ctll::list<character<V>, Tail...>) noexcept {
4275 : return ctll::list<Content..., character<V>>{};
4276 : }
4277 :
4278 : template <typename... Content, auto... Values, typename... Tail>
4279 : constexpr auto first(ctll::list<Content...>, ctll::list<enumeration<Values...>, Tail...>) noexcept {
4280 : return ctll::list<Content..., character<Values>...>{};
4281 : }
4282 :
4283 : template <typename... Content, typename... SetContent, typename... Tail>
4284 : constexpr auto first(ctll::list<Content...>, ctll::list<set<SetContent...>, Tail...>) noexcept {
4285 : return ctll::list<Content..., SetContent...>{};
4286 : }
4287 :
4288 : template <typename... Content, auto A, auto B, typename... Tail>
4289 : constexpr auto first(ctll::list<Content...>, ctll::list<char_range<A,B>, Tail...>) noexcept {
4290 : return ctll::list<Content..., char_range<A,B>>{};
4291 : }
4292 :
4293 : template <typename... Content, typename... Tail>
4294 : constexpr auto first(ctll::list<Content...>, ctll::list<any, Tail...>) noexcept {
4295 : return ctll::list<can_be_anything>{};
4296 : }
4297 :
4298 : // negative
4299 : template <typename... Content, typename... SetContent, typename... Tail>
4300 : constexpr auto first(ctll::list<Content...>, ctll::list<negate<SetContent...>, Tail...>) noexcept {
4301 : return ctll::list<Content..., negative_set<SetContent...>>{};
4302 : }
4303 :
4304 : template <typename... Content, typename... SetContent, typename... Tail>
4305 : constexpr auto first(ctll::list<Content...>, ctll::list<negative_set<SetContent...>, Tail...>) noexcept {
4306 : return ctll::list<Content..., negative_set<SetContent...>>{};
4307 : }
4308 :
4309 : // user facing interface
4310 : template <typename... Content> constexpr auto calculate_first(Content...) noexcept {
4311 : return first(ctll::list<>{}, ctll::list<Content...>{});
4312 : }
4313 :
4314 : // calculate mutual exclusivity
4315 : template <typename... Content> constexpr size_t calculate_size_of_first(ctre::negative_set<Content...>) {
4316 : return 1 + calculate_size_of_first(ctre::set<Content...>{});
4317 : }
4318 :
4319 : template <auto... V> constexpr size_t calculate_size_of_first(ctre::enumeration<V...>) {
4320 : return sizeof...(V);
4321 : }
4322 :
4323 : constexpr size_t calculate_size_of_first(...) {
4324 : return 1;
4325 : }
4326 :
4327 : template <typename... Content> constexpr size_t calculate_size_of_first(ctll::list<Content...>) {
4328 : return (calculate_size_of_first(Content{}) + ... + 0);
4329 : }
4330 :
4331 : template <typename... Content> constexpr size_t calculate_size_of_first(ctre::set<Content...>) {
4332 : return (calculate_size_of_first(Content{}) + ... + 0);
4333 : }
4334 :
4335 : template <auto A, typename CB> constexpr int64_t negative_helper(ctre::character<A>, CB & cb, int64_t start) {
4336 : if (A != (std::numeric_limits<int64_t>::min)()) {
4337 : if (start < A) {
4338 : cb(start, A-1);
4339 : }
4340 : }
4341 : if (A != (std::numeric_limits<int64_t>::max)()) {
4342 : return A+1;
4343 : } else {
4344 : return A;
4345 : }
4346 : }
4347 :
4348 : template <auto A, auto B, typename CB> constexpr int64_t negative_helper(ctre::char_range<A,B>, CB & cb, int64_t start) {
4349 : if (A != (std::numeric_limits<int64_t>::min)()) {
4350 : if (start < A) {
4351 : cb(start, A-1);
4352 : }
4353 : }
4354 : if (B != (std::numeric_limits<int64_t>::max)()) {
4355 : return B+1;
4356 : } else {
4357 : return B;
4358 : }
4359 : }
4360 :
4361 : template <auto Head, auto... Tail, typename CB> constexpr int64_t negative_helper(ctre::enumeration<Head, Tail...>, CB & cb, int64_t start) {
4362 : int64_t nstart = negative_helper(ctre::character<Head>{}, cb, start);
4363 : return negative_helper(ctre::enumeration<Tail...>{}, cb, nstart);
4364 : }
4365 :
4366 : template <typename CB> constexpr int64_t negative_helper(ctre::enumeration<>, CB &, int64_t start) {
4367 : return start;
4368 : }
4369 :
4370 : template <typename CB> constexpr int64_t negative_helper(ctre::set<>, CB &, int64_t start) {
4371 : return start;
4372 : }
4373 :
4374 : template <typename PropertyType, PropertyType Property, typename CB>
4375 : constexpr auto negative_helper(ctre::binary_property<PropertyType, Property>, CB &&, int64_t start) {
4376 : return start;
4377 : }
4378 :
4379 : template <typename PropertyType, PropertyType Property, auto Value, typename CB>
4380 : constexpr auto negative_helper(ctre::property<PropertyType, Property, Value>, CB &&, int64_t start) {
4381 : return start;
4382 : }
4383 :
4384 : template <typename Head, typename... Rest, typename CB> constexpr int64_t negative_helper(ctre::set<Head, Rest...>, CB & cb, int64_t start) {
4385 : start = negative_helper(Head{}, cb, start);
4386 : return negative_helper(ctre::set<Rest...>{}, cb, start);
4387 : }
4388 :
4389 : template <typename Head, typename... Rest, typename CB> constexpr void negative_helper(ctre::negative_set<Head, Rest...>, CB && cb, int64_t start = (std::numeric_limits<int64_t>::min)()) {
4390 : start = negative_helper(Head{}, cb, start);
4391 : negative_helper(ctre::negative_set<Rest...>{}, std::forward<CB>(cb), start);
4392 : }
4393 :
4394 : template <typename CB> constexpr void negative_helper(ctre::negative_set<>, CB && cb, int64_t start = (std::numeric_limits<int64_t>::min)()) {
4395 : if (start < (std::numeric_limits<int64_t>::max)()) {
4396 : cb(start, (std::numeric_limits<int64_t>::max)());
4397 : }
4398 : }
4399 :
4400 : // simple fixed set
4401 : // TODO: this needs some optimizations
4402 : template <size_t Capacity> class point_set {
4403 : struct point {
4404 : int64_t low{};
4405 : int64_t high{};
4406 : constexpr bool operator<(const point & rhs) const {
4407 : return low < rhs.low;
4408 : }
4409 : constexpr point() { }
4410 : constexpr point(int64_t l, int64_t h): low{l}, high{h} { }
4411 : };
4412 : point points[Capacity+1]{};
4413 : size_t used{0};
4414 : constexpr point * begin() {
4415 : return points;
4416 : }
4417 : constexpr point * begin() const {
4418 : return points;
4419 : }
4420 : constexpr point * end() {
4421 : return points + used;
4422 : }
4423 : constexpr point * end() const {
4424 : return points + used;
4425 : }
4426 : constexpr point * lower_bound(point obj) {
4427 : auto first = begin();
4428 : auto last = end();
4429 : auto it = first;
4430 : auto count = std::distance(first, last);
4431 : while (count != 0) {
4432 : it = first;
4433 : auto step = count / 2;
4434 : std::advance(it, step);
4435 : if (*it < obj) {
4436 : first = ++it;
4437 : count -= step + 1;
4438 : } else {
4439 : count = step;
4440 : }
4441 : }
4442 : return it;
4443 : }
4444 : constexpr point * insert_point(int64_t position, int64_t other) {
4445 : point obj{position, other};
4446 : auto it = lower_bound(obj);
4447 : if (it == end()) {
4448 : *it = obj;
4449 : used++;
4450 : return it;
4451 : } else {
4452 : auto out = it;
4453 : auto e = end();
4454 : while (it != e) {
4455 : auto tmp = *it;
4456 : *it = obj;
4457 : obj = tmp;
4458 : //std::swap(*it, obj);
4459 : it++;
4460 : }
4461 : auto tmp = *it;
4462 : *it = obj;
4463 : obj = tmp;
4464 : //std::swap(*it, obj);
4465 :
4466 : used++;
4467 : return out;
4468 : }
4469 : }
4470 : public:
4471 : constexpr point_set() { }
4472 : constexpr void insert(int64_t low, int64_t high) {
4473 : insert_point(low, high);
4474 : //insert_point(high, low);
4475 : }
4476 : constexpr bool check(int64_t low, int64_t high) {
4477 : for (const auto & r: *this) {
4478 : if (r.low <= low && low <= r.high) {
4479 : return true;
4480 : } else if (r.low <= high && high <= r.high) {
4481 : return true;
4482 : } else if (low <= r.low && r.low <= high) {
4483 : return true;
4484 : } else if (low <= r.high && r.high <= high) {
4485 : return true;
4486 : }
4487 : }
4488 : return false;
4489 : }
4490 :
4491 :
4492 : template <auto V> constexpr bool check(ctre::character<V>) {
4493 : return check(V,V);
4494 : }
4495 : template <auto A, auto B> constexpr bool check(ctre::char_range<A,B>) {
4496 : return check(A,B);
4497 : }
4498 : constexpr bool check(can_be_anything) {
4499 : return used > 0;
4500 : }
4501 : template <typename PropertyType, PropertyType Property>
4502 : constexpr bool check(ctre::binary_property<PropertyType, Property>) {
4503 : return check(can_be_anything{});
4504 : }
4505 :
4506 : template <typename PropertyType, PropertyType Property, auto Value>
4507 : constexpr bool check(ctre::property<PropertyType, Property, Value>) {
4508 : return check(can_be_anything{});
4509 : }
4510 : template <typename... Content> constexpr bool check(ctre::negative_set<Content...> nset) {
4511 : bool collision = false;
4512 : negative_helper(nset, [&](int64_t low, int64_t high){
4513 : collision |= this->check(low, high);
4514 : });
4515 : return collision;
4516 : }
4517 : template <auto... V> constexpr bool check(ctre::enumeration<V...>) {
4518 :
4519 : return (check(V,V) || ... || false);
4520 : }
4521 : template <typename... Content> constexpr bool check(ctll::list<Content...>) {
4522 : return (check(Content{}) || ... || false);
4523 : }
4524 : template <typename... Content> constexpr bool check(ctre::set<Content...>) {
4525 : return (check(Content{}) || ... || false);
4526 : }
4527 :
4528 :
4529 : template <auto V> constexpr void populate(ctre::character<V>) {
4530 : insert(V,V);
4531 : }
4532 : template <auto A, auto B> constexpr void populate(ctre::char_range<A,B>) {
4533 : insert(A,B);
4534 : }
4535 : constexpr void populate(...) {
4536 : points[0].low = (std::numeric_limits<int64_t>::min)();
4537 : points[0].high = (std::numeric_limits<int64_t>::max)();
4538 : used = 1;
4539 : }
4540 : template <typename... Content> constexpr void populate(ctre::negative_set<Content...> nset) {
4541 : negative_helper(nset, [&](int64_t low, int64_t high){
4542 : this->insert(low, high);
4543 : });
4544 : }
4545 : template <typename... Content> constexpr void populate(ctre::set<Content...>) {
4546 : (populate(Content{}), ...);
4547 : }
4548 : template <typename... Content> constexpr void populate(ctll::list<Content...>) {
4549 : (populate(Content{}), ...);
4550 : }
4551 : };
4552 :
4553 : template <typename... A, typename... B> constexpr bool collides(ctll::list<A...> rhs, ctll::list<B...> lhs) {
4554 : constexpr size_t capacity = calculate_size_of_first(rhs);
4555 :
4556 : point_set<capacity> set;
4557 : set.populate(rhs);
4558 :
4559 : return set.check(lhs);
4560 : }
4561 :
4562 : }
4563 :
4564 : #endif
4565 :
4566 : #ifndef CTRE_IN_A_MODULE
4567 : #include <iterator>
4568 : #endif
4569 :
4570 : // remove me when MSVC fix the constexpr bug
4571 : #ifdef _MSC_VER
4572 : #ifndef CTRE_MSVC_GREEDY_WORKAROUND
4573 : #define CTRE_MSVC_GREEDY_WORKAROUND
4574 : #endif
4575 : #endif
4576 :
4577 : namespace ctre {
4578 :
4579 : template <size_t Limit> constexpr CTRE_FORCE_INLINE bool less_than_or_infinite([[maybe_unused]] size_t i) noexcept {
4580 : if constexpr (Limit == 0) {
4581 : // infinite
4582 0 : return true;
4583 : } else {
4584 0 : return i < Limit;
4585 : }
4586 : }
4587 :
4588 : template <size_t Limit> constexpr CTRE_FORCE_INLINE bool less_than([[maybe_unused]] size_t i) noexcept {
4589 : if constexpr (Limit == 0) {
4590 : // infinite
4591 0 : return false;
4592 : } else {
4593 0 : return i < Limit;
4594 : }
4595 : }
4596 :
4597 : constexpr bool is_bidirectional(const std::bidirectional_iterator_tag &) { return true; }
4598 : constexpr bool is_bidirectional(...) { return false; }
4599 :
4600 : // sink for making the errors shorter
4601 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator>
4602 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R, ...) noexcept {
4603 : return not_matched;
4604 : }
4605 :
4606 : // if we found "accept" object on stack => ACCEPT
4607 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator>
4608 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R captures, ctll::list<accept>) noexcept {
4609 0 : return captures.matched();
4610 : }
4611 :
4612 : // if we found "reject" object on stack => REJECT
4613 : template <typename R, typename... Rest, typename BeginIterator, typename Iterator, typename EndIterator>
4614 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R, ctll::list<reject, Rest...>) noexcept {
4615 : return not_matched;
4616 : }
4617 :
4618 : // mark start of outer capture
4619 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
4620 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<start_mark, Tail...>) noexcept {
4621 0 : return evaluate(begin, current, last, f, captures.set_start_mark(current), ctll::list<Tail...>());
4622 : }
4623 :
4624 : // mark end of outer capture
4625 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
4626 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<end_mark, Tail...>) noexcept {
4627 0 : return evaluate(begin, current, last, f, captures.set_end_mark(current), ctll::list<Tail...>());
4628 : }
4629 :
4630 : // mark end of cycle
4631 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
4632 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator current, const EndIterator, [[maybe_unused]] const flags & f, R captures, ctll::list<end_cycle_mark>) noexcept {
4633 0 : if (cannot_be_empty_match(f)) {
4634 0 : return not_matched;
4635 : }
4636 :
4637 0 : return captures.set_end_mark(current).matched();
4638 : }
4639 :
4640 : // matching everything which behave as a one character matcher
4641 :
4642 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename CharacterLike, typename... Tail, typename = std::enable_if_t<(MatchesCharacter<CharacterLike>::template value<decltype(*std::declval<Iterator>())>)>>
4643 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<CharacterLike, Tail...>) noexcept {
4644 0 : if (current == last) return not_matched;
4645 0 : if (!CharacterLike::match_char(*current, f)) return not_matched;
4646 :
4647 0 : return evaluate(begin, ++current, last, consumed_something(f), captures, ctll::list<Tail...>());
4648 : }
4649 :
4650 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
4651 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<any, Tail...>) noexcept {
4652 0 : if (current == last) return not_matched;
4653 :
4654 0 : if (multiline_mode(f)) {
4655 : // TODO add support for different line ending and unicode (in a future unicode mode)
4656 0 : if (*current == '\n') return not_matched;
4657 : }
4658 0 : return evaluate(begin, ++current, last, consumed_something(f), captures, ctll::list<Tail...>());
4659 : }
4660 :
4661 : // matching strings in patterns
4662 : template <auto... String, typename Iterator, typename EndIterator> constexpr CTRE_FORCE_INLINE bool match_string([[maybe_unused]] Iterator & current, [[maybe_unused]] const EndIterator last, [[maybe_unused]] const flags & f) {
4663 0 : return ((current != last && character<String>::match_char(*current++, f)) && ... && true);
4664 : }
4665 :
4666 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, auto... String, typename... Tail>
4667 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, [[maybe_unused]] const flags & f, R captures, ctll::list<string<String...>, Tail...>) noexcept {
4668 0 : if (!match_string<String...>(current, last, f)) {
4669 0 : return not_matched;
4670 : }
4671 :
4672 0 : return evaluate(begin, current, last, consumed_something(f, sizeof...(String) > 0), captures, ctll::list<Tail...>());
4673 : }
4674 :
4675 : // matching select in patterns
4676 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename HeadOptions, typename... TailOptions, typename... Tail>
4677 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<select<HeadOptions, TailOptions...>, Tail...>) noexcept {
4678 0 : if (auto r = evaluate(begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>())) {
4679 0 : return r;
4680 : } else {
4681 0 : return evaluate(begin, current, last, f, captures, ctll::list<select<TailOptions...>, Tail...>());
4682 : }
4683 : }
4684 :
4685 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
4686 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R, ctll::list<select<>, Tail...>) noexcept {
4687 : // no previous option was matched => REJECT
4688 0 : return not_matched;
4689 : }
4690 :
4691 : // matching sequence in patterns
4692 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename HeadContent, typename... TailContent, typename... Tail>
4693 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<sequence<HeadContent, TailContent...>, Tail...>) noexcept {
4694 : if constexpr (sizeof...(TailContent) > 0) {
4695 0 : return evaluate(begin, current, last, f, captures, ctll::list<HeadContent, sequence<TailContent...>, Tail...>());
4696 : } else {
4697 0 : return evaluate(begin, current, last, f, captures, ctll::list<HeadContent, Tail...>());
4698 : }
4699 : }
4700 :
4701 : // matching empty in patterns
4702 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
4703 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<empty, Tail...>) noexcept {
4704 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4705 : }
4706 :
4707 : // matching asserts
4708 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
4709 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<assert_subject_begin, Tail...>) noexcept {
4710 : if (begin != current) {
4711 : return not_matched;
4712 : }
4713 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4714 : }
4715 :
4716 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
4717 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<assert_subject_end, Tail...>) noexcept {
4718 0 : if (last != current) {
4719 0 : return not_matched;
4720 : }
4721 0 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4722 : }
4723 :
4724 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
4725 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<assert_subject_end_line, Tail...>) noexcept {
4726 : if (multiline_mode(f)) {
4727 : if (last == current) {
4728 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4729 : } else if (*current == '\n' && std::next(current) == last) {
4730 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4731 : } else {
4732 : return not_matched;
4733 : }
4734 : } else {
4735 : if (last != current) {
4736 : return not_matched;
4737 : }
4738 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4739 : }
4740 : }
4741 :
4742 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
4743 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<assert_line_begin, Tail...>) noexcept {
4744 : if (multiline_mode(f)) {
4745 : if (begin == current) {
4746 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4747 : } else if (*std::prev(current) == '\n') {
4748 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4749 : } else {
4750 : return not_matched;
4751 : }
4752 : } else {
4753 : if (begin != current) {
4754 : return not_matched;
4755 : }
4756 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4757 : }
4758 : }
4759 :
4760 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
4761 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<assert_line_end, Tail...>) noexcept {
4762 0 : if (multiline_mode(f)) {
4763 0 : if (last == current) {
4764 0 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4765 0 : } else if (*current == '\n') {
4766 0 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4767 : } else {
4768 0 : return not_matched;
4769 : }
4770 : }
4771 :
4772 : // TODO properly match line end
4773 0 : if (last != current) {
4774 0 : return not_matched;
4775 : }
4776 0 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4777 : }
4778 :
4779 : // matching boundary
4780 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename CharacterLike, typename... Tail>
4781 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<boundary<CharacterLike>, Tail...>) noexcept {
4782 :
4783 : // reason why I need bidirectional iterators or some clever hack
4784 : bool before = false;
4785 : bool after = false;
4786 :
4787 : static_assert(is_bidirectional(typename std::iterator_traits<Iterator>::iterator_category{}), "To use boundary in regex you need to provide bidirectional iterator or range.");
4788 :
4789 : if (last != current) {
4790 : after = CharacterLike::match_char(*current, f);
4791 : }
4792 : if (begin != current) {
4793 : before = CharacterLike::match_char(*std::prev(current), f);
4794 : }
4795 :
4796 : if (before == after) return not_matched;
4797 :
4798 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4799 : }
4800 :
4801 : // matching not_boundary
4802 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename CharacterLike, typename... Tail>
4803 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<not_boundary<CharacterLike>, Tail...>) noexcept {
4804 :
4805 : // reason why I need bidirectional iterators or some clever hack
4806 : bool before = false;
4807 : bool after = false;
4808 :
4809 : static_assert(is_bidirectional(typename std::iterator_traits<Iterator>::iterator_category{}), "To use boundary in regex you need to provide bidirectional iterator or range.");
4810 :
4811 : if (last != current) {
4812 : after = CharacterLike::match_char(*current, f);
4813 : }
4814 : if (begin != current) {
4815 : before = CharacterLike::match_char(*std::prev(current), f);
4816 : }
4817 :
4818 : if (before != after) return not_matched;
4819 :
4820 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
4821 : }
4822 :
4823 : // lazy repeat
4824 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail>
4825 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, [[maybe_unused]] const flags & f, R captures, ctll::list<lazy_repeat<A,B,Content...>, Tail...>) noexcept {
4826 :
4827 : if constexpr (B != 0 && A > B) {
4828 : return not_matched;
4829 : } else {
4830 : const Iterator backup_current = current;
4831 :
4832 : size_t i{0};
4833 :
4834 : while (less_than<A>(i)) {
4835 : auto outer_result = evaluate(begin, current, last, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());
4836 :
4837 : if (!outer_result) return not_matched;
4838 :
4839 : captures = outer_result.unmatch();
4840 : current = outer_result.get_end_position();
4841 :
4842 : ++i;
4843 : }
4844 :
4845 : if (auto outer_result = evaluate(begin, current, last, consumed_something(f, backup_current != current), captures, ctll::list<Tail...>())) {
4846 : return outer_result;
4847 : }
4848 :
4849 : while (less_than_or_infinite<B>(i)) {
4850 : auto inner_result = evaluate(begin, current, last, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());
4851 :
4852 : if (!inner_result) return not_matched;
4853 :
4854 : auto outer_result = evaluate(begin, inner_result.get_end_position(), last, consumed_something(f), inner_result.unmatch(), ctll::list<Tail...>());
4855 :
4856 : if (outer_result) {
4857 : return outer_result;
4858 : }
4859 :
4860 : captures = inner_result.unmatch();
4861 : current = inner_result.get_end_position();
4862 :
4863 : ++i;
4864 : }
4865 :
4866 : // rest of regex
4867 : return evaluate(begin, current, last, consumed_something(f), captures, ctll::list<Tail...>());
4868 : }
4869 : }
4870 :
4871 : // possessive repeat
4872 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail>
4873 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, [[maybe_unused]] const flags & f, R captures, ctll::list<possessive_repeat<A,B,Content...>, Tail...>) noexcept {
4874 :
4875 : if constexpr ((B != 0) && (A > B)) {
4876 : return not_matched;
4877 : } else {
4878 0 : const auto backup_current = current;
4879 :
4880 0 : for (size_t i{0}; less_than_or_infinite<B>(i); ++i) {
4881 : // try as many of inner as possible and then try outer once
4882 0 : auto inner_result = evaluate(begin, current, last, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());
4883 :
4884 0 : if (!inner_result) {
4885 0 : if (!less_than<A>(i)) break;
4886 0 : return not_matched;
4887 : }
4888 :
4889 0 : captures = inner_result.unmatch();
4890 0 : current = inner_result.get_end_position();
4891 : }
4892 :
4893 0 : return evaluate(begin, current, last, consumed_something(f, backup_current != current), captures, ctll::list<Tail...>());
4894 : }
4895 : }
4896 :
4897 : // (gready) repeat
4898 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail>
4899 : #ifdef CTRE_MSVC_GREEDY_WORKAROUND
4900 : constexpr inline void evaluate_recursive(R & result, size_t i, const BeginIterator begin, Iterator current, const EndIterator last, [[maybe_unused]] const flags & f, R captures, ctll::list<repeat<A,B,Content...>, Tail...> stack) noexcept {
4901 : #else
4902 0 : constexpr inline R evaluate_recursive(size_t i, const BeginIterator begin, Iterator current, const EndIterator last, [[maybe_unused]] const flags & f, R captures, ctll::list<repeat<A,B,Content...>, Tail...> stack) noexcept {
4903 : #endif
4904 0 : if (less_than_or_infinite<B>(i)) {
4905 :
4906 : // a*ab
4907 : // aab
4908 :
4909 0 : if (auto inner_result = evaluate(begin, current, last, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>())) {
4910 : // TODO MSVC issue:
4911 : // if I uncomment this return it will not fail in constexpr (but the matching result will not be correct)
4912 : // return inner_result
4913 : // I tried to add all constructors to R but without any success
4914 0 : auto tmp_current = current;
4915 0 : tmp_current = inner_result.get_end_position();
4916 : #ifdef CTRE_MSVC_GREEDY_WORKAROUND
4917 : evaluate_recursive(result, i+1, begin, tmp_current, last, f, inner_result.unmatch(), stack);
4918 : if (result) {
4919 : return;
4920 : }
4921 : #else
4922 0 : if (auto rec_result = evaluate_recursive(i+1, begin, tmp_current, last, f, inner_result.unmatch(), stack)) {
4923 0 : return rec_result;
4924 : }
4925 : #endif
4926 : }
4927 : }
4928 : #ifdef CTRE_MSVC_GREEDY_WORKAROUND
4929 : result = evaluate(begin, current, last, consumed_something(f), captures, ctll::list<Tail...>());
4930 : #else
4931 0 : return evaluate(begin, current, last, consumed_something(f), captures, ctll::list<Tail...>());
4932 : #endif
4933 : }
4934 :
4935 : // (greedy) repeat
4936 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail>
4937 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, [[maybe_unused]] const flags & f, R captures, [[maybe_unused]] ctll::list<repeat<A,B,Content...>, Tail...> stack) {
4938 :
4939 : if constexpr ((B != 0) && (A > B)) {
4940 : return not_matched;
4941 : }
4942 :
4943 : #ifndef CTRE_DISABLE_GREEDY_OPT
4944 : else if constexpr (!collides(calculate_first(Content{}...), calculate_first(Tail{}...))) {
4945 0 : return evaluate(begin, current, last, f, captures, ctll::list<possessive_repeat<A,B,Content...>, Tail...>());
4946 : }
4947 : #endif
4948 : else {
4949 : // A..B
4950 0 : size_t i{0};
4951 0 : while (less_than<A>(i)) {
4952 0 : auto inner_result = evaluate(begin, current, last, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());
4953 :
4954 0 : if (!inner_result) return not_matched;
4955 :
4956 0 : captures = inner_result.unmatch();
4957 0 : current = inner_result.get_end_position();
4958 :
4959 0 : ++i;
4960 : }
4961 :
4962 : #ifdef CTRE_MSVC_GREEDY_WORKAROUND
4963 : R result;
4964 : evaluate_recursive(result, i, begin, current, last, f, captures, stack);
4965 : return result;
4966 : #else
4967 0 : return evaluate_recursive(i, begin, current, last, f, captures, stack);
4968 : #endif
4969 : }
4970 :
4971 : }
4972 :
4973 : // capture (numeric ID)
4974 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t Id, typename... Content, typename... Tail>
4975 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<capture<Id, Content...>, Tail...>) noexcept {
4976 : return evaluate(begin, current, last, f, captures.template start_capture<Id>(current), ctll::list<sequence<Content...>, numeric_mark<Id>, Tail...>());
4977 : }
4978 :
4979 : // capture end mark (numeric and string ID)
4980 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t Id, typename... Tail>
4981 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<numeric_mark<Id>, Tail...>) noexcept {
4982 : return evaluate(begin, current, last, f, captures.template end_capture<Id>(current), ctll::list<Tail...>());
4983 : }
4984 :
4985 : // capture (string ID)
4986 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t Id, typename Name, typename... Content, typename... Tail>
4987 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<capture_with_name<Id, Name, Content...>, Tail...>) noexcept {
4988 : return evaluate(begin, current, last, f, captures.template start_capture<Id>(current), ctll::list<sequence<Content...>, numeric_mark<Id>, Tail...>());
4989 : }
4990 :
4991 : // backreference support (match agains content of iterators)
4992 : template <typename Iterator> struct string_match {
4993 : Iterator position;
4994 : bool match;
4995 : };
4996 :
4997 : template <typename Iterator, typename EndIterator> constexpr CTRE_FORCE_INLINE string_match<Iterator> match_against_range(Iterator current, const EndIterator last, Iterator range_current, const Iterator range_end, flags) noexcept {
4998 : while (last != current && range_end != range_current) {
4999 : if (*current == *range_current) {
5000 : current++;
5001 : range_current++;
5002 : } else {
5003 : return {current, false};
5004 : }
5005 : }
5006 : return {current, range_current == range_end};
5007 : }
5008 :
5009 : // backreference with name
5010 : template <typename R, typename Id, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
5011 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<back_reference_with_name<Id>, Tail...>) noexcept {
5012 :
5013 : if (const auto ref = captures.template get<Id>()) {
5014 : if (auto result = match_against_range(current, last, ref.begin(), ref.end(), f); result.match) {
5015 : return evaluate(begin, result.position, last, consumed_something(f, ref.begin() != ref.end()), captures, ctll::list<Tail...>());
5016 : }
5017 : }
5018 : return not_matched;
5019 : }
5020 :
5021 : // backreference
5022 : template <typename R, size_t Id, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
5023 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<back_reference<Id>, Tail...>) noexcept {
5024 :
5025 : if (const auto ref = captures.template get<Id>()) {
5026 : if (auto result = match_against_range(current, last, ref.begin(), ref.end(), f); result.match) {
5027 : return evaluate(begin, result.position, last, consumed_something(f, ref.begin() != ref.end()), captures, ctll::list<Tail...>());
5028 : }
5029 : }
5030 : return not_matched;
5031 : }
5032 :
5033 : // end of lookahead
5034 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
5035 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R captures, ctll::list<end_lookahead_mark>) noexcept {
5036 : // TODO check interaction with non-empty flag
5037 : return captures.matched();
5038 : }
5039 :
5040 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail>
5041 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R captures, ctll::list<end_lookbehind_mark>) noexcept {
5042 : // TODO check interaction with non-empty flag
5043 : return captures.matched();
5044 : }
5045 :
5046 : // lookahead positive
5047 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Content, typename... Tail>
5048 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<lookahead_positive<Content...>, Tail...>) noexcept {
5049 :
5050 : if (auto lookahead_result = evaluate(begin, current, last, f, captures, ctll::list<sequence<Content...>, end_lookahead_mark>())) {
5051 : captures = lookahead_result.unmatch();
5052 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
5053 : } else {
5054 : return not_matched;
5055 : }
5056 : }
5057 :
5058 : // lookahead negative
5059 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Content, typename... Tail>
5060 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<lookahead_negative<Content...>, Tail...>) noexcept {
5061 :
5062 : if (auto lookahead_result = evaluate(begin, current, last, f, captures, ctll::list<sequence<Content...>, end_lookahead_mark>())) {
5063 : return not_matched;
5064 : } else {
5065 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
5066 : }
5067 : }
5068 :
5069 : // lookbehind positive
5070 : constexpr bool is_at_least_bidirectional(std::input_iterator_tag) {
5071 : return false;
5072 : }
5073 :
5074 : constexpr bool is_at_least_bidirectional(std::bidirectional_iterator_tag) {
5075 : return true;
5076 : }
5077 :
5078 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Content, typename... Tail>
5079 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<lookbehind_positive<Content...>, Tail...>) noexcept {
5080 : static_assert(is_at_least_bidirectional(typename std::iterator_traits<Iterator>::iterator_category{}), "to use lookbehind you must provide bi-directional iterator");
5081 :
5082 : if (auto lookbehind_result = evaluate(std::make_reverse_iterator(last), std::make_reverse_iterator(current), std::make_reverse_iterator(begin), f, captures, ctll::list<sequence<Content...>, end_lookbehind_mark>())) {
5083 : captures = lookbehind_result.unmatch();
5084 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
5085 : } else {
5086 : return not_matched;
5087 : }
5088 : }
5089 :
5090 : // lookbehind negative
5091 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Content, typename... Tail>
5092 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<lookbehind_negative<Content...>, Tail...>) noexcept {
5093 : static_assert(is_at_least_bidirectional(typename std::iterator_traits<Iterator>::iterator_category{}), "to use negative lookbehind you must provide bi-directional iterator");
5094 :
5095 : if (auto lookbehind_result = evaluate(std::make_reverse_iterator(last), std::make_reverse_iterator(current), std::make_reverse_iterator(begin), f, captures, ctll::list<sequence<Content...>, end_lookbehind_mark>())) {
5096 : return not_matched;
5097 : } else {
5098 : return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
5099 : }
5100 : }
5101 :
5102 : template <typename...> constexpr auto dependent_false = false;
5103 :
5104 : // atomic_group<...> is just transformation to possessive_repeat<1,1,...>
5105 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Content, typename... Tail>
5106 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<atomic_group<Content...>, Tail...>) noexcept {
5107 : return evaluate(begin, current, last, f, captures, ctll::list<possessive_repeat<1,1,Content...>, Tail...>{});
5108 : }
5109 :
5110 : // switching modes
5111 : template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename Mode, typename... Tail>
5112 : constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<mode_switch<Mode>, Tail...>) noexcept {
5113 : return evaluate(begin, current, last, f + Mode{}, captures, ctll::list<Tail...>());
5114 : }
5115 :
5116 : }
5117 :
5118 : #endif
5119 :
5120 : #ifndef CTRE__WRAPPER__HPP
5121 : #define CTRE__WRAPPER__HPP
5122 :
5123 : #ifndef CTRE_V2__CTRE__RANGE__HPP
5124 : #define CTRE_V2__CTRE__RANGE__HPP
5125 :
5126 : #ifndef CTRE_V2__CTRE__ITERATOR__HPP
5127 : #define CTRE_V2__CTRE__ITERATOR__HPP
5128 :
5129 : #ifndef CTRE_IN_A_MODULE
5130 : #include <cstddef>
5131 : #endif
5132 :
5133 : namespace ctre {
5134 :
5135 : // TODO make proper iterator traits here
5136 :
5137 : struct regex_end_iterator {
5138 : constexpr regex_end_iterator() noexcept { }
5139 : };
5140 :
5141 : template <typename BeginIterator, typename EndIterator, typename RE, typename ResultIterator = BeginIterator> struct regex_iterator {
5142 : using value_type = decltype(RE::template exec_with_result_iterator<ResultIterator>(std::declval<BeginIterator>(), std::declval<EndIterator>()));
5143 : using iterator_category = std::forward_iterator_tag;
5144 : using pointer = void;
5145 : using reference = const value_type &;
5146 : using difference_type = int;
5147 :
5148 : BeginIterator orig_begin{};
5149 : BeginIterator current{};
5150 : EndIterator end{};
5151 : value_type current_match{};
5152 :
5153 : constexpr CTRE_FORCE_INLINE regex_iterator() noexcept = default;
5154 : constexpr CTRE_FORCE_INLINE regex_iterator(const regex_iterator &) noexcept = default;
5155 : constexpr CTRE_FORCE_INLINE regex_iterator(regex_iterator &&) noexcept = default;
5156 :
5157 : constexpr CTRE_FORCE_INLINE regex_iterator(BeginIterator begin, EndIterator last) noexcept: orig_begin{begin}, current{begin}, end{last}, current_match{RE::template exec_with_result_iterator<ResultIterator>(current, last)} {
5158 : if (current_match) {
5159 : current = current_match.template get<0>().end();
5160 : }
5161 : }
5162 :
5163 : constexpr CTRE_FORCE_INLINE regex_iterator & operator=(const regex_iterator &) noexcept = default;
5164 : constexpr CTRE_FORCE_INLINE regex_iterator & operator=(regex_iterator &&) noexcept = default;
5165 :
5166 : constexpr CTRE_FORCE_INLINE const value_type & operator*() const noexcept {
5167 : return current_match;
5168 : }
5169 : constexpr CTRE_FORCE_INLINE regex_iterator & operator++() noexcept {
5170 : if (current == end) {
5171 : current_match = decltype(current_match){};
5172 : return *this;
5173 : }
5174 :
5175 : current_match = RE::template exec_with_result_iterator<ResultIterator>(orig_begin, current, end);
5176 :
5177 : if (current_match) {
5178 : current = current_match.template get<0>().end();
5179 : }
5180 : return *this;
5181 : }
5182 : constexpr CTRE_FORCE_INLINE regex_iterator operator++(int) noexcept {
5183 : auto previous = *this;
5184 : this->operator++();
5185 : return previous;
5186 : }
5187 : friend constexpr CTRE_FORCE_INLINE bool operator==(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5188 : return left.current == right.current;
5189 : }
5190 : friend constexpr CTRE_FORCE_INLINE bool operator!=(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5191 : return !(left.current == right.current);
5192 : }
5193 : friend constexpr CTRE_FORCE_INLINE bool operator<(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5194 : return left.current < right.current;
5195 : }
5196 : friend constexpr CTRE_FORCE_INLINE bool operator>(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5197 : return left.current > right.current;
5198 : }
5199 : friend constexpr CTRE_FORCE_INLINE bool operator<=(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5200 : return left.current <= right.current;
5201 : }
5202 : friend constexpr CTRE_FORCE_INLINE bool operator>=(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5203 : return left.current >= right.current;
5204 : }
5205 : friend constexpr CTRE_FORCE_INLINE bool operator==(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, regex_end_iterator) noexcept {
5206 : return !bool(left.current_match);
5207 : }
5208 : friend constexpr CTRE_FORCE_INLINE bool operator==(regex_end_iterator, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5209 : return !bool(right.current_match);
5210 : }
5211 : friend constexpr CTRE_FORCE_INLINE bool operator!=(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, regex_end_iterator) noexcept {
5212 : return bool(left.current_match);
5213 : }
5214 : friend constexpr CTRE_FORCE_INLINE bool operator!=(regex_end_iterator, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5215 : return bool(right.current_match);
5216 : }
5217 : };
5218 :
5219 : template <typename BeginIterator, typename EndIterator, typename RE, typename ResultIterator = BeginIterator> struct regex_split_iterator {
5220 : using value_type = decltype(RE::template exec_with_result_iterator<ResultIterator>(std::declval<BeginIterator>(), std::declval<EndIterator>()));
5221 : using iterator_category = std::forward_iterator_tag;
5222 : using pointer = void;
5223 : using reference = const value_type &;
5224 : using difference_type = int;
5225 :
5226 : BeginIterator orig_begin{};
5227 : BeginIterator current{};
5228 : EndIterator end{};
5229 : value_type current_match{};
5230 : bool last_match{false};
5231 :
5232 : constexpr CTRE_FORCE_INLINE void modify_match() {
5233 : auto tmp = current_match.template get<0>().end();
5234 : current_match.set_end_mark(current_match.template get<0>().begin());
5235 : current_match.set_start_mark(current);
5236 : current = tmp;
5237 : }
5238 :
5239 : constexpr CTRE_FORCE_INLINE void match_rest() {
5240 : // the end is there set by search_method
5241 : current_match.set_start_mark(current);
5242 : current_match.matched();
5243 : current = current_match.template get<0>().end();
5244 : last_match = true;
5245 : }
5246 :
5247 : constexpr CTRE_FORCE_INLINE regex_split_iterator() noexcept = default;
5248 : constexpr CTRE_FORCE_INLINE regex_split_iterator(const regex_split_iterator &) noexcept = default;
5249 : constexpr CTRE_FORCE_INLINE regex_split_iterator(regex_split_iterator &&) noexcept = default;
5250 :
5251 : constexpr CTRE_FORCE_INLINE regex_split_iterator(BeginIterator begin, EndIterator last) noexcept: orig_begin{begin}, current{begin}, end{last}, current_match{RE::template exec_with_result_iterator<ResultIterator>(current, last)} {
5252 : if (current_match) {
5253 : modify_match();
5254 : } else {
5255 : match_rest();
5256 : }
5257 : }
5258 :
5259 : constexpr CTRE_FORCE_INLINE regex_split_iterator & operator=(const regex_split_iterator &) noexcept = default;
5260 : constexpr CTRE_FORCE_INLINE regex_split_iterator & operator=(regex_split_iterator &&) noexcept = default;
5261 :
5262 : constexpr CTRE_FORCE_INLINE const value_type & operator*() const noexcept {
5263 : return current_match;
5264 : }
5265 : constexpr CTRE_FORCE_INLINE regex_split_iterator & operator++() noexcept {
5266 : if (current == end && last_match) {
5267 : current_match = decltype(current_match){};
5268 : return *this;
5269 : }
5270 :
5271 : current_match = RE::template exec_with_result_iterator<ResultIterator>(orig_begin, current, end);
5272 :
5273 : if (current_match) {
5274 : modify_match();
5275 : } else {
5276 : match_rest();
5277 : }
5278 : return *this;
5279 : }
5280 : constexpr CTRE_FORCE_INLINE regex_split_iterator operator++(int) noexcept {
5281 : auto previous = *this;
5282 : this->operator++();
5283 : return previous;
5284 : }
5285 : friend constexpr CTRE_FORCE_INLINE bool operator==(const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5286 : return left.current == right.current;
5287 : }
5288 : friend constexpr CTRE_FORCE_INLINE bool operator!=(const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5289 : return !(left.current == right.current);
5290 : }
5291 : friend constexpr CTRE_FORCE_INLINE bool operator<(const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5292 : return left.current < right.current;
5293 : }
5294 : friend constexpr CTRE_FORCE_INLINE bool operator>(const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5295 : return left.current > right.current;
5296 : }
5297 : friend constexpr CTRE_FORCE_INLINE bool operator<=(const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5298 : return left.current <= right.current;
5299 : }
5300 : friend constexpr CTRE_FORCE_INLINE bool operator>=(const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5301 : return left.current >= right.current;
5302 : }
5303 : friend constexpr CTRE_FORCE_INLINE bool operator==(const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, regex_end_iterator) noexcept {
5304 : return !bool(left.current_match);
5305 : }
5306 : friend constexpr CTRE_FORCE_INLINE bool operator==(regex_end_iterator, const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5307 : return !bool(right.current_match);
5308 : }
5309 : friend constexpr CTRE_FORCE_INLINE bool operator!=(const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, regex_end_iterator) noexcept {
5310 : return bool(left.current_match);
5311 : }
5312 : friend constexpr CTRE_FORCE_INLINE bool operator!=(regex_end_iterator, const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
5313 : return bool(right.current_match);
5314 : }
5315 : };
5316 :
5317 : } // ctre
5318 :
5319 : #endif
5320 :
5321 : namespace ctre {
5322 :
5323 : template <typename> constexpr bool is_range = false;
5324 :
5325 : template <typename BeginIterator, typename EndIterator, typename RE, typename ResultIterator = BeginIterator> struct regex_range {
5326 : BeginIterator _begin;
5327 : EndIterator _end;
5328 :
5329 : constexpr CTRE_FORCE_INLINE regex_range(BeginIterator begin, EndIterator end) noexcept: _begin{begin}, _end{end} { }
5330 :
5331 : constexpr CTRE_FORCE_INLINE auto begin() const noexcept {
5332 : return regex_iterator<BeginIterator, EndIterator, RE, ResultIterator>(_begin, _end);
5333 : }
5334 : constexpr CTRE_FORCE_INLINE auto end() const noexcept {
5335 : return regex_end_iterator{};
5336 : }
5337 : };
5338 :
5339 : template <typename... Ts> constexpr bool is_range<regex_range<Ts...>> = true;
5340 :
5341 : template <typename BeginIterator, typename EndIterator, typename RE, typename ResultIterator = BeginIterator> struct regex_split_range {
5342 : BeginIterator _begin;
5343 : EndIterator _end;
5344 :
5345 : constexpr CTRE_FORCE_INLINE regex_split_range(BeginIterator begin, EndIterator end) noexcept: _begin{begin}, _end{end} { }
5346 :
5347 : constexpr CTRE_FORCE_INLINE auto begin() const noexcept {
5348 : return regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator>(_begin, _end);
5349 : }
5350 : constexpr CTRE_FORCE_INLINE auto end() const noexcept {
5351 : return regex_end_iterator{};
5352 : }
5353 : };
5354 :
5355 : template <typename... Ts> constexpr bool is_range<regex_split_range<Ts...>> = true;
5356 :
5357 : template <typename Range, typename RE> struct multi_subject_range {
5358 : struct end_iterator { };
5359 :
5360 : using first_type = decltype(std::declval<Range>().begin());
5361 : using last_type = decltype(std::declval<Range>().end());
5362 :
5363 : struct iterator {
5364 : using value_type = decltype(RE::exec(std::declval<typename std::iterator_traits<first_type>::value_type>()));
5365 : using iterator_category = std::forward_iterator_tag;
5366 : using reference = const value_type &;
5367 : using pointer = const value_type *;
5368 : using difference_type = int;
5369 :
5370 : first_type first{};
5371 : last_type last{};
5372 : value_type current_result{};
5373 :
5374 : constexpr CTRE_FORCE_INLINE iterator() noexcept = default;
5375 : constexpr CTRE_FORCE_INLINE iterator(first_type f, last_type l) noexcept: first{f}, last{l}, current_result{find_first()} { }
5376 :
5377 : constexpr CTRE_FORCE_INLINE value_type find_first() noexcept {
5378 : while (first != last) {
5379 : if (auto res = RE::exec(*first)) return res;
5380 : else ++first;
5381 : }
5382 : return {};
5383 : }
5384 :
5385 : constexpr CTRE_FORCE_INLINE reference operator*() const noexcept {
5386 : return current_result;
5387 : }
5388 :
5389 : constexpr CTRE_FORCE_INLINE pointer operator->() const noexcept {
5390 : return ¤t_result;
5391 : }
5392 :
5393 : constexpr CTRE_FORCE_INLINE iterator & operator++() noexcept {
5394 : ++first;
5395 : current_result = find_first();
5396 : return *this;
5397 : }
5398 : constexpr CTRE_FORCE_INLINE iterator operator++(int) noexcept {
5399 : auto previous = *this;
5400 : this->operator++();
5401 : return previous;
5402 : }
5403 :
5404 : friend constexpr CTRE_FORCE_INLINE bool operator==(const iterator & left, const iterator & right) noexcept {
5405 : return left.first == right.first;
5406 : }
5407 : friend constexpr CTRE_FORCE_INLINE bool operator!=(const iterator & left, const iterator & right) noexcept {
5408 : return !(left.first == right.first);
5409 : }
5410 : friend constexpr CTRE_FORCE_INLINE bool operator<(const iterator & left, const iterator & right) noexcept {
5411 : return left.first < right.first;
5412 : }
5413 : friend constexpr CTRE_FORCE_INLINE bool operator>(const iterator & left, const iterator & right) noexcept {
5414 : return left.first > right.first;
5415 : }
5416 : friend constexpr CTRE_FORCE_INLINE bool operator<=(const iterator & left, const iterator & right) noexcept {
5417 : return left.first <= right.first;
5418 : }
5419 : friend constexpr CTRE_FORCE_INLINE bool operator>=(const iterator & left, const iterator & right) noexcept {
5420 : return left.first >= right.first;
5421 : }
5422 : friend constexpr CTRE_FORCE_INLINE bool operator==(const iterator & left, end_iterator) noexcept {
5423 : return left.first == left.last;
5424 : }
5425 : friend constexpr CTRE_FORCE_INLINE bool operator==(end_iterator, const iterator & right) noexcept {
5426 : return right.first == right.last;
5427 : }
5428 : friend constexpr CTRE_FORCE_INLINE bool operator!=(const iterator & left, end_iterator) noexcept {
5429 : return left.first != left.last;
5430 : }
5431 : friend constexpr CTRE_FORCE_INLINE bool operator!=(end_iterator, const iterator & right) noexcept {
5432 : return right.first == right.last;
5433 : }
5434 : };
5435 :
5436 : Range range{};
5437 :
5438 : constexpr CTRE_FORCE_INLINE multi_subject_range() noexcept = default;
5439 : constexpr CTRE_FORCE_INLINE multi_subject_range(Range r) noexcept: range{r} { }
5440 :
5441 : constexpr CTRE_FORCE_INLINE auto begin() const noexcept {
5442 : return iterator{range.begin(), range.end()};
5443 : }
5444 : constexpr CTRE_FORCE_INLINE auto end() const noexcept {
5445 : return end_iterator{};
5446 : }
5447 : };
5448 :
5449 : // this is not regex range!
5450 : template <typename... Ts> constexpr bool is_range<multi_subject_range<Ts...>> = true;
5451 :
5452 : }
5453 :
5454 : #if defined __cpp_lib_ranges && __cpp_lib_ranges >= 201911
5455 : namespace std::ranges {
5456 :
5457 : template <typename... Ts> inline constexpr bool enable_borrowed_range<::ctre::regex_range<Ts...>> = true;
5458 : template <typename... Ts> inline constexpr bool enable_borrowed_range<::ctre::regex_split_range<Ts...>> = true;
5459 : template <typename Range, typename RE> inline constexpr bool enable_borrowed_range<::ctre::multi_subject_range<Range, RE>> = enable_borrowed_range<Range>;
5460 : template <typename Range, typename RE> inline constexpr bool enable_view<::ctre::multi_subject_range<Range, RE>> = true;
5461 :
5462 : }
5463 : #endif
5464 :
5465 : #endif
5466 :
5467 : #ifndef CTRE_IN_A_MODULE
5468 : #include <string_view>
5469 : #endif
5470 :
5471 : namespace ctre {
5472 :
5473 : CTRE_EXPORT template <typename RE, typename Method = void, typename Modifier = singleline> struct regular_expression;
5474 :
5475 : struct zero_terminated_string_end_iterator {
5476 : // this is here only because I want to support std::make_reverse_iterator
5477 : using self_type = zero_terminated_string_end_iterator;
5478 : using value_type = char;
5479 : using reference = char &;
5480 : using pointer = const char *;
5481 : using iterator_category = std::bidirectional_iterator_tag;
5482 : using difference_type = int;
5483 :
5484 : // it's just sentinel it won't be ever called
5485 : auto operator++() noexcept -> self_type &;
5486 : auto operator++(int) noexcept -> self_type;
5487 : auto operator--() noexcept -> self_type &;
5488 : auto operator--(int) noexcept -> self_type;
5489 : friend auto operator==(self_type, self_type) noexcept -> bool;
5490 : auto operator*() noexcept -> reference;
5491 :
5492 : constexpr CTRE_FORCE_INLINE friend bool operator==(const char * ptr, zero_terminated_string_end_iterator) noexcept {
5493 0 : return *ptr == '\0';
5494 : }
5495 : constexpr CTRE_FORCE_INLINE friend bool operator==(const wchar_t * ptr, zero_terminated_string_end_iterator) noexcept {
5496 : return *ptr == 0;
5497 : }
5498 : constexpr CTRE_FORCE_INLINE friend bool operator!=(const char * ptr, zero_terminated_string_end_iterator) noexcept {
5499 0 : return *ptr != '\0';
5500 : }
5501 : constexpr CTRE_FORCE_INLINE friend bool operator!=(const wchar_t * ptr, zero_terminated_string_end_iterator) noexcept {
5502 : return *ptr != 0;
5503 : }
5504 : constexpr CTRE_FORCE_INLINE friend bool operator==(zero_terminated_string_end_iterator, const char * ptr) noexcept {
5505 0 : return *ptr == '\0';
5506 : }
5507 : constexpr CTRE_FORCE_INLINE friend bool operator==(zero_terminated_string_end_iterator, const wchar_t * ptr) noexcept {
5508 : return *ptr == 0;
5509 : }
5510 : constexpr CTRE_FORCE_INLINE friend bool operator!=(zero_terminated_string_end_iterator, const char * ptr) noexcept {
5511 0 : return *ptr != '\0';
5512 : }
5513 : constexpr CTRE_FORCE_INLINE friend bool operator!=(zero_terminated_string_end_iterator, const wchar_t * ptr) noexcept {
5514 : return *ptr != 0;
5515 : }
5516 : };
5517 :
5518 : template <typename T> class RangeLikeType {
5519 : template <typename Y> static auto test(Y *) -> decltype(std::declval<const Y &>().begin(), std::declval<const Y &>().end(), std::true_type());
5520 : template <typename> static auto test(...) -> std::false_type;
5521 :
5522 : public:
5523 : static constexpr bool value = decltype(test<std::remove_reference_t<std::remove_const_t<T>>>(nullptr))::value;
5524 : };
5525 :
5526 : struct match_method {
5527 : template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin orig_begin, IteratorBegin begin, IteratorEnd end, RE) noexcept {
5528 : using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
5529 :
5530 0 : return evaluate(orig_begin, begin, end, Modifier{}, return_type<result_iterator, RE>{}, ctll::list<start_mark, RE, assert_subject_end, end_mark, accept>());
5531 : }
5532 :
5533 : template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin begin, IteratorEnd end, RE) noexcept {
5534 0 : return exec<Modifier, ResultIterator>(begin, begin, end, RE{});
5535 : }
5536 : };
5537 :
5538 : struct search_method {
5539 : template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin orig_begin, IteratorBegin begin, IteratorEnd end, RE) noexcept {
5540 : using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
5541 :
5542 0 : constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list<RE>{});
5543 :
5544 0 : auto it = begin;
5545 :
5546 0 : for (; end != it && !fixed; ++it) {
5547 0 : if (auto out = evaluate(orig_begin, it, end, Modifier{}, return_type<result_iterator, RE>{}, ctll::list<start_mark, RE, end_mark, accept>())) {
5548 0 : return out;
5549 : }
5550 : }
5551 :
5552 : // in case the RE is empty or fixed
5553 0 : auto out = evaluate(orig_begin, it, end, Modifier{}, return_type<result_iterator, RE>{}, ctll::list<start_mark, RE, end_mark, accept>());
5554 :
5555 : // ALERT: ugly hack
5556 : // propagate end even if it didn't match (this is needed for split function)
5557 0 : if (!out) out.set_end_mark(it);
5558 0 : return out;
5559 : }
5560 :
5561 : template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin begin, IteratorEnd end, RE) noexcept {
5562 0 : return exec<Modifier, ResultIterator>(begin, begin, end, RE{});
5563 : }
5564 : };
5565 :
5566 : struct starts_with_method {
5567 : template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin orig_begin, IteratorBegin begin, IteratorEnd end, RE) noexcept {
5568 : using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
5569 : return evaluate(orig_begin, begin, end, Modifier{}, return_type<result_iterator, RE>{}, ctll::list<start_mark, RE, end_mark, accept>());
5570 : }
5571 :
5572 : template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin begin, IteratorEnd end, RE) noexcept {
5573 : return exec<Modifier, ResultIterator>(begin, begin, end, RE{});
5574 : }
5575 : };
5576 :
5577 : // wrapper which calls search on input
5578 : struct range_method {
5579 : template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin begin, IteratorEnd end, RE) noexcept {
5580 : using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
5581 : using wrapped_regex = regular_expression<RE, search_method, Modifier>;
5582 :
5583 : return regex_range<IteratorBegin, IteratorEnd, wrapped_regex, result_iterator>(begin, end);
5584 : }
5585 : };
5586 :
5587 : struct tokenize_method {
5588 : template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin begin, IteratorEnd end, RE) noexcept {
5589 : using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
5590 : using wrapped_regex = regular_expression<RE, starts_with_method, Modifier>;
5591 :
5592 : return regex_range<IteratorBegin, IteratorEnd, wrapped_regex, result_iterator>(begin, end);
5593 : }
5594 : };
5595 :
5596 : struct split_method {
5597 : template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin begin, IteratorEnd end, RE) noexcept {
5598 : using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
5599 : using wrapped_regex = regular_expression<RE, search_method, Modifier>;
5600 :
5601 : return regex_split_range<IteratorBegin, IteratorEnd, wrapped_regex, result_iterator>(begin, end);
5602 : }
5603 : };
5604 :
5605 : struct iterator_method {
5606 : template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin begin, IteratorEnd end, RE) noexcept {
5607 : using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
5608 : using wrapped_regex = regular_expression<RE, search_method, Modifier>;
5609 :
5610 : return regex_iterator<IteratorBegin, IteratorEnd, wrapped_regex, result_iterator>(begin, end);
5611 : }
5612 : constexpr CTRE_FORCE_INLINE static auto exec() noexcept {
5613 : return regex_end_iterator{};
5614 : }
5615 : };
5616 :
5617 : CTRE_EXPORT template <typename RE, typename Method, typename Modifier> struct regular_expression {
5618 : constexpr CTRE_FORCE_INLINE regular_expression() noexcept { }
5619 : constexpr CTRE_FORCE_INLINE regular_expression(RE) noexcept { }
5620 :
5621 : template <typename ResultIterator, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec_with_result_iterator(IteratorBegin orig_begin, IteratorBegin begin, IteratorEnd end) noexcept {
5622 : return Method::template exec<Modifier, ResultIterator>(orig_begin, begin, end, RE{});
5623 : }
5624 : template <typename ResultIterator, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec_with_result_iterator(IteratorBegin begin, IteratorEnd end) noexcept {
5625 : return Method::template exec<Modifier, ResultIterator>(begin, end, RE{});
5626 : }
5627 : template <typename Range> constexpr CTRE_FORCE_INLINE static auto multi_exec(Range && range) noexcept {
5628 : return multi_subject_range<Range, regular_expression>{std::forward<Range>(range)};
5629 : }
5630 : constexpr CTRE_FORCE_INLINE static auto exec() noexcept {
5631 : return Method::exec();
5632 : }
5633 : template <typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin begin, IteratorEnd end) noexcept {
5634 0 : return Method::template exec<Modifier>(begin, end, RE{});
5635 : }
5636 : static constexpr CTRE_FORCE_INLINE auto exec(const char * s) noexcept {
5637 0 : return Method::template exec<Modifier>(s, zero_terminated_string_end_iterator(), RE{});
5638 : }
5639 : static constexpr CTRE_FORCE_INLINE auto exec(const wchar_t * s) noexcept {
5640 : return Method::template exec<Modifier>(s, zero_terminated_string_end_iterator(), RE{});
5641 : }
5642 : static constexpr CTRE_FORCE_INLINE auto exec(std::string_view sv) noexcept {
5643 : return exec(sv.begin(), sv.end());
5644 : }
5645 : static constexpr CTRE_FORCE_INLINE auto exec(std::wstring_view sv) noexcept {
5646 : return exec(sv.begin(), sv.end());
5647 : }
5648 : #ifdef CTRE_ENABLE_UTF8_RANGE
5649 : static constexpr CTRE_FORCE_INLINE auto exec(std::u8string_view sv) noexcept {
5650 : return exec_with_result_iterator<const char8_t *>(utf8_range(sv).begin(), utf8_range(sv).end());
5651 : }
5652 : #endif
5653 : static constexpr CTRE_FORCE_INLINE auto exec(std::u16string_view sv) noexcept {
5654 : return exec(sv.begin(), sv.end());
5655 : }
5656 : static constexpr CTRE_FORCE_INLINE auto exec(std::u32string_view sv) noexcept {
5657 : return exec(sv.begin(), sv.end());
5658 : }
5659 : template <typename Range, typename = typename std::enable_if<RangeLikeType<Range>::value>::type> static constexpr CTRE_FORCE_INLINE auto exec(Range && range) noexcept {
5660 0 : return exec(std::begin(range), std::end(range));
5661 : }
5662 :
5663 : // another api
5664 : template <typename... Args> CTRE_FORCE_INLINE constexpr auto operator()(Args &&... args) const noexcept {
5665 0 : return exec(std::forward<Args>(args)...);
5666 : }
5667 : // api for pattern matching
5668 : template <typename... Args> CTRE_FORCE_INLINE constexpr auto try_extract(Args &&... args) const noexcept {
5669 : return exec(std::forward<Args>(args)...);
5670 : }
5671 :
5672 : // for compatibility with _ctre literal
5673 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto match(Args &&... args) noexcept {
5674 : return regular_expression<RE, match_method, singleline>::exec(std::forward<Args>(args)...);
5675 : }
5676 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto search(Args &&... args) noexcept {
5677 : return regular_expression<RE, search_method, singleline>::exec(std::forward<Args>(args)...);
5678 : }
5679 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto starts_with(Args &&... args) noexcept {
5680 : return regular_expression<RE, starts_with_method, singleline>::exec(std::forward<Args>(args)...);
5681 : }
5682 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto range(Args &&... args) noexcept {
5683 : return regular_expression<RE, range_method, singleline>::exec(std::forward<Args>(args)...);
5684 : }
5685 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto split(Args &&... args) noexcept {
5686 : return regular_expression<RE, split_method, singleline>::exec(std::forward<Args>(args)...);
5687 : }
5688 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto tokenize(Args &&... args) noexcept {
5689 : return regular_expression<RE, tokenize_method, singleline>::exec(std::forward<Args>(args)...);
5690 : }
5691 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto iterator(Args &&... args) noexcept {
5692 : return regular_expression<RE, iterator_method, singleline>::exec(std::forward<Args>(args)...);
5693 : }
5694 :
5695 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_match(Args &&... args) noexcept {
5696 : return regular_expression<RE, match_method, multiline>::exec(std::forward<Args>(args)...);
5697 : }
5698 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_search(Args &&... args) noexcept {
5699 : return regular_expression<RE, search_method, multiline>::exec(std::forward<Args>(args)...);
5700 : }
5701 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_starts_with(Args &&... args) noexcept {
5702 : return regular_expression<RE, starts_with_method, multiline>::exec(std::forward<Args>(args)...);
5703 : }
5704 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_range(Args &&... args) noexcept {
5705 : return regular_expression<RE, range_method, multiline>::exec(std::forward<Args>(args)...);
5706 : }
5707 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_split(Args &&... args) noexcept {
5708 : return regular_expression<RE, split_method, multiline>::exec(std::forward<Args>(args)...);
5709 : }
5710 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_tokenize(Args &&... args) noexcept {
5711 : return regular_expression<RE, tokenize_method, multiline>::exec(std::forward<Args>(args)...);
5712 : }
5713 : template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_iterator(Args &&... args) noexcept {
5714 : return regular_expression<RE, iterator_method, multiline>::exec(std::forward<Args>(args)...);
5715 : }
5716 : };
5717 :
5718 : // range style API support for tokenize/range/split operations
5719 : template <typename Range, typename RE, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, range_method, Modifier> re) noexcept {
5720 : return re.exec(std::forward<Range>(range));
5721 : }
5722 :
5723 : template <typename Range, typename RE, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, tokenize_method, Modifier> re) noexcept {
5724 : return re.exec(std::forward<Range>(range));
5725 : }
5726 :
5727 : template <typename Range, typename RE, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, split_method, Modifier> re) noexcept {
5728 : return re.exec(std::forward<Range>(range));
5729 : }
5730 :
5731 : template <typename Range, typename RE, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, iterator_method, Modifier> re) noexcept = delete;
5732 :
5733 : template <typename Range, typename RE, typename Method, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, Method, Modifier> re) noexcept {
5734 : return re.multi_exec(std::forward<Range>(range));
5735 : }
5736 :
5737 : // error reporting of problematic position in a regex
5738 : template <size_t> struct problem_at_position; // do not define!
5739 :
5740 : template <> struct problem_at_position<~static_cast<size_t>(0)> {
5741 : constexpr operator bool() const noexcept {
5742 : return true;
5743 : }
5744 : };
5745 :
5746 : #if CTRE_CNTTP_COMPILER_CHECK
5747 : #define CTRE_REGEX_INPUT_TYPE ctll::fixed_string
5748 : #define CTRE_REGEX_TEMPLATE_COPY_TYPE auto
5749 : #else
5750 : #define CTRE_REGEX_INPUT_TYPE const auto &
5751 : #define CTRE_REGEX_TEMPLATE_COPY_TYPE const auto &
5752 : #endif
5753 :
5754 : template <CTRE_REGEX_TEMPLATE_COPY_TYPE input> struct regex_builder {
5755 : static constexpr auto _input = input;
5756 : using result = typename ctll::parser<ctre::pcre, _input, ctre::pcre_actions>::template output<pcre_context<>>;
5757 :
5758 : static constexpr auto n = result::is_correct ? ~static_cast<size_t>(0) : result::position;
5759 :
5760 : static_assert(result::is_correct && problem_at_position<n>{}, "Regular Expression contains syntax error.");
5761 :
5762 : using type = ctll::conditional<result::is_correct, decltype(ctll::front(typename result::output_type::stack_type())), ctll::list<reject>>;
5763 : };
5764 :
5765 : // case-sensitive
5766 :
5767 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto match = regular_expression<typename regex_builder<input>::type, match_method, ctll::list<singleline, Modifiers...>>();
5768 :
5769 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto search = regular_expression<typename regex_builder<input>::type, search_method, ctll::list<singleline, Modifiers...>>();
5770 :
5771 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto starts_with = regular_expression<typename regex_builder<input>::type, starts_with_method, ctll::list<singleline, Modifiers...>>();
5772 :
5773 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto search_all = regular_expression<typename regex_builder<input>::type, range_method, ctll::list<singleline, Modifiers...>>();
5774 :
5775 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> [[deprecated("use search_all")]] constexpr auto range = regular_expression<typename regex_builder<input>::type, range_method, ctll::list<singleline, Modifiers...>>();
5776 :
5777 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto split = regular_expression<typename regex_builder<input>::type, split_method, ctll::list<singleline, Modifiers...>>();
5778 :
5779 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto tokenize = regular_expression<typename regex_builder<input>::type, tokenize_method, ctll::list<singleline, Modifiers...>>();
5780 :
5781 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto iterator = regular_expression<typename regex_builder<input>::type, iterator_method, ctll::list<singleline, Modifiers...>>();
5782 :
5783 : CTRE_EXPORT constexpr auto sentinel = regex_end_iterator();
5784 :
5785 : // multiline
5786 :
5787 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto multiline_match = regular_expression<typename regex_builder<input>::type, match_method, ctll::list<multiline, Modifiers...>>();
5788 :
5789 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto multiline_search = regular_expression<typename regex_builder<input>::type, search_method, ctll::list<multiline, Modifiers...>>();
5790 :
5791 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto multiline_starts_with = regular_expression<typename regex_builder<input>::type, starts_with_method, ctll::list<multiline, Modifiers...>>();
5792 :
5793 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto multiline_search_all = regular_expression<typename regex_builder<input>::type, range_method, ctll::list<multiline, Modifiers...>>();
5794 :
5795 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> [[deprecated("use multiline_search_all")]] constexpr auto multiline_range = regular_expression<typename regex_builder<input>::type, range_method, ctll::list<multiline, Modifiers...>>();
5796 :
5797 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto multiline_split = regular_expression<typename regex_builder<input>::type, split_method, ctll::list<multiline, Modifiers...>>();
5798 :
5799 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto multiline_tokenize = regular_expression<typename regex_builder<input>::type, tokenize_method, ctll::list<multiline, Modifiers...>>();
5800 :
5801 : CTRE_EXPORT template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> constexpr auto multiline_iterator = regular_expression<typename regex_builder<input>::type, iterator_method, ctll::list<multiline, Modifiers...>>();
5802 :
5803 : CTRE_EXPORT constexpr auto multiline_sentinel = regex_end_iterator();
5804 :
5805 : } // namespace ctre
5806 :
5807 : #endif
5808 :
5809 : #ifndef __EDG__
5810 :
5811 : namespace ctre {
5812 :
5813 : // in C++17 (clang & gcc with gnu extension) we need translate character pack into ctll::fixed_string
5814 : // in C++20 we have `class nontype template parameters`
5815 :
5816 : #if !CTRE_CNTTP_COMPILER_CHECK
5817 : template <typename CharT, CharT... input> static inline constexpr auto _fixed_string_reference = ctll::fixed_string< sizeof...(input)>({input...});
5818 : #endif
5819 :
5820 : namespace literals {
5821 :
5822 : // clang and GCC <9 supports LITERALS with packs
5823 :
5824 : #ifdef __clang__
5825 : #pragma clang diagnostic push
5826 : #pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
5827 : #define CTRE_ENABLE_LITERALS
5828 : #endif
5829 :
5830 : #ifdef _MSC_VER
5831 : #ifdef _MSVC_LANG
5832 : #if _MSVC_LANG >= 202002L
5833 : #define CTRE_ENABLE_LITERALS
5834 : #endif
5835 : #else
5836 : #define CTRE_ENABLE_LITERALS
5837 : #endif
5838 : #endif
5839 :
5840 : #ifdef __INTEL_COMPILER
5841 : // not enable literals
5842 : #elif defined __GNUC__
5843 : #if __GNUC__ < 9
5844 : #define CTRE_ENABLE_LITERALS
5845 : #elif __GNUC__ >= 10
5846 : #if !CTRE_CNTTP_COMPILER_CHECK
5847 : // newer versions of GCC will give error when trying to use GNU extension
5848 : #else
5849 : #define CTRE_ENABLE_LITERALS
5850 : #endif
5851 : #endif
5852 : #endif
5853 :
5854 : #ifdef CTRE_ENABLE_LITERALS
5855 :
5856 : // add this when we will have concepts
5857 : // requires ctll::parser<ctre::pcre, _fixed_string_reference<CharT, charpack...>, ctre::pcre_actions>::template correct_with<pcre_context<>>
5858 :
5859 : #if !CTRE_CNTTP_COMPILER_CHECK
5860 : template <typename CharT, CharT... charpack> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto operator""_ctre() noexcept {
5861 : constexpr auto & _input = _fixed_string_reference<CharT, charpack...>;
5862 : #else
5863 : template <ctll::fixed_string input> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto operator""_ctre() noexcept {
5864 : constexpr auto _input = input; // workaround for GCC 9 bug 88092
5865 : #endif
5866 : using tmp = typename ctll::parser<ctre::pcre, _input, ctre::pcre_actions>::template output<pcre_context<>>;
5867 : static_assert(tmp(), "Regular Expression contains syntax error.");
5868 : if constexpr (tmp()) {
5869 : using re = decltype(front(typename tmp::output_type::stack_type()));
5870 : return ctre::regular_expression(re());
5871 : } else {
5872 : return ctre::regular_expression(reject());
5873 : }
5874 : }
5875 :
5876 : // this will need to be fixed with C++20
5877 : #if !CTRE_CNTTP_COMPILER_CHECK
5878 : template <typename CharT, CharT... charpack> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto operator""_ctre_id() noexcept {
5879 : return id<charpack...>();
5880 : }
5881 : #endif
5882 :
5883 : #endif // CTRE_ENABLE_LITERALS
5884 :
5885 : }
5886 :
5887 : namespace test_literals {
5888 :
5889 : #ifdef CTRE_ENABLE_LITERALS
5890 :
5891 : #if !CTRE_CNTTP_COMPILER_CHECK
5892 : template <typename CharT, CharT... charpack> CTRE_FLATTEN constexpr inline auto operator""_ctre_test() noexcept {
5893 : constexpr auto & _input = _fixed_string_reference<CharT, charpack...>;
5894 : #else
5895 : template <ctll::fixed_string input> CTRE_FLATTEN constexpr inline auto operator""_ctre_test() noexcept {
5896 : constexpr auto _input = input; // workaround for GCC 9 bug 88092
5897 : #endif
5898 : return ctll::parser<ctre::pcre, _input>::template correct_with<>;
5899 : }
5900 :
5901 : #if !CTRE_CNTTP_COMPILER_CHECK
5902 : template <typename CharT, CharT... charpack> CTRE_FLATTEN constexpr inline auto operator""_ctre_gen() noexcept {
5903 : constexpr auto & _input = _fixed_string_reference<CharT, charpack...>;
5904 : #else
5905 : template <ctll::fixed_string input> CTRE_FLATTEN constexpr inline auto operator""_ctre_gen() noexcept {
5906 : constexpr auto _input = input; // workaround for GCC 9 bug 88092
5907 : #endif
5908 : using tmp = typename ctll::parser<ctre::pcre, _input, ctre::pcre_actions>::template output<pcre_context<>>;
5909 : static_assert(tmp(), "Regular Expression contains syntax error.");
5910 : return typename tmp::output_type::stack_type();
5911 : }
5912 :
5913 : #if !CTRE_CNTTP_COMPILER_CHECK
5914 : template <typename CharT, CharT... charpack> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto operator""_ctre_syntax() noexcept {
5915 : constexpr auto & _input = _fixed_string_reference<CharT, charpack...>;
5916 : #else
5917 : template <ctll::fixed_string input> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto operator""_ctre_syntax() noexcept {
5918 : constexpr auto _input = input; // workaround for GCC 9 bug 88092
5919 : #endif
5920 : return ctll::parser<ctre::pcre, _input, ctre::pcre_actions>::template correct_with<pcre_context<>>;
5921 : }
5922 :
5923 : #endif
5924 :
5925 : #ifdef __clang__
5926 : #pragma clang diagnostic pop
5927 : #endif
5928 :
5929 : } // literals
5930 :
5931 : } // ctre
5932 :
5933 : #endif
5934 :
5935 : #endif
5936 :
5937 : #ifndef CTRE_V2__CTRE__FUNCTIONS__HPP
5938 : #define CTRE_V2__CTRE__FUNCTIONS__HPP
5939 :
5940 : namespace ctre {
5941 :
5942 : #if !CTRE_CNTTP_COMPILER_CHECK
5943 : // avoiding CTAD limitation in C++17
5944 : template <typename CharT, size_t N> class pattern: public ctll::fixed_string<N> {
5945 : using parent = ctll::fixed_string<N>;
5946 : public:
5947 : constexpr pattern(const CharT (&input)[N]) noexcept: parent(input) { }
5948 : };
5949 :
5950 : template <typename CharT, size_t N> pattern(const CharT (&)[N]) -> pattern<CharT, N>;
5951 :
5952 : // for better examples
5953 : template <typename CharT, size_t N> class fixed_string: public ctll::fixed_string<N> {
5954 : using parent = ctll::fixed_string<N>;
5955 : public:
5956 : constexpr fixed_string(const CharT (&input)[N]) noexcept: parent(input) { }
5957 : };
5958 :
5959 : template <typename CharT, size_t N> fixed_string(const CharT (&)[N]) -> fixed_string<CharT, N>;
5960 : #endif
5961 :
5962 : #if CTRE_CNTTP_COMPILER_CHECK
5963 : template <ctll::fixed_string input, typename Modifier = void> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto re() noexcept {
5964 : constexpr auto _input = input; // workaround for GCC 9 bug 88092
5965 : #else
5966 : template <auto & input, typename Modifier = void> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto re() noexcept {
5967 : constexpr auto & _input = input;
5968 : #endif
5969 :
5970 : using tmp = typename ctll::parser<ctre::pcre, _input, ctre::pcre_actions>::template output<pcre_context<>>;
5971 : static_assert(tmp(), "Regular Expression contains syntax error.");
5972 : using regex = decltype(front(typename tmp::output_type::stack_type()));
5973 : return ctre::regular_expression<regex, Modifier, singleline>();
5974 : }
5975 :
5976 : }
5977 :
5978 : #endif
5979 :
5980 : #ifndef CTRE_V2__CTRE__OPERATORS__HPP
5981 : #define CTRE_V2__CTRE__OPERATORS__HPP
5982 :
5983 : template <typename A, typename B> constexpr auto operator|(ctre::regular_expression<A>, ctre::regular_expression<B>) -> ctre::regular_expression<ctre::select<A,B>> {
5984 : return {};
5985 : }
5986 :
5987 : template <typename A, typename B> constexpr auto operator>>(ctre::regular_expression<A>, ctre::regular_expression<B>) -> ctre::regular_expression<ctre::sequence<A,B>> {
5988 : return {};
5989 : }
5990 :
5991 : #endif
5992 :
5993 : #endif
|