commit a1d736909644af35e9ecc584d8dc88b31b7efe63 Author: JIe Date: Mon Sep 23 19:50:16 2024 +0800 init diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..30a5ba3 --- /dev/null +++ b/.clangd @@ -0,0 +1,2 @@ +CompileFlags: + Add: [-std=c++20] diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..e4b0f61 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,46 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..41f0e76 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/serialt.iml b/.idea/serialt.iml new file mode 100644 index 0000000..4c94235 --- /dev/null +++ b/.idea/serialt.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/demo.exe b/demo.exe new file mode 100644 index 0000000..5aaf030 Binary files /dev/null and b/demo.exe differ diff --git a/include/serial.h b/include/serial.h new file mode 100644 index 0000000..d81b7fe --- /dev/null +++ b/include/serial.h @@ -0,0 +1,140 @@ +#ifndef SERIAL_H +#define SERIAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../third/serialib.h" + +using namespace std::literals::chrono_literals; + +template +concept SupportString = requires{ + std::is_same_v; + std::is_same_v; +}; + +enum class +[[maybe_unused]] +ErrorCode{ + SUCCESS, + TIMEOUT, + SETTIMEOUTERROR, + WRITEINGERROR, + READINGERROR, +}; + +class Serial +{ +private: + serialib ser; + const char* endChar = "\r\n"; + std::function logCallBack; + +public: + Serial() = default; + + std::string GetTimeNow(){ + auto now = std::chrono::system_clock::now(); + auto now_c = std::chrono::system_clock::to_time_t(now); + return std::ctime(&now_c); + } + + template + bool OpenDevice(T PortName, unsigned int bauds) + { + int code; + if constexpr (std::is_same_v){ + code = ser.openDevice(PortName.c_str(), bauds); + } + else{ + code = ser.openDevice(PortName, bauds); + } + if(code == 1){ + return true; + }else{ + return false; + } + } + + void Log(const std::string& log){ + if(logCallBack){ + auto msg = GetTimeNow() + " "+ log + "\n"; + logCallBack(msg); + } + } + + void SetLogCallBack(std::function callBack){ + logCallBack = callBack; + } + + void CloseDevice(){ + ser.closeDevice(); + } + + ~Serial() = default; + + + template + std::optional GetAtResponse(T command, int timeout = 50){ + ser.flushReceiver(); + std::string reallyCommand; + std::string response; + if constexpr (std::is_same_v){ + reallyCommand = command + endChar; + } + else{ + reallyCommand = std::string(command) + endChar; + } + ser.writeString(reallyCommand.c_str()); + Log("Send: " + reallyCommand); + std::this_thread::sleep_for(10ms); + // char buffer[ser.available()] = {0}; + char* buffer = (char*)malloc(sizeof(char)*ser.available()); + std::cout< 0){ + response = std::string(buffer); + Log("Receive: " + response); + delete[] buffer; + return response; + } + delete[] buffer; + return std::nullopt; + } + + template + bool GetAtUntil(T command, T expect = "OK",int timeout = 50){ + auto endTime = std::chrono::system_clock::now() + std::chrono::milliseconds(timeout); + ser.flushReceiver(); + std::string reallyCommand; + if constexpr (std::is_same_v){ + reallyCommand = command + endChar; + } + else{ + reallyCommand = std::string(command) + endChar; + } + ser.writeString(reallyCommand.c_str()); + Log("Send : " + reallyCommand); + while(std::chrono::system_clock::now() < endTime){ + std::this_thread::sleep_for(10ms); + auto buffer = new char[ser.available()]; + auto size = ser.readBytes(buffer, sizeof(buffer), timeout); + auto str = std::string(buffer); + delete[] buffer; + if(size > 0) + Log("Receive: "+str); + if(str.find(expect) != std::string::npos){ + return true; + } + } + return false; + } +}; + +#endif // SERIAL_H diff --git a/main.cc b/main.cc new file mode 100644 index 0000000..5df52a7 --- /dev/null +++ b/main.cc @@ -0,0 +1,24 @@ +#include "include/serial.h" +#include +#include +using namespace std::literals::chrono_literals; + +void PrintLog(const std::string& msg){ + std::cout<(endTime-startTime).count(); +} diff --git a/third/ctre.hpp b/third/ctre.hpp new file mode 100644 index 0000000..813c73f --- /dev/null +++ b/third/ctre.hpp @@ -0,0 +1,5983 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +--- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. +*/ +#ifndef CTRE_V2__CTRE__HPP +#define CTRE_V2__CTRE__HPP + +#ifndef CTRE_V2__CTRE__LITERALS__HPP +#define CTRE_V2__CTRE__LITERALS__HPP + +#ifndef CTRE_V2__CTLL__HPP +#define CTRE_V2__CTLL__HPP + +#ifndef CTLL__PARSER__HPP +#define CTLL__PARSER__HPP + +#ifndef CTLL__FIXED_STRING__GPP +#define CTLL__FIXED_STRING__GPP + +#ifndef CTLL_IN_A_MODULE +#include +#include +#include +#include +#include +#endif + +namespace ctll { + +struct length_value_t { + uint32_t value; + uint8_t length; +}; + +constexpr length_value_t length_and_value_of_utf8_code_point(uint8_t first_unit) noexcept { + if ((first_unit & 0b1000'0000) == 0b0000'0000) return {static_cast(first_unit), 1}; + else if ((first_unit & 0b1110'0000) == 0b1100'0000) return {static_cast(first_unit & 0b0001'1111), 2}; + else if ((first_unit & 0b1111'0000) == 0b1110'0000) return {static_cast(first_unit & 0b0000'1111), 3}; + else if ((first_unit & 0b1111'1000) == 0b1111'0000) return {static_cast(first_unit & 0b0000'0111), 4}; + else if ((first_unit & 0b1111'1100) == 0b1111'1000) return {static_cast(first_unit & 0b0000'0011), 5}; + else if ((first_unit & 0b1111'1100) == 0b1111'1100) return {static_cast(first_unit & 0b0000'0001), 6}; + else return {0, 0}; +} + +constexpr char32_t value_of_trailing_utf8_code_point(uint8_t unit, bool & correct) noexcept { + if ((unit & 0b1100'0000) == 0b1000'0000) return unit & 0b0011'1111; + else { + correct = false; + return 0; + } +} + +constexpr length_value_t length_and_value_of_utf16_code_point(uint16_t first_unit) noexcept { + if ((first_unit & 0b1111110000000000) == 0b1101'1000'0000'0000) return {static_cast(first_unit & 0b0000001111111111), 2}; + else return {first_unit, 1}; +} + +struct construct_from_pointer_t { }; + +constexpr auto construct_from_pointer = construct_from_pointer_t{}; + +template struct fixed_string { + char32_t content[N] = {}; + size_t real_size{0}; + bool correct_flag{true}; + + template constexpr fixed_string(construct_from_pointer_t, const T * input) noexcept { + if constexpr (std::is_same_v) { + #ifdef CTRE_STRING_IS_UTF8 + size_t out{0}; + for (size_t i{0}; i < N; ++i) { + if ((i == (N-1)) && (input[i] == 0)) break; + length_value_t info = length_and_value_of_utf8_code_point(input[i]); + switch (info.length) { + case 6: + if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag); + [[fallthrough]]; + case 5: + if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag); + [[fallthrough]]; + case 4: + if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag); + [[fallthrough]]; + case 3: + if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag); + [[fallthrough]]; + case 2: + if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag); + [[fallthrough]]; + case 1: + content[out++] = static_cast(info.value); + real_size++; + break; + default: + correct_flag = false; + return; + } + } + #else + for (size_t i{0}; i < N; ++i) { + content[i] = static_cast(input[i]); + if ((i == (N-1)) && (input[i] == 0)) break; + real_size++; + } + #endif + #if __cpp_char8_t + } else if constexpr (std::is_same_v) { + size_t out{0}; + for (size_t i{0}; i < N; ++i) { + if ((i == (N-1)) && (input[i] == 0)) break; + length_value_t info = length_and_value_of_utf8_code_point(input[i]); + switch (info.length) { + case 6: + if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag); + [[fallthrough]]; + case 5: + if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag); + [[fallthrough]]; + case 4: + if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag); + [[fallthrough]]; + case 3: + if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag); + [[fallthrough]]; + case 2: + if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag); + [[fallthrough]]; + case 1: + content[out++] = static_cast(info.value); + real_size++; + break; + default: + correct_flag = false; + return; + } + } + #endif + } else if constexpr (std::is_same_v) { + size_t out{0}; + for (size_t i{0}; i < N; ++i) { + length_value_t info = length_and_value_of_utf16_code_point(input[i]); + if (info.length == 2) { + if (++i < N) { + if ((input[i] & 0b1111'1100'0000'0000) == 0b1101'1100'0000'0000) { + content[out++] = ((info.value << 10) | (input[i] & 0b0000'0011'1111'1111)) + 0x10000; + } else { + correct_flag = false; + break; + } + } + } else { + if ((i == (N-1)) && (input[i] == 0)) break; + content[out++] = info.value; + } + } + real_size = out; + } else if constexpr (std::is_same_v || std::is_same_v) { + for (size_t i{0}; i < N; ++i) { + content[i] = static_cast(input[i]); + if ((i == (N-1)) && (input[i] == 0)) break; + real_size++; + } + } + } + + template constexpr fixed_string(const std::array & in) noexcept: fixed_string{construct_from_pointer, in.data()} { } + template constexpr fixed_string(const T (&input)[N+1]) noexcept: fixed_string{construct_from_pointer, input} { } + + constexpr fixed_string(const fixed_string & other) noexcept { + for (size_t i{0}; i < N; ++i) { + content[i] = other.content[i]; + } + real_size = other.real_size; + correct_flag = other.correct_flag; + } + constexpr bool correct() const noexcept { + return correct_flag; + } + constexpr size_t size() const noexcept { + return real_size; + } + constexpr const char32_t * begin() const noexcept { + return content; + } + constexpr const char32_t * end() const noexcept { + return content + size(); + } + constexpr char32_t operator[](size_t i) const noexcept { + return content[i]; + } + template constexpr bool is_same_as(const fixed_string & rhs) const noexcept { + if (real_size != rhs.size()) return false; + for (size_t i{0}; i != real_size; ++i) { + if (content[i] != rhs[i]) return false; + } + return true; + } + constexpr operator std::basic_string_view() const noexcept { + return std::basic_string_view{content, size()}; + } +}; + +template <> class fixed_string<0> { + static constexpr char32_t empty[1] = {0}; +public: + template constexpr fixed_string(const T *) noexcept { + + } + constexpr fixed_string(std::initializer_list) noexcept { + + } + constexpr fixed_string(const fixed_string &) noexcept { + + } + constexpr bool correct() const noexcept { + return true; + } + constexpr size_t size() const noexcept { + return 0; + } + constexpr const char32_t * begin() const noexcept { + return empty; + } + constexpr const char32_t * end() const noexcept { + return empty + size(); + } + constexpr char32_t operator[](size_t) const noexcept { + return 0; + } + constexpr operator std::basic_string_view() const noexcept { + return std::basic_string_view{empty, 0}; + } +}; + +template fixed_string(const CharT (&)[N]) -> fixed_string; +template fixed_string(const std::array &) -> fixed_string; + +template fixed_string(fixed_string) -> fixed_string; + +} + +#endif + +#ifndef CTLL__TYPE_STACK__HPP +#define CTLL__TYPE_STACK__HPP + +#ifndef CTLL__UTILITIES__HPP +#define CTLL__UTILITIES__HPP + +#ifndef CTLL_IN_A_MODULE +#include +#endif + +#ifdef CTLL_IN_A_MODULE +#define CTLL_EXPORT +#else +#define CTLL_EXPORT export +#endif + +#if defined __cpp_nontype_template_parameter_class + #define CTLL_CNTTP_COMPILER_CHECK 1 +#elif defined __cpp_nontype_template_args +// compiler which defines correctly feature test macro (not you clang) + #if __cpp_nontype_template_args >= 201911L + #define CTLL_CNTTP_COMPILER_CHECK 1 + #elif __cpp_nontype_template_args >= 201411L +// appleclang 13+ + #if defined __apple_build_version__ + #if defined __clang_major__ && __clang_major__ >= 13 +// but only in c++20 and more + #if __cplusplus > 201703L + #define CTLL_CNTTP_COMPILER_CHECK 1 + #endif + #endif + #else +// clang 12+ + #if defined __clang_major__ && __clang_major__ >= 12 +// but only in c++20 and more + #if __cplusplus > 201703L + #define CTLL_CNTTP_COMPILER_CHECK 1 + #endif + #endif + #endif + #endif +#endif + +#ifndef CTLL_CNTTP_COMPILER_CHECK + #define CTLL_CNTTP_COMPILER_CHECK 0 +#endif + +#ifdef _MSC_VER +#define CTLL_FORCE_INLINE __forceinline +#else +#define CTLL_FORCE_INLINE __attribute__((always_inline)) +#endif + +namespace ctll { + +template struct conditional_helper; + +template <> struct conditional_helper { + template using type = A; +}; + +template <> struct conditional_helper { + template using type = B; +}; + +template using conditional = typename conditional_helper::template type; + +} + +#endif + +namespace ctll { + +template struct list { }; + +struct _nothing { }; + +using empty_list = list<>; + +// calculate size of list content +template constexpr auto size(list) noexcept { return sizeof...(Ts); } + + +// check if the list is empty +template constexpr bool empty(list) noexcept { return false; } +constexpr bool empty(empty_list) { return true; } + +// concat two lists together left to right +template constexpr auto concat(list, list) noexcept -> list { return {}; } + +// push something to the front of a list +template constexpr auto push_front(T, list) noexcept -> list { return {}; } + +// pop element from the front of a list +template constexpr auto pop_front(list) noexcept -> list { return {}; } +constexpr auto pop_front(empty_list) -> empty_list; + +// pop element from the front of a list and return new typelist too +template struct list_pop_pair { + Front front{}; + List list{}; + constexpr list_pop_pair() = default; +}; + +template constexpr auto pop_and_get_front(list, T = T()) noexcept -> list_pop_pair> { return {}; } +template constexpr auto pop_and_get_front(empty_list, T = T()) noexcept -> list_pop_pair { return {}; } + +// return front of the list +template constexpr auto front(list, T = T()) noexcept -> Head { return {}; } +template constexpr auto front(empty_list, T = T()) noexcept -> T { return {}; } + +// rotate list +template struct rotate_item { + template friend constexpr auto operator+(list, rotate_item) noexcept -> list { return {}; } +}; + +template constexpr auto rotate(list) -> decltype((list<>{} + ... + rotate_item{})) { + return {}; +} + +// set operations +template struct item_matcher { + struct not_selected { + template friend constexpr auto operator+(list, not_selected) -> list; + }; + template struct wrapper { + template friend constexpr auto operator+(list, wrapper) -> list; + }; + + static constexpr auto check(T) { return std::true_type{}; } + static constexpr auto check(...) { return std::false_type{}; } + static constexpr auto select(T) { return not_selected{}; } + template static constexpr auto select(Y) { return wrapper{}; } +}; + +template constexpr bool exists_in(T, list) noexcept { + return (item_matcher::check(Ts{}) || ... || false); +} + +template constexpr auto add_item(T item, list l) noexcept { + if constexpr (exists_in(item, l)) { + return l; + } else { + return list{}; + } +} + +template constexpr auto remove_item(T, list) noexcept { + item_matcher matcher; + return decltype((list<>{} + ... + matcher.select(Ts{}))){}; +} + +} + +#endif + +#ifndef CTLL__GRAMMARS__HPP +#define CTLL__GRAMMARS__HPP + +namespace ctll { + +// terminal type representing symbol / character of any type +template struct term { + static constexpr auto value = v; +}; + +// epsilon = nothing on input tape +// also used as an command for parsing means "do nothing" +struct epsilon { + static constexpr auto value = '-'; +}; + +// empty_stack_symbol = nothing on stack +struct empty_stack_symbol {}; + +// push is alias to list +template using push = list; + +// accept/reject type for controlling output of LL1 machine +struct accept { constexpr explicit operator bool() noexcept { return true; } }; +struct reject { constexpr explicit operator bool() noexcept { return false; } }; + +// action type, every action item in grammar must inherit from +struct action { + struct action_tag { }; +}; + +// move one character forward and pop it from stack command +struct pop_input { + struct pop_input_tag { }; +}; + +// additional overloads for type list +template constexpr auto push_front(pop_input, list) -> list { return {}; } + +template constexpr auto push_front(epsilon, list) -> list { return {}; } + +template constexpr auto push_front(list, list) -> list { return {}; } + +template constexpr auto pop_front_and_push_front(T item, list l) { + return push_front(item, pop_front(l)); +} + +// SPECIAL matching types for nicer grammars + +// match any term +struct anything { + constexpr inline anything() noexcept { } + template constexpr anything(term) noexcept; +}; + +// match range of term A-B +template struct range { + constexpr inline range() noexcept { } + //template constexpr range(term) noexcept requires (A <= V) && (V <= B); + template > constexpr range(term) noexcept; +}; + +#ifdef __EDG__ +template struct contains { + static constexpr bool value = ((Set == V) || ... || false); +}; +#endif + +// match terms defined in set +template struct set { + constexpr inline set() noexcept { } + #ifdef __EDG__ + template ::value>> constexpr set(term) noexcept; + #else + template > constexpr set(term) noexcept; + #endif +}; + +// match terms not defined in set +template struct neg_set { + constexpr inline neg_set() noexcept { } + + #ifdef __EDG__ + template ::value>> constexpr neg_set(term) noexcept; + #else + template > constexpr neg_set(term) noexcept; + #endif +}; + +// AUGMENTED grammar which completes user-defined grammar for all other cases +template struct augment_grammar: public Grammar { + // start nonterminal is defined in parent type + using typename Grammar::_start; + + // grammar rules are inherited from Grammar parent type + using Grammar::rule; + + // term on stack and on input means pop_input; + template static constexpr auto rule(term, term) -> ctll::pop_input; + + // if the type on stack (range, set, neg_set, anything) is constructible from the terminal => pop_input + template static constexpr auto rule(Expected, term) -> std::enable_if_t>, ctll::pop_input>; + + // empty stack and empty input means we are accepting + static constexpr auto rule(empty_stack_symbol, epsilon) -> ctll::accept; + + // not matching anything else => reject + static constexpr auto rule(...) -> ctll::reject; + + // start stack is just a list; + using start_stack = list; +}; + +} + +#endif + +#ifndef CTLL__ACTIONS__HPP +#define CTLL__ACTIONS__HPP + +namespace ctll { + struct empty_subject { }; + + struct empty_actions { + // dummy operator so using Actions::operator() later will not give error + template static constexpr auto apply(Action, InputSymbol, Subject subject) { + return subject; + } + }; + + template struct identity: public Actions { + using Actions::apply; + // allow empty_subject to exists + template constexpr static auto apply(Action, term, empty_subject) -> empty_subject { return {}; } + template constexpr static auto apply(Action, epsilon, empty_subject) -> empty_subject { return {}; } + }; + + template struct ignore_unknown: public Actions { + using Actions::apply; + // allow flow thru unknown actions + template constexpr static auto apply(Action, term, Subject) -> Subject { return {}; } + template constexpr static auto apply(Action, epsilon, Subject) -> Subject { return {}; } + }; +} + +#endif + +#ifndef CTLL_IN_A_MODULE +#include +#endif + +namespace ctll { + +enum class decision { + reject, + accept, + undecided +}; + +struct placeholder { }; + +template using index_placeholder = placeholder; + +#if CTLL_CNTTP_COMPILER_CHECK +template struct parser { // in c++20 +#else +template struct parser { +#endif + + #ifdef __GNUC__ // workaround to GCC bug + #if CTLL_CNTTP_COMPILER_CHECK + static constexpr auto _input = input; // c++20 mode + #else + static constexpr auto & _input = input; // c++17 mode + #endif + #else + static constexpr auto _input = input; // everyone else + #endif + + using Actions = ctll::conditional, identity>; + using grammar = augment_grammar; + + template struct results { + + static constexpr bool is_correct = Decision == decision::accept; + + constexpr inline CTLL_FORCE_INLINE operator bool() const noexcept { + return is_correct; + } + + #ifdef __GNUC__ // workaround to GCC bug + #if CTLL_CNTTP_COMPILER_CHECK + static constexpr auto _input = input; // c++20 mode + #else + static constexpr auto & _input = input; // c++17 mode + #endif + #else + static constexpr auto _input = input; // everyone else + #endif + + using output_type = Subject; + static constexpr size_t position = Pos; + + constexpr auto operator+(placeholder) const noexcept { + if constexpr (Decision == decision::undecided) { + // parse for current char (RPos) with previous stack and subject :) + return parser::template decide({}, {}); + } else { + // if there is decision already => just push it to the end of fold expression + return *this; + } + } + }; + + template static constexpr auto get_current_term() noexcept { + if constexpr (Pos < input.size()) { + constexpr auto value = input[Pos]; + if constexpr (value <= static_cast((std::numeric_limits::max)())) { + return term(value)>{}; + } else { + return term{}; + } + + } else { + // return epsilon if we are past the input + return epsilon{}; + } + } + template static constexpr auto get_previous_term() noexcept { + if constexpr (Pos == 0) { + // there is no previous character on input if we are on start + return epsilon{}; + } else if constexpr ((Pos-1) < input.size()) { + constexpr auto value = input[Pos-1]; + if constexpr (value <= static_cast((std::numeric_limits::max)())) { + return term(value)>{}; + } else { + return term{}; + } + } else { + return epsilon{}; + } + } + // if rule is accept => return true and subject + template + static constexpr auto move(ctll::accept, Terminal, Stack, Subject) noexcept { + return typename parser::template results(); + } + // if rule is reject => return false and subject + template + static constexpr auto move(ctll::reject, Terminal, Stack, Subject) noexcept { + return typename parser::template results(); + } + // if rule is pop_input => move to next character + template + static constexpr auto move(ctll::pop_input, Terminal, Stack, Subject) noexcept { + return typename parser::template results(); + } + // if rule is string => push it to the front of stack + template + static constexpr auto move(push string, Terminal, Stack stack, Subject subject) noexcept { + return decide(push_front(string, stack), subject); + } + // if rule is epsilon (empty string) => continue + template + static constexpr auto move(epsilon, Terminal, Stack stack, Subject subject) noexcept { + return decide(stack, subject); + } + // if rule is string with current character at the beginning (term) => move to next character + // and push string without the character (quick LL(1)) + template + static constexpr auto move(push, Content...>, term, Stack stack, Subject) noexcept { + constexpr auto local_input = input; + return typename parser::template results(), stack)), Subject, decision::undecided>(); + } + // if rule is string with any character at the beginning (compatible with current term) => move to next character + // and push string without the character (quick LL(1)) + template + static constexpr auto move(push, term, Stack stack, Subject) noexcept { + constexpr auto local_input = input; + return typename parser::template results(), stack)), Subject, decision::undecided>(); + } + // decide if we need to take action or move + template static constexpr auto decide(Stack previous_stack, Subject previous_subject) noexcept { + // each call means we pop something from stack + auto top_symbol = decltype(ctll::front(previous_stack, empty_stack_symbol()))(); + // gcc pedantic warning + [[maybe_unused]] auto stack = decltype(ctll::pop_front(previous_stack))(); + + // in case top_symbol is action type (apply it on previous subject and get new one) + if constexpr (std::is_base_of_v) { + auto subject = Actions::apply(top_symbol, get_previous_term(), previous_subject); + + // in case that semantic action is error => reject input + if constexpr (std::is_same_v) { + return typename parser::template results(); + } else { + return decide(stack, subject); + } + } else { + // all other cases are ordinary for LL(1) parser + auto current_term = get_current_term(); + auto rule = decltype(grammar::rule(top_symbol,current_term))(); + return move(rule, current_term, stack, previous_subject); + } + } + + // trampolines with folded expression + template static constexpr auto trampoline_decide(Subject, std::index_sequence) noexcept { + // parse everything for first char and than for next and next ... + // Pos+1 is needed as we want to finish calculation with epsilons on stack + auto v = (decide<0, typename grammar::start_stack, Subject>({}, {}) + ... + index_placeholder()); + return v; + } + + template static constexpr auto trampoline_decide(Subject subject = {}) noexcept { + // there will be no recursion, just sequence long as the input + return trampoline_decide(subject, std::make_index_sequence()); + } + + template using output = decltype(trampoline_decide()); + template static inline constexpr bool correct_with = trampoline_decide(); + +}; + +} // end of ctll namespace + +#endif + +#endif + +#ifndef CTRE__PCRE_ACTIONS__HPP +#define CTRE__PCRE_ACTIONS__HPP + +#ifndef CTRE__PCRE__HPP +#define CTRE__PCRE__HPP + +// THIS FILE WAS GENERATED BY DESATOMAT TOOL, DO NOT MODIFY THIS FILE + +namespace ctre { + +struct pcre { + +// NONTERMINALS: + struct a {}; + struct b {}; + struct backslash {}; + struct backslash_range {}; + struct block {}; + struct block_name2 {}; + struct block_name {}; + struct c {}; + struct class_named_name {}; + struct content2 {}; + struct content {}; + struct content_in_capture {}; + struct content_or_empty {}; + struct d {}; + struct e {}; + struct f {}; + struct g {}; + struct h {}; + struct hexdec_repeat {}; + struct i {}; + struct j {}; + struct k {}; + struct l {}; + struct m {}; + struct mod {}; + struct mode_switch2 {}; + struct n {}; + struct number2 {}; + struct number {}; + struct o {}; + struct p {}; + struct property_name2 {}; + struct property_name {}; + struct property_value2 {}; + struct property_value {}; + struct range {}; + struct repeat {}; + struct s {}; using _start = s; + struct set2a {}; + struct set2b {}; + struct string2 {}; + +// 'action' types: + struct class_digit: ctll::action {}; + struct class_horizontal_space: ctll::action {}; + struct class_named_alnum: ctll::action {}; + struct class_named_alpha: ctll::action {}; + struct class_named_ascii: ctll::action {}; + struct class_named_blank: ctll::action {}; + struct class_named_cntrl: ctll::action {}; + struct class_named_digit: ctll::action {}; + struct class_named_graph: ctll::action {}; + struct class_named_lower: ctll::action {}; + struct class_named_print: ctll::action {}; + struct class_named_punct: ctll::action {}; + struct class_named_space: ctll::action {}; + struct class_named_upper: ctll::action {}; + struct class_named_word: ctll::action {}; + struct class_named_xdigit: ctll::action {}; + struct class_non_horizontal_space: ctll::action {}; + struct class_non_vertical_space: ctll::action {}; + struct class_nondigit: ctll::action {}; + struct class_nonnewline: ctll::action {}; + struct class_nonspace: ctll::action {}; + struct class_nonword: ctll::action {}; + struct class_space: ctll::action {}; + struct class_vertical_space: ctll::action {}; + struct class_word: ctll::action {}; + struct create_hexdec: ctll::action {}; + struct create_number: ctll::action {}; + struct finish_hexdec: ctll::action {}; + struct look_finish: ctll::action {}; + struct make_alternate: ctll::action {}; + struct make_atomic: ctll::action {}; + struct make_back_reference: ctll::action {}; + struct make_capture: ctll::action {}; + struct make_capture_with_name: ctll::action {}; + struct make_lazy: ctll::action {}; + struct make_optional: ctll::action {}; + struct make_possessive: ctll::action {}; + struct make_property: ctll::action {}; + struct make_property_negative: ctll::action {}; + struct make_range: ctll::action {}; + struct make_relative_back_reference: ctll::action {}; + struct make_sequence: ctll::action {}; + struct mode_case_insensitive: ctll::action {}; + struct mode_case_sensitive: ctll::action {}; + struct mode_multiline: ctll::action {}; + struct mode_singleline: ctll::action {}; + struct negate_class_named: ctll::action {}; + struct prepare_capture: ctll::action {}; + struct push_assert_begin: ctll::action {}; + struct push_assert_end: ctll::action {}; + struct push_assert_subject_begin: ctll::action {}; + struct push_assert_subject_end: ctll::action {}; + struct push_assert_subject_end_with_lineend: ctll::action {}; + struct push_character: ctll::action {}; + struct push_character_alarm: ctll::action {}; + struct push_character_anything: ctll::action {}; + struct push_character_escape: ctll::action {}; + struct push_character_formfeed: ctll::action {}; + struct push_character_newline: ctll::action {}; + struct push_character_null: ctll::action {}; + struct push_character_return_carriage: ctll::action {}; + struct push_character_tab: ctll::action {}; + struct push_empty: ctll::action {}; + struct push_hexdec: ctll::action {}; + struct push_name: ctll::action {}; + struct push_not_word_boundary: ctll::action {}; + struct push_number: ctll::action {}; + struct push_property_name: ctll::action {}; + struct push_property_value: ctll::action {}; + struct push_word_boundary: ctll::action {}; + struct repeat_ab: ctll::action {}; + struct repeat_at_least: ctll::action {}; + struct repeat_exactly: ctll::action {}; + struct repeat_plus: ctll::action {}; + struct repeat_star: ctll::action {}; + struct reset_capture: ctll::action {}; + struct set_combine: ctll::action {}; + struct set_make: ctll::action {}; + struct set_make_negative: ctll::action {}; + struct set_start: ctll::action {}; + struct start_atomic: ctll::action {}; + struct start_lookahead_negative: ctll::action {}; + struct start_lookahead_positive: ctll::action {}; + struct start_lookbehind_negative: ctll::action {}; + struct start_lookbehind_positive: ctll::action {}; + +// (q)LL1 function: + 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'>; + static constexpr auto rule(s, ctll::term<'\\'>) -> ctll::push; + static constexpr auto rule(s, ctll::term<'['>) -> ctll::push; + static constexpr auto rule(s, ctll::term<'\x28'>) -> ctll::push; + static constexpr auto rule(s, ctll::term<'^'>) -> ctll::push; + static constexpr auto rule(s, ctll::term<'$'>) -> ctll::push; + 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; + static constexpr auto rule(s, _others) -> ctll::push; + static constexpr auto rule(s, ctll::term<'.'>) -> ctll::push; + static constexpr auto rule(s, ctll::term<'|'>) -> ctll::push; + static constexpr auto rule(s, ctll::epsilon) -> ctll::push; + static constexpr auto rule(s, ctll::set<'\x29','*','+','?','\x7B','\x7D'>) -> ctll::reject; + + static constexpr auto rule(a, ctll::term<'\\'>) -> ctll::push; + static constexpr auto rule(a, ctll::term<'['>) -> ctll::push; + static constexpr auto rule(a, ctll::term<'\x28'>) -> ctll::push; + static constexpr auto rule(a, ctll::term<'^'>) -> ctll::push; + static constexpr auto rule(a, ctll::term<'$'>) -> ctll::push; + 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; + static constexpr auto rule(a, _others) -> ctll::push; + static constexpr auto rule(a, ctll::term<'.'>) -> ctll::push; + static constexpr auto rule(a, ctll::term<'\x29'>) -> ctll::push; + static constexpr auto rule(a, ctll::epsilon) -> ctll::push; + static constexpr auto rule(a, ctll::set<'*','+','?','\x7B','|','\x7D'>) -> ctll::reject; + + static constexpr auto rule(b, ctll::term<','>) -> ctll::push; + static constexpr auto rule(b, ctll::term<'\x7D'>) -> ctll::push; + + static constexpr auto rule(backslash, ctll::term<'d'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'h'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'H'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'V'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'D'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'N'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'S'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'W'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'s'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'v'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'w'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::set<'1','2','3','4','5','6','7','8','9'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'g'>) -> ctll::push, m>; + static constexpr auto rule(backslash, ctll::term<'p'>) -> ctll::push, property_name, ctll::term<'\x7D'>, make_property>; + static constexpr auto rule(backslash, ctll::term<'P'>) -> ctll::push, property_name, ctll::term<'\x7D'>, make_property_negative>; + static constexpr auto rule(backslash, ctll::term<'u'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'x'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'A'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'z'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'Z'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'a'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'e'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'f'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'n'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'0'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'r'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'t'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'B'>) -> ctll::push; + static constexpr auto rule(backslash, ctll::term<'b'>) -> ctll::push; + + static constexpr auto rule(backslash_range, ctll::term<'u'>) -> ctll::push; + static constexpr auto rule(backslash_range, ctll::term<'x'>) -> ctll::push; + static constexpr auto rule(backslash_range, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push; + static constexpr auto rule(backslash_range, ctll::term<'a'>) -> ctll::push; + static constexpr auto rule(backslash_range, ctll::term<'e'>) -> ctll::push; + static constexpr auto rule(backslash_range, ctll::term<'f'>) -> ctll::push; + static constexpr auto rule(backslash_range, ctll::term<'n'>) -> ctll::push; + static constexpr auto rule(backslash_range, ctll::term<'0'>) -> ctll::push; + static constexpr auto rule(backslash_range, ctll::term<'r'>) -> ctll::push; + static constexpr auto rule(backslash_range, ctll::term<'t'>) -> ctll::push; + + static constexpr auto rule(block, ctll::term<'\\'>) -> ctll::push>; + static constexpr auto rule(block, ctll::term<'['>) -> ctll::push>; + static constexpr auto rule(block, ctll::term<'?'>) -> ctll::push; + static constexpr auto rule(block, ctll::term<'\x28'>) -> ctll::push>; + static constexpr auto rule(block, ctll::term<'^'>) -> ctll::push>; + static constexpr auto rule(block, ctll::term<'$'>) -> ctll::push>; + 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>; + static constexpr auto rule(block, _others) -> ctll::push>; + static constexpr auto rule(block, ctll::term<'.'>) -> ctll::push>; + static constexpr auto rule(block, ctll::term<'|'>) -> ctll::push>; + static constexpr auto rule(block, ctll::term<'\x29'>) -> ctll::push; + static constexpr auto rule(block, ctll::set<'*','+','\x7B','\x7D'>) -> ctll::reject; + + static constexpr auto rule(block_name2, ctll::set<'>','\x7D'>) -> ctll::epsilon; + 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; + + 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; + + static constexpr auto rule(c, ctll::term<'['>) -> ctll::push, i, range, set_start, set2b, set_make, ctll::term<']'>>; + static constexpr auto rule(c, ctll::term<'\\'>) -> ctll::push>; + 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>; + static constexpr auto rule(c, _others) -> ctll::push>; + static constexpr auto rule(c, ctll::term<'^'>) -> ctll::push>; + static constexpr auto rule(c, ctll::set<'-',']'>) -> ctll::reject; + + static constexpr auto rule(class_named_name, ctll::term<'x'>) -> ctll::push, ctll::term<'i'>, ctll::term<'g'>, ctll::term<'i'>, ctll::term<'t'>, class_named_xdigit>; + static constexpr auto rule(class_named_name, ctll::term<'d'>) -> ctll::push, ctll::term<'g'>, ctll::term<'i'>, ctll::term<'t'>, class_named_digit>; + static constexpr auto rule(class_named_name, ctll::term<'b'>) -> ctll::push, ctll::term<'a'>, ctll::term<'n'>, ctll::term<'k'>, class_named_blank>; + static constexpr auto rule(class_named_name, ctll::term<'c'>) -> ctll::push, ctll::term<'t'>, ctll::term<'r'>, ctll::term<'l'>, class_named_cntrl>; + static constexpr auto rule(class_named_name, ctll::term<'w'>) -> ctll::push, ctll::term<'r'>, ctll::term<'d'>, class_named_word>; + static constexpr auto rule(class_named_name, ctll::term<'l'>) -> ctll::push, ctll::term<'w'>, ctll::term<'e'>, ctll::term<'r'>, class_named_lower>; + static constexpr auto rule(class_named_name, ctll::term<'s'>) -> ctll::push, ctll::term<'a'>, ctll::term<'c'>, ctll::term<'e'>, class_named_space>; + static constexpr auto rule(class_named_name, ctll::term<'u'>) -> ctll::push, ctll::term<'p'>, ctll::term<'e'>, ctll::term<'r'>, class_named_upper>; + static constexpr auto rule(class_named_name, ctll::term<'g'>) -> ctll::push, ctll::term<'a'>, ctll::term<'p'>, ctll::term<'h'>, class_named_graph>; + static constexpr auto rule(class_named_name, ctll::term<'a'>) -> ctll::push; + static constexpr auto rule(class_named_name, ctll::term<'p'>) -> ctll::push; + + static constexpr auto rule(content2, ctll::term<'\x29'>) -> ctll::epsilon; + static constexpr auto rule(content2, ctll::epsilon) -> ctll::epsilon; + static constexpr auto rule(content2, ctll::term<'|'>) -> ctll::push; + + static constexpr auto rule(content, ctll::term<'\\'>) -> ctll::push; + static constexpr auto rule(content, ctll::term<'['>) -> ctll::push; + static constexpr auto rule(content, ctll::term<'\x28'>) -> ctll::push; + static constexpr auto rule(content, ctll::term<'^'>) -> ctll::push; + static constexpr auto rule(content, ctll::term<'$'>) -> ctll::push; + static constexpr auto rule(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; + static constexpr auto rule(content, _others) -> ctll::push; + static constexpr auto rule(content, ctll::term<'.'>) -> ctll::push; + static constexpr auto rule(content, ctll::set<'\x29','*','+','?','\x7B','|','\x7D'>) -> ctll::reject; + + static constexpr auto rule(content_in_capture, ctll::term<'\\'>) -> ctll::push; + static constexpr auto rule(content_in_capture, ctll::term<'['>) -> ctll::push; + static constexpr auto rule(content_in_capture, ctll::term<'\x28'>) -> ctll::push; + static constexpr auto rule(content_in_capture, ctll::term<'^'>) -> ctll::push; + static constexpr auto rule(content_in_capture, ctll::term<'$'>) -> ctll::push; + 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; + static constexpr auto rule(content_in_capture, _others) -> ctll::push; + static constexpr auto rule(content_in_capture, ctll::term<'.'>) -> ctll::push; + static constexpr auto rule(content_in_capture, ctll::term<'|'>) -> ctll::push; + static constexpr auto rule(content_in_capture, ctll::term<'\x29'>) -> ctll::push; + static constexpr auto rule(content_in_capture, ctll::set<'*','+','?','\x7B','\x7D'>) -> ctll::reject; + + static constexpr auto rule(content_or_empty, ctll::term<'\\'>) -> ctll::push; + static constexpr auto rule(content_or_empty, ctll::term<'['>) -> ctll::push; + static constexpr auto rule(content_or_empty, ctll::term<'\x28'>) -> ctll::push; + static constexpr auto rule(content_or_empty, ctll::term<'^'>) -> ctll::push; + static constexpr auto rule(content_or_empty, ctll::term<'$'>) -> ctll::push; + 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; + static constexpr auto rule(content_or_empty, _others) -> ctll::push; + static constexpr auto rule(content_or_empty, ctll::term<'.'>) -> ctll::push; + static constexpr auto rule(content_or_empty, ctll::term<'\x29'>) -> ctll::push; + static constexpr auto rule(content_or_empty, ctll::set<'*','+','?','\x7B','|','\x7D'>) -> ctll::reject; + + static constexpr auto rule(d, ctll::term<'i'>) -> ctll::push; + static constexpr auto rule(d, ctll::term<'c'>) -> ctll::push; + static constexpr auto rule(d, ctll::term<'m'>) -> ctll::push; + static constexpr auto rule(d, ctll::term<'s'>) -> ctll::push; + static constexpr auto rule(d, ctll::term<'<'>) -> ctll::push; + static constexpr auto rule(d, ctll::term<':'>) -> ctll::push>; + static constexpr auto rule(d, ctll::term<'>'>) -> ctll::push>; + static constexpr auto rule(d, ctll::term<'!'>) -> ctll::push>; + static constexpr auto rule(d, ctll::term<'='>) -> ctll::push>; + + static constexpr auto rule(e, ctll::term<'d'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'h'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'H'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'V'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'D'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'N'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'S'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'W'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'s'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'v'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'w'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'p'>) -> ctll::push, property_name, ctll::term<'\x7D'>, make_property>; + static constexpr auto rule(e, ctll::term<'P'>) -> ctll::push, property_name, ctll::term<'\x7D'>, make_property_negative>; + static constexpr auto rule(e, ctll::term<'u'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'x'>) -> ctll::push; + static constexpr auto rule(e, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'a'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'e'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'f'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'n'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'0'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'r'>) -> ctll::push; + static constexpr auto rule(e, ctll::term<'t'>) -> ctll::push; + + static constexpr auto rule(f, ctll::term<'d'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'h'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'H'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'V'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'D'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'N'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'S'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'W'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'s'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'v'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'w'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'p'>) -> ctll::push, property_name, ctll::term<'\x7D'>, make_property>; + static constexpr auto rule(f, ctll::term<'P'>) -> ctll::push, property_name, ctll::term<'\x7D'>, make_property_negative>; + static constexpr auto rule(f, ctll::term<'u'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'x'>) -> ctll::push; + static constexpr auto rule(f, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'a'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'e'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'f'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'n'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'0'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'r'>) -> ctll::push; + static constexpr auto rule(f, ctll::term<'t'>) -> ctll::push; + + static constexpr auto rule(g, ctll::term<'s'>) -> ctll::push, ctll::term<'i'>, ctll::term<'i'>, class_named_ascii>; + static constexpr auto rule(g, ctll::term<'l'>) -> ctll::push; + + static constexpr auto rule(h, ctll::term<'r'>) -> ctll::push, ctll::term<'n'>, ctll::term<'t'>, class_named_print>; + static constexpr auto rule(h, ctll::term<'u'>) -> ctll::push, ctll::term<'c'>, ctll::term<'t'>, class_named_punct>; + + static constexpr auto rule(hexdec_repeat, ctll::term<'\x7D'>) -> ctll::epsilon; + 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; + + static constexpr auto rule(i, ctll::term<'^'>) -> ctll::push, ctll::term<']'>>; + static constexpr auto rule(i, ctll::term<'x'>) -> ctll::push, ctll::term<'i'>, ctll::term<'g'>, ctll::term<'i'>, ctll::term<'t'>, class_named_xdigit, ctll::term<':'>, ctll::term<']'>>; + static constexpr auto rule(i, ctll::term<'d'>) -> ctll::push, ctll::term<'g'>, ctll::term<'i'>, ctll::term<'t'>, class_named_digit, ctll::term<':'>, ctll::term<']'>>; + static constexpr auto rule(i, ctll::term<'b'>) -> ctll::push, ctll::term<'a'>, ctll::term<'n'>, ctll::term<'k'>, class_named_blank, ctll::term<':'>, ctll::term<']'>>; + static constexpr auto rule(i, ctll::term<'c'>) -> ctll::push, ctll::term<'t'>, ctll::term<'r'>, ctll::term<'l'>, class_named_cntrl, ctll::term<':'>, ctll::term<']'>>; + static constexpr auto rule(i, ctll::term<'w'>) -> ctll::push, ctll::term<'r'>, ctll::term<'d'>, class_named_word, ctll::term<':'>, ctll::term<']'>>; + static constexpr auto rule(i, ctll::term<'l'>) -> ctll::push, ctll::term<'w'>, ctll::term<'e'>, ctll::term<'r'>, class_named_lower, ctll::term<':'>, ctll::term<']'>>; + static constexpr auto rule(i, ctll::term<'s'>) -> ctll::push, ctll::term<'a'>, ctll::term<'c'>, ctll::term<'e'>, class_named_space, ctll::term<':'>, ctll::term<']'>>; + static constexpr auto rule(i, ctll::term<'u'>) -> ctll::push, ctll::term<'p'>, ctll::term<'e'>, ctll::term<'r'>, class_named_upper, ctll::term<':'>, ctll::term<']'>>; + static constexpr auto rule(i, ctll::term<'g'>) -> ctll::push, ctll::term<'a'>, ctll::term<'p'>, ctll::term<'h'>, class_named_graph, ctll::term<':'>, ctll::term<']'>>; + static constexpr auto rule(i, ctll::term<'a'>) -> ctll::push, ctll::term<']'>>; + static constexpr auto rule(i, ctll::term<'p'>) -> ctll::push, ctll::term<']'>>; + + static constexpr auto rule(j, ctll::term<'\\'>) -> ctll::push; + 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; + static constexpr auto rule(j, _others) -> ctll::push; + static constexpr auto rule(j, ctll::set<'-','[',']'>) -> ctll::reject; + + static constexpr auto rule(k, ctll::term<'\x7B'>) -> ctll::push, push_hexdec, hexdec_repeat, ctll::term<'\x7D'>, finish_hexdec>; + 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, 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>; + + static constexpr auto rule(l, ctll::term<'\x7B'>) -> ctll::push, push_hexdec, hexdec_repeat, ctll::term<'\x7D'>, finish_hexdec>; + 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, push_hexdec, finish_hexdec>; + + static constexpr auto rule(m, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push, make_back_reference>; + static constexpr auto rule(m, ctll::term<'-'>) -> ctll::push, make_relative_back_reference>; + 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, make_back_reference>; + + 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; + static constexpr auto rule(mod, ctll::epsilon) -> ctll::epsilon; + static constexpr auto rule(mod, _others) -> ctll::epsilon; + static constexpr auto rule(mod, ctll::term<'?'>) -> ctll::push; + static constexpr auto rule(mod, ctll::term<'+'>) -> ctll::push; + static constexpr auto rule(mod, ctll::set<'*','\x7B','\x7D'>) -> ctll::reject; + + static constexpr auto rule(mode_switch2, ctll::term<'i'>) -> ctll::push; + static constexpr auto rule(mode_switch2, ctll::term<'c'>) -> ctll::push; + static constexpr auto rule(mode_switch2, ctll::term<'m'>) -> ctll::push; + static constexpr auto rule(mode_switch2, ctll::term<'s'>) -> ctll::push; + static constexpr auto rule(mode_switch2, ctll::term<'\x29'>) -> ctll::push; + + static constexpr auto rule(n, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push, mod>; + static constexpr auto rule(n, ctll::term<'\x7D'>) -> ctll::push; + + static constexpr auto rule(number2, ctll::set<',','\x7D'>) -> ctll::epsilon; + static constexpr auto rule(number2, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push; + + static constexpr auto rule(number, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push; + + 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'>, content_in_capture, make_capture_with_name, ctll::term<'\x29'>>; + static constexpr auto rule(o, ctll::term<'!'>) -> ctll::push>; + static constexpr auto rule(o, ctll::term<'='>) -> ctll::push>; + + static constexpr auto rule(p, ctll::term<'p'>) -> ctll::push, ctll::term<'a'>, class_named_alpha>; + static constexpr auto rule(p, ctll::term<'n'>) -> ctll::push, ctll::term<'m'>, class_named_alnum>; + + static constexpr auto rule(property_name2, ctll::term<'\x7D'>) -> ctll::epsilon; + static constexpr auto rule(property_name2, ctll::term<'='>) -> ctll::push; + 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; + + 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; + + static constexpr auto rule(property_value2, ctll::term<'\x7D'>) -> ctll::epsilon; + 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; + + 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; + + 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; + static constexpr auto rule(range, ctll::epsilon) -> ctll::epsilon; + static constexpr auto rule(range, _others) -> ctll::epsilon; + static constexpr auto rule(range, ctll::term<'-'>) -> ctll::push; + + 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; + static constexpr auto rule(repeat, ctll::epsilon) -> ctll::epsilon; + static constexpr auto rule(repeat, _others) -> ctll::epsilon; + static constexpr auto rule(repeat, ctll::term<'?'>) -> ctll::push; + static constexpr auto rule(repeat, ctll::term<'\x7B'>) -> ctll::push; + static constexpr auto rule(repeat, ctll::term<'+'>) -> ctll::push; + static constexpr auto rule(repeat, ctll::term<'*'>) -> ctll::push; + static constexpr auto rule(repeat, ctll::term<'\x7D'>) -> ctll::reject; + + static constexpr auto rule(set2a, ctll::term<']'>) -> ctll::epsilon; + static constexpr auto rule(set2a, ctll::term<'['>) -> ctll::push, i, range, set_start, set2b>; + static constexpr auto rule(set2a, ctll::term<'\\'>) -> ctll::push; + 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; + static constexpr auto rule(set2a, _others) -> ctll::push; + static constexpr auto rule(set2a, ctll::term<'-'>) -> ctll::reject; + + static constexpr auto rule(set2b, ctll::term<']'>) -> ctll::epsilon; + static constexpr auto rule(set2b, ctll::term<'['>) -> ctll::push, i, range, set_combine, set2b>; + static constexpr auto rule(set2b, ctll::term<'\\'>) -> ctll::push; + 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; + static constexpr auto rule(set2b, _others) -> ctll::push; + static constexpr auto rule(set2b, ctll::term<'-'>) -> ctll::reject; + + static constexpr auto rule(string2, ctll::set<'\x29','|'>) -> ctll::epsilon; + static constexpr auto rule(string2, ctll::epsilon) -> ctll::epsilon; + static constexpr auto rule(string2, ctll::term<'\\'>) -> ctll::push; + static constexpr auto rule(string2, ctll::term<'['>) -> ctll::push; + static constexpr auto rule(string2, ctll::term<'\x28'>) -> ctll::push; + static constexpr auto rule(string2, ctll::term<'^'>) -> ctll::push; + static constexpr auto rule(string2, ctll::term<'$'>) -> ctll::push; + 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; + static constexpr auto rule(string2, _others) -> ctll::push; + static constexpr auto rule(string2, ctll::term<'.'>) -> ctll::push; + static constexpr auto rule(string2, ctll::set<'*','+','?','\x7B','\x7D'>) -> ctll::reject; + +}; + +} + +#endif //CTRE__PCRE__HPP + +#ifndef CTRE__ROTATE__HPP +#define CTRE__ROTATE__HPP + +#ifndef CTRE__ATOMS__HPP +#define CTRE__ATOMS__HPP + +#ifndef CTRE__ATOMS_CHARACTERS__HPP +#define CTRE__ATOMS_CHARACTERS__HPP + +#ifndef CTRE__UTILITY__HPP +#define CTRE__UTILITY__HPP + +#define CTRE_CNTTP_COMPILER_CHECK CTLL_CNTTP_COMPILER_CHECK + +#ifdef CTRE_IN_A_MODULE +#define CTRE_EXPORT export +#else +#define CTRE_EXPORT +#endif + +#if __GNUC__ > 9 +#if __has_cpp_attribute(likely) +#define CTRE_LIKELY [[likely]] +#else +#define CTRE_LIKELY +#endif + +#if __has_cpp_attribute(unlikely) +#define CTRE_UNLIKELY [[unlikely]] +#else +#define CTRE_UNLIKELY +#endif +#else +#define CTRE_LIKELY +#define CTRE_UNLIKELY +#endif + +#ifdef _MSC_VER +#define CTRE_FORCE_INLINE __forceinline +#if __has_cpp_attribute(msvc::flatten) +#define CTRE_FLATTEN [[msvc::flatten]] +#elif _MSC_VER >= 1930 && !defined(__clang__) +#define CTRE_FLATTEN [[msvc::flatten]] +#else +#define CTRE_FLATTEN +#endif +#else +#define CTRE_FORCE_INLINE inline __attribute__((always_inline)) +#define CTRE_FLATTEN __attribute__((flatten)) +#endif + +#endif + +#ifndef CTRE_V2__CTRE__FLAGS_AND_MODES__HPP +#define CTRE_V2__CTRE__FLAGS_AND_MODES__HPP + +namespace ctre { + +struct singleline { }; +struct multiline { }; + +struct case_sensitive { }; +struct case_insensitive { }; + +using ci = case_insensitive; +using cs = case_sensitive; + +template struct flag_list { }; + +struct flags { + bool block_empty_match = false; + bool multiline = false; + bool case_insensitive = false; + + constexpr flags() = default; + constexpr flags(const flags &) = default; + constexpr flags(flags &&) = default; + + constexpr CTRE_FORCE_INLINE flags(ctre::singleline v) noexcept { set_flag(v); } + constexpr CTRE_FORCE_INLINE flags(ctre::multiline v) noexcept { set_flag(v); } + constexpr CTRE_FORCE_INLINE flags(ctre::case_sensitive v) noexcept { set_flag(v); } + constexpr CTRE_FORCE_INLINE flags(ctre::case_insensitive v) noexcept { set_flag(v); } + + + template constexpr CTRE_FORCE_INLINE flags(ctll::list) noexcept { + (this->set_flag(Args{}), ...); + } + + constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_case_insensitive) noexcept { + f.case_insensitive = true; + return f; + } + + constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_case_sensitive) noexcept { + f.case_insensitive = false; + return f; + } + + constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_singleline) noexcept { + f.multiline = false; + return f; + } + + constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_multiline) noexcept { + f.multiline = true; + return f; + } + + constexpr CTRE_FORCE_INLINE void set_flag(ctre::singleline) noexcept { + multiline = false; + } + + constexpr CTRE_FORCE_INLINE void set_flag(ctre::multiline) noexcept { + multiline = true; + } + + constexpr CTRE_FORCE_INLINE void set_flag(ctre::case_insensitive) noexcept { + case_insensitive = true; + } + + constexpr CTRE_FORCE_INLINE void set_flag(ctre::case_sensitive) noexcept { + case_insensitive = false; + } +}; + +constexpr CTRE_FORCE_INLINE auto not_empty_match(flags f) { + f.block_empty_match = true; + return f; +} + +constexpr CTRE_FORCE_INLINE auto consumed_something(flags f, bool condition = true) { + if (condition) f.block_empty_match = false; + return f; +} + +constexpr CTRE_FORCE_INLINE bool cannot_be_empty_match(flags f) { + return f.block_empty_match; +} + +constexpr CTRE_FORCE_INLINE bool multiline_mode(flags f) { + return f.multiline; +} + +constexpr CTRE_FORCE_INLINE bool is_case_insensitive(flags f) { + return f.case_insensitive; +} + +} // namespace ctre + +#endif + +#ifndef CTRE_IN_A_MODULE +#include +#endif + +namespace ctre { + +// sfinae check for types here + +template class MatchesCharacter { + template static auto test(CharT c) -> decltype(Y::match_char(c, std::declval()), std::true_type()); + template static auto test(...) -> std::false_type; +public: + template static inline constexpr bool value = decltype(test(std::declval()))(); +}; + +template constexpr CTRE_FORCE_INLINE bool is_ascii_alpha(T v) { + return ((v >= static_cast('a') && v <= static_cast('z')) || (v >= static_cast('A') && v <= static_cast('Z'))); +} + +template constexpr CTRE_FORCE_INLINE bool is_ascii_alpha_lowercase(T v) { + return (v >= static_cast('a')) && (v <= static_cast('z')); +} + +template constexpr CTRE_FORCE_INLINE bool is_ascii_alpha_uppercase(T v) { + return (v >= static_cast('A')) && v <= (static_cast('Z')); +} + +template struct character { + template CTRE_FORCE_INLINE static constexpr bool match_char(CharT value, const flags & f) noexcept { + if constexpr (is_ascii_alpha(V)) { + if (is_case_insensitive(f)) { + if (value == (V ^ static_cast(0x20))) { + return true;// + } + } + } + return value == V; + } +}; + +template struct negative_set { + template CTRE_FORCE_INLINE static constexpr bool match_char(CharT value, const flags & f) noexcept { + return !(Content::match_char(value, f) || ... || false); + } +}; + +template struct set { + template CTRE_FORCE_INLINE static constexpr bool match_char(CharT value, const flags & f) noexcept { + return (Content::match_char(value, f) || ... || false); + } +}; + +template struct enumeration : set...> { }; + +template struct negate { + template CTRE_FORCE_INLINE static constexpr bool match_char(CharT value, const flags & f) noexcept { + return !(Content::match_char(value, f) || ... || false); + } +}; + +template struct char_range { + template CTRE_FORCE_INLINE static constexpr bool match_char(CharT value, const flags & f) noexcept { + if constexpr (is_ascii_alpha_lowercase(A) && is_ascii_alpha_lowercase(B)) { + if (is_case_insensitive(f)) { + if (value >= (A ^ static_cast(0x20)) && value <= (B ^ static_cast(0x20))) { + return true;// + } + } + } else if constexpr (is_ascii_alpha_uppercase(A) && is_ascii_alpha_uppercase(B)) { + if (is_case_insensitive(f)) { + if (value >= (A ^ static_cast(0x20)) && value <= (B ^ static_cast(0x20))) { + return true;// + } + } + } + return (value >= A) && (value <= B); + } +}; +using word_chars = set, char_range<'a','z'>, char_range<'0','9'>, character<'_'> >; + +using space_chars = enumeration<' ', '\t', '\n', '\v', '\f', '\r'>; + +using vertical_space_chars = enumeration< + char{0x000A}, // Linefeed (LF) + char{0x000B}, // Vertical tab (VT) + char{0x000C}, // Form feed (FF) + char{0x000D}, // Carriage return (CR) + char32_t{0x0085}, // Next line (NEL) + char32_t{0x2028}, // Line separator + char32_t{0x2029} // Paragraph separator +>; + +using horizontal_space_chars = enumeration< + char{0x0009}, // Horizontal tab (HT) + char{0x0020}, // Space + char32_t{0x00A0}, // Non-break space + char32_t{0x1680}, // Ogham space mark + char32_t{0x180E}, // Mongolian vowel separator + char32_t{0x2000}, // En quad + char32_t{0x2001}, // Em quad + char32_t{0x2002}, // En space + char32_t{0x2003}, // Em space + char32_t{0x2004}, // Three-per-em space + char32_t{0x2005}, // Four-per-em space + char32_t{0x2006}, // Six-per-em space + char32_t{0x2007}, // Figure space + char32_t{0x2008}, // Punctuation space + char32_t{0x2009}, // Thin space + char32_t{0x200A}, // Hair space + char32_t{0x202F}, // Narrow no-break space + char32_t{0x205F}, // Medium mathematical space + char32_t{0x3000} // Ideographic space +>; + +using alphanum_chars = set, char_range<'a','z'>, char_range<'0','9'> >; + +using alpha_chars = set, char_range<'a','z'> >; + +using xdigit_chars = set, char_range<'a','f'>, char_range<'0','9'> >; + +using punct_chars + = enumeration<'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', + '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', + '^', '_', '`', '{', '|', '}', '~'>; + +using digit_chars = char_range<'0','9'>; + +using ascii_chars = char_range<'\x00','\x7F'>; + +} + +#endif + +#ifndef CTRE_IN_A_MODULE +#include +#endif + +namespace ctre { + +// special helpers for matching +struct accept { }; +struct reject { }; +struct start_mark { }; +struct end_mark { }; +struct end_cycle_mark { }; +struct end_lookahead_mark { }; +struct end_lookbehind_mark { }; +template struct numeric_mark { }; + +struct any { }; + +// actual AST of regexp +template struct string { }; +template struct select { }; +template struct sequence { }; +struct empty { }; + +template struct repeat { }; +template using plus = repeat<1,0,Content...>; +template using star = repeat<0,0,Content...>; + +template struct lazy_repeat { }; +template using lazy_plus = lazy_repeat<1,0,Content...>; +template using lazy_star = lazy_repeat<0,0,Content...>; + +template struct possessive_repeat { }; +template using possessive_plus = possessive_repeat<1,0,Content...>; +template using possessive_star = possessive_repeat<0,0,Content...>; + +template using optional = repeat<0,1,Content...>; +template using lazy_optional = lazy_repeat<0,1,Content...>; +template using possessive_optional = possessive_repeat<0,1,Content...>; + +template struct capture { }; + +template struct capture_with_name { }; + +template struct back_reference { }; +template struct back_reference_with_name { }; + +template struct look_start { }; + +template struct lookahead_positive { }; +template struct lookahead_negative { }; + +template struct lookbehind_positive { }; +template struct lookbehind_negative { }; + +struct atomic_start { }; + +template struct atomic_group { }; + +template struct boundary { }; +template struct not_boundary { }; + +using word_boundary = boundary; +using not_word_boundary = not_boundary; + +struct assert_subject_begin { }; +struct assert_subject_end { }; +struct assert_subject_end_line{ }; +struct assert_line_begin { }; +struct assert_line_end { }; + +template struct mode_switch { }; + +} + +#endif + +#ifndef CTRE__ATOMS_UNICODE__HPP +#define CTRE__ATOMS_UNICODE__HPP + +// master branch is not including unicode db (for now) +#ifndef H_COR3NTIN_UNICODE_SYNOPSYS +#define H_COR3NTIN_UNICODE_SYNOPSYS + +#ifndef UNICODE_DB_IN_A_MODULE +#include +#endif + +namespace uni +{ + enum class category; + enum class property; + enum class version : unsigned char; + enum class script ; + enum class block; + + struct script_extensions_view { + constexpr script_extensions_view(char32_t); + + struct sentinel {}; + struct iterator { + + constexpr iterator(char32_t c); + constexpr script operator*() const; + + constexpr iterator& operator++(int); + + constexpr iterator operator++(); + + constexpr bool operator==(sentinel) const; + constexpr bool operator!=(sentinel) const; + + private: + char32_t m_c; + script m_script; + int idx = 1; + }; + + constexpr iterator begin() const; + constexpr sentinel end() const; + + private: + char32_t c; + }; + + struct numeric_value { + + constexpr double value() const; + constexpr long long numerator() const; + constexpr int denominator() const; + constexpr bool is_valid() const; + + protected: + constexpr numeric_value() = default; + constexpr numeric_value(long long n, int16_t d); + + long long _n = 0; + int16_t _d = 0; + friend constexpr numeric_value cp_numeric_value(char32_t cp); + }; + + constexpr category cp_category(char32_t cp); + constexpr script cp_script(char32_t cp); + constexpr script_extensions_view cp_script_extensions(char32_t cp); + constexpr version cp_age(char32_t cp); + constexpr block cp_block(char32_t cp); + constexpr bool cp_is_valid(char32_t cp); + constexpr bool cp_is_assigned(char32_t cp); + constexpr bool cp_is_ascii(char32_t cp); + constexpr numeric_value cp_numeric_value(char32_t cp); + + template