Branch data 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 : : constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list<RE>{});
5543 : :
5544 : : auto it = begin;
5545 : :
5546 : : for (; end != it && !fixed; ++it) {
5547 : : if (auto out = evaluate(orig_begin, it, end, Modifier{}, return_type<result_iterator, RE>{}, ctll::list<start_mark, RE, end_mark, accept>())) {
5548 : : return out;
5549 : : }
5550 : : }
5551 : :
5552 : : // in case the RE is empty or fixed
5553 : : 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 : : if (!out) out.set_end_mark(it);
5558 : : 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 : : 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 : : 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 : : 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
|