gnucash stable: Multiple changes pushed

Christopher Lam clam at code.gnucash.org
Sat May 16 20:43:43 EDT 2026


Updated	 via  https://github.com/Gnucash/gnucash/commit/df9380c2 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/384043ac (commit)
	 via  https://github.com/Gnucash/gnucash/commit/0d21fdc9 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/96dac7bb (commit)
	from  https://github.com/Gnucash/gnucash/commit/bf1264b5 (commit)



commit df9380c2a80f92e8d0c003cb461e898489233d06
Merge: bf1264b561 384043ac41
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sun May 17 08:41:06 2026 +0800

    Merge branch 'ctre-regex' into stable


commit 384043ac41ab2f8e59ab746b5b87f503c7c74483
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sat May 16 18:27:12 2026 +0800

    [gnc-filepath-utils.cpp] use ctre instead of std::regex

diff --git a/libgnucash/core-utils/CMakeLists.txt b/libgnucash/core-utils/CMakeLists.txt
index 4fc2ad7ff1..3f66cf7410 100644
--- a/libgnucash/core-utils/CMakeLists.txt
+++ b/libgnucash/core-utils/CMakeLists.txt
@@ -57,6 +57,7 @@ target_link_libraries(gnc-core-utils
         ${GOBJECT_LDFLAGS}
         ${GTK_MAC_LDFLAGS}
         ${ICU_LIBRARIES}
+        ctre
         "$<$<BOOL:${MAC_INTEGRATION}>:${OSX_EXTRA_LIBRARIES}>")
 
 target_compile_definitions(gnc-core-utils
diff --git a/libgnucash/core-utils/gnc-filepath-utils.cpp b/libgnucash/core-utils/gnc-filepath-utils.cpp
index fe3e31e5ee..dea726b135 100644
--- a/libgnucash/core-utils/gnc-filepath-utils.cpp
+++ b/libgnucash/core-utils/gnc-filepath-utils.cpp
@@ -66,7 +66,7 @@
 #include "gnc-locale-utils.hpp"
 #include <boost/filesystem.hpp>
 #include <boost/locale.hpp>
-#include <regex>
+#include <ctre.hpp>
 #include <iostream>
 
 /* Below cvt and bfs_locale should be used with boost::filesystem::path (bfs)
@@ -1321,23 +1321,22 @@ gnc_list_all_paths ()
     };
 }
 
-static const std::regex
+static constexpr ctll::fixed_string
 backup_regex (".*[.](?:xac|gnucash)[.][0-9]{14}[.](?:xac|gnucash)$");
 
 gboolean gnc_filename_is_backup (const char *filename)
 {
     g_return_val_if_fail (filename, FALSE);
-    return std::regex_match (filename, backup_regex);
+    return ctre::match<backup_regex>(filename);
 }
 
-static const std::regex
+static constexpr ctll::fixed_string
 datafile_regex (".*[.](?:xac|gnucash)$");
 
 gboolean gnc_filename_is_datafile (const char *filename)
 {
     g_return_val_if_fail (filename, FALSE);
-    return !gnc_filename_is_backup (filename) &&
-        std::regex_match (filename, datafile_regex);
+    return !gnc_filename_is_backup (filename) && ctre::match<datafile_regex>(filename);
 }
 
 std::ofstream
diff --git a/libgnucash/core-utils/test/CMakeLists.txt b/libgnucash/core-utils/test/CMakeLists.txt
index f5879a696f..1e5ad913a1 100644
--- a/libgnucash/core-utils/test/CMakeLists.txt
+++ b/libgnucash/core-utils/test/CMakeLists.txt
@@ -37,6 +37,7 @@ set(gtest_core_utils_LIBS
   PkgConfig::GLIB2
   ${Boost_LIBRARIES}
   ${GTHREAD_LDFLAGS}
+  ctre
   gtest)
 
 set(test_gnc_path_util_SOURCES

commit 0d21fdc9f7815b878314e31970717d20cb5ee01f
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Fri May 15 17:22:53 2026 +0800

    [ctre.hpp] add single-header ctre v3.11.0

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0fbab46baa..e9811d4de9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -900,6 +900,7 @@ endif()
 
 # The subdirectories
 add_subdirectory (borrowed)
+add_library(ctre_global ALIAS ctre)
 add_subdirectory (data)
 add_subdirectory (doc)
 # Note: po should be processed before gnucash - it provides LINGUAS, used to generate desktop and appdata files
diff --git a/borrowed/CMakeLists.txt b/borrowed/CMakeLists.txt
index eb2c5159da..301f2ea59d 100644
--- a/borrowed/CMakeLists.txt
+++ b/borrowed/CMakeLists.txt
@@ -3,6 +3,7 @@ add_subdirectory(goffice)
 add_subdirectory(chartjs-2)
 add_subdirectory(chartjs-4)
 add_subdirectory(guile-json)
+add_subdirectory(ctre)
 
 set_local_dist(borrowed_DIST_local jenny/jenny.c CMakeLists.txt README)
 set(borrowed_DIST
@@ -12,4 +13,5 @@ set(borrowed_DIST
     ${libc_DIST}
     ${guile-json_DIST}
     ${goffice_DIST}
+    ${ctre_DIST}
     PARENT_SCOPE)
diff --git a/borrowed/ctre/CMakeLists.txt b/borrowed/ctre/CMakeLists.txt
new file mode 100644
index 0000000000..a99c637517
--- /dev/null
+++ b/borrowed/ctre/CMakeLists.txt
@@ -0,0 +1,13 @@
+
+add_library(ctre INTERFACE)
+
+target_include_directories(ctre INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
+
+set(ctre_DIST ${ctre_DIST_LOCAL} PARENT_SCOPE)
+
+set_local_dist(ctre_DIST_LOCAL
+  CMakeLists.txt
+  ctre.hpp
+)
+
+set(ctre_DIST ${ctre_DIST_LOCAL} PARENT_SCOPE)
diff --git a/borrowed/ctre/LICENSE b/borrowed/ctre/LICENSE
new file mode 100644
index 0000000000..bd8b243dfa
--- /dev/null
+++ b/borrowed/ctre/LICENSE
@@ -0,0 +1,218 @@
+                                 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.
diff --git a/borrowed/ctre/ctre.hpp b/borrowed/ctre/ctre.hpp
new file mode 100644
index 0000000000..0e0ac4a487
--- /dev/null
+++ b/borrowed/ctre/ctre.hpp
@@ -0,0 +1,5993 @@
+/*
+                                 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 <utility>
+#include <cstddef>
+#include <string_view>
+#include <array>
+#include <cstdint>
+#endif
+
+#ifndef CTLL__UTILITIES__HPP
+#define CTLL__UTILITIES__HPP
+
+#ifndef CTLL_IN_A_MODULE
+#include <type_traits>
+#endif
+
+#ifdef CTLL_IN_A_MODULE
+#define CTLL_EXPORT export
+#else
+#define CTLL_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 <bool> struct conditional_helper;
+	
+template <> struct conditional_helper<true> {
+	template <typename A, typename> using type = A;
+};
+
+template <> struct conditional_helper<false> {
+	template <typename, typename B> using type = B;
+};
+
+template <bool V, typename A, typename B> using conditional = typename conditional_helper<V>::template type<A,B>;
+	
+}
+
+#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<uint32_t>(first_unit), 1};
+	else if ((first_unit & 0b1110'0000) == 0b1100'0000) return {static_cast<uint32_t>(first_unit & 0b0001'1111), 2};
+	else if ((first_unit & 0b1111'0000) == 0b1110'0000) return {static_cast<uint32_t>(first_unit & 0b0000'1111), 3};
+	else if ((first_unit & 0b1111'1000) == 0b1111'0000) return {static_cast<uint32_t>(first_unit & 0b0000'0111), 4};
+	else if ((first_unit & 0b1111'1100) == 0b1111'1000) return {static_cast<uint32_t>(first_unit & 0b0000'0011), 5};
+	else if ((first_unit & 0b1111'1100) == 0b1111'1100) return {static_cast<uint32_t>(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<uint32_t>(first_unit & 0b0000001111111111), 2};
+	else return {first_unit, 1};
+}
+
+struct construct_from_pointer_t { };
+
+constexpr auto construct_from_pointer = construct_from_pointer_t{};
+
+CTLL_EXPORT template <size_t N> struct fixed_string {
+	char32_t content[N] = {};
+	size_t real_size{0};
+	bool correct_flag{true};
+	
+	template <typename T> constexpr fixed_string(construct_from_pointer_t, const T * input) noexcept {
+		if constexpr (std::is_same_v<T, char>) {
+			#ifdef CTRE_STRING_IS_UTF8
+				size_t out{0};
+				for (size_t i{0}; i < N; ++i) {
+					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<char32_t>(info.value);
+							real_size++;
+							break;
+						default:
+							correct_flag = false;
+							return;
+					}
+				}
+			#else
+				for (size_t i{0}; i < N; ++i) {
+					content[i] = static_cast<uint8_t>(input[i]);
+					real_size++;
+				}
+			#endif
+#if defined(__cpp_char8_t)
+		} else if constexpr (std::is_same_v<T, char8_t>) {
+			size_t out{0};
+			for (size_t i{0}; i < N; ++i) {
+				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<char32_t>(info.value);
+						real_size++;
+						break;
+					default:
+						correct_flag = false;
+						return;
+				}
+			}
+#endif
+		} else if constexpr (std::is_same_v<T, char16_t>) {
+			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 {
+					content[out++] = info.value;
+				}
+			}
+			real_size = out;
+		} else if constexpr (std::is_same_v<T, wchar_t> || std::is_same_v<T, char32_t>) {
+			for (size_t i{0}; i < N; ++i) {
+				content[i] = static_cast<char32_t>(input[i]);
+				real_size++;
+			}
+		}
+	}
+	
+	template <typename T> constexpr fixed_string(const std::array<T, N> & in) noexcept: fixed_string{construct_from_pointer, in.data()} { }
+	template <typename T> 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 <size_t M> constexpr bool is_same_as(const fixed_string<M> & 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<char32_t>() const noexcept {
+		return std::basic_string_view<char32_t>{content, size()};
+	}
+};
+
+template <> class fixed_string<0> {
+	static constexpr char32_t empty[1] = {0};
+public:
+	template <typename T> constexpr fixed_string(const T *) noexcept {
+		
+	}
+	constexpr fixed_string(std::initializer_list<char32_t>) 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<char32_t>() const noexcept {
+		return std::basic_string_view<char32_t>{empty, 0};
+	}
+};
+
+template <typename CharT, size_t N> fixed_string(const CharT (&)[N]) -> fixed_string<N-1>;
+template <typename CharT, size_t N> fixed_string(const std::array<CharT,N> &) -> fixed_string<N>;
+
+template <size_t N> fixed_string(fixed_string<N>) -> fixed_string<N>;
+
+}
+
+#endif
+
+#ifndef CTLL__TYPE_STACK__HPP
+#define CTLL__TYPE_STACK__HPP
+
+namespace ctll {
+
+template <typename... Ts> struct list { };
+	
+struct _nothing { };
+
+using empty_list = list<>;
+
+// calculate size of list content
+template <typename... Ts> constexpr auto size(list<Ts...>) noexcept { return sizeof...(Ts); }
+
+	
+// check if the list is empty
+template <typename... Ts> constexpr bool empty(list<Ts...>) noexcept { return false; }
+constexpr bool empty(empty_list) { return true; }
+
+// concat two lists together left to right
+template <typename... As, typename... Bs> constexpr auto concat(list<As...>, list<Bs...>) noexcept -> list<As..., Bs...> { return {}; }
+
+// push something to the front of a list
+template <typename T, typename... As> constexpr auto push_front(T, list<As...>) noexcept -> list<T, As...> { return {}; }
+
+// pop element from the front of a list
+template <typename T, typename... As> constexpr auto pop_front(list<T, As...>) noexcept -> list<As...> { return {}; }
+constexpr auto pop_front(empty_list) -> empty_list;
+
+// pop element from the front of a list and return new typelist too
+template <typename Front, typename List> struct list_pop_pair {
+	Front front{};
+	List list{};
+	constexpr list_pop_pair() = default;
+};
+
+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 {}; }
+template <typename T = _nothing> constexpr auto pop_and_get_front(empty_list, T = T()) noexcept -> list_pop_pair<T, empty_list> { return {}; }
+
+// return front of the list
+template <typename Head, typename... As, typename T = _nothing> constexpr auto front(list<Head, As...>, T = T()) noexcept -> Head { return {}; }
+template <typename T = _nothing> constexpr auto front(empty_list, T = T()) noexcept -> T { return {}; }
+
+// rotate list
+template <typename T> struct rotate_item {
+	template <typename... Ts> friend constexpr auto operator+(list<Ts...>, rotate_item<T>) noexcept -> list<T, Ts...> { return {}; }
+};
+
+template <typename... Ts> constexpr auto rotate(list<Ts...>) -> decltype((list<>{} + ... + rotate_item<Ts>{})) {
+	return {};
+}
+
+// set operations
+template <typename T> struct item_matcher {
+	struct not_selected {
+		template <typename... Ts> friend constexpr auto operator+(list<Ts...>, not_selected) -> list<Ts...>;
+	};
+	template <typename Y> struct wrapper {
+		template <typename... Ts> friend constexpr auto operator+(list<Ts...>, wrapper<Y>) -> list<Ts...,Y>;
+	};
+
+	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 <typename Y> static constexpr auto select(Y) { return wrapper<Y>{}; }
+};
+
+template <typename T, typename... Ts> constexpr bool exists_in(T, list<Ts...>) noexcept {
+	return (item_matcher<T>::check(Ts{}) || ... || false);
+}
+
+template <typename T, typename... Ts> constexpr auto add_item(T item, list<Ts...> l) noexcept {
+	if constexpr (exists_in(item, l)) {
+		return l;
+	} else {
+		return list<Ts..., T>{};
+	}
+}
+
+template <typename T, typename... Ts> constexpr auto remove_item(T, list<Ts...>) noexcept {
+	item_matcher<T> 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 <auto v> 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<T...> is alias to list<T...>
+template <typename... Ts> using push = list<Ts...>;
+
+// 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 <typename... Ts> constexpr auto push_front(pop_input, list<Ts...>) -> list<Ts...> { return {}; }
+
+template <typename... Ts> constexpr auto push_front(epsilon, list<Ts...>) -> list<Ts...> { return {}; }
+
+template <typename... As, typename... Bs> constexpr auto push_front(list<As...>, list<Bs...>) -> list<As..., Bs...> { return {}; }
+
+template <typename T, typename... As> constexpr auto pop_front_and_push_front(T item, list<As...> l) {
+	return push_front(item, pop_front(l));
+}
+
+// SPECIAL matching types for nicer grammars
+
+// match any term
+struct anything {
+	constexpr inline anything() noexcept { }
+	template <auto V> constexpr anything(term<V>) noexcept;
+};
+
+// match range of term A-B
+template <auto A, decltype(A) B> struct range {
+	constexpr inline range() noexcept { }
+	//template <auto V> constexpr range(term<V>) noexcept requires (A <= V) && (V <= B);
+	template <auto V, typename = std::enable_if_t<(A <= V) && (V <= B)>> constexpr range(term<V>) noexcept;
+};
+
+#ifdef __EDG__
+template <auto V, auto... Set> struct contains {
+	static constexpr bool value = ((Set == V) || ... || false);
+};
+#endif
+
+// match terms defined in set
+template <auto... Def> struct set {
+	constexpr inline set() noexcept { }
+	#ifdef __EDG__
+	template <auto V, typename = std::enable_if_t<contains<V, Def...>::value>> constexpr set(term<V>) noexcept;
+	#else
+	template <auto V, typename = std::enable_if_t<((Def == V) || ... || false)>> constexpr set(term<V>) noexcept;
+	#endif
+};
+
+// match terms not defined in set
+template <auto... Def> struct neg_set {
+	constexpr inline neg_set() noexcept { }
+	
+	#ifdef __EDG__
+	template <auto V, typename = std::enable_if_t<!contains<V, Def...>::value>> constexpr neg_set(term<V>) noexcept;
+	#else
+	template <auto V, typename = std::enable_if_t<!((Def == V) || ... || false)>> constexpr neg_set(term<V>) noexcept;
+	#endif
+};
+
+// AUGMENTED grammar which completes user-defined grammar for all other cases
+template <typename Grammar> 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 <auto A> static constexpr auto rule(term<A>, term<A>) -> ctll::pop_input;
+	
+	// if the type on stack (range, set, neg_set, anything) is constructible from the terminal => pop_input
+	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>;
+	
+	// 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<Grammar::_start>;
+	using start_stack = list<typename Grammar::_start>;
+};
+
+}
+
+#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 <typename Action, typename InputSymbol, typename Subject> static constexpr auto apply(Action, InputSymbol, Subject subject) {
+			return subject;
+		}
+	};
+	
+	template <typename Actions> struct identity: public Actions {
+		using Actions::apply;
+		// allow empty_subject to exists
+		template <typename Action, auto V> constexpr static auto apply(Action, term<V>, empty_subject) -> empty_subject { return {}; }
+		template <typename Action> constexpr static auto apply(Action, epsilon, empty_subject) -> empty_subject { return {}; }	
+	};
+	
+	template <typename Actions> struct ignore_unknown: public Actions {
+		using Actions::apply;
+		// allow flow thru unknown actions
+		template <typename Action, auto V, typename Subject> constexpr static auto apply(Action, term<V>, Subject) -> Subject { return {}; }
+		template <typename Action, typename Subject> constexpr static auto apply(Action, epsilon, Subject) -> Subject { return {}; }	
+	};
+}
+
+#endif
+
+#ifndef CTLL_IN_A_MODULE
+#include <limits>
+#endif
+
+namespace ctll {
+
+enum class decision {
+	reject,
+	accept,
+	undecided
+};
+
+struct placeholder { };
+
+template <size_t> using index_placeholder = placeholder;
+
+#if CTLL_CNTTP_COMPILER_CHECK
+template <typename Grammar, ctll::fixed_string input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = false> struct parser { // in c++20
+#else
+template <typename Grammar, const auto & input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = false> 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<IgnoreUnknownActions, ignore_unknown<ActionSelector>, identity<ActionSelector>>;
+	using grammar = augment_grammar<Grammar>;
+	
+	template <size_t Pos, typename Stack, typename Subject, decision Decision> 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<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template decide<Pos, Stack, Subject>({}, {});
+			} else {
+				// if there is decision already => just push it to the end of fold expression
+				return *this;
+			}
+		}
+	};
+	
+	template <size_t Pos> static constexpr auto get_current_term() noexcept {
+		if constexpr (Pos < input.size()) {
+			constexpr auto value = input[Pos];
+			if constexpr (value <= static_cast<decltype(value)>((std::numeric_limits<char>::max)())) {
+				return term<static_cast<char>(value)>{};
+			} else {
+				return term<value>{};
+			}
+			
+		} else {
+			// return epsilon if we are past the input
+			return epsilon{};
+		}
+	}
+	template <size_t Pos> 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<decltype(value)>((std::numeric_limits<char>::max)())) {
+				return term<static_cast<char>(value)>{};
+			} else {
+				return term<value>{};
+			}
+		} else {
+			return epsilon{};
+		}
+	}
+	// if rule is accept => return true and subject
+	template <size_t Pos, typename Terminal, typename Stack, typename Subject> 
+	static constexpr auto move(ctll::accept, Terminal, Stack, Subject) noexcept {
+		return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos, Stack, Subject, decision::accept>();
+	}
+	// if rule is reject => return false and subject
+	template <size_t Pos, typename Terminal, typename Stack, typename Subject>
+	static constexpr auto move(ctll::reject, Terminal, Stack, Subject) noexcept {
+		return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos, Stack, Subject, decision::reject>();
+	}
+	// if rule is pop_input => move to next character
+	template <size_t Pos, typename Terminal, typename Stack, typename Subject>
+	static constexpr auto move(ctll::pop_input, Terminal, Stack, Subject) noexcept {
+		return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos+1, Stack, Subject, decision::undecided>();
+	}
+	// if rule is string => push it to the front of stack
+	template <size_t Pos, typename... Content, typename Terminal, typename Stack, typename Subject>
+	static constexpr auto move(push<Content...> string, Terminal, Stack stack, Subject subject) noexcept {
+		return decide<Pos>(push_front(string, stack), subject);
+	}
+	// if rule is epsilon (empty string) => continue
+	template <size_t Pos, typename Terminal, typename Stack, typename Subject>
+	static constexpr auto move(epsilon, Terminal, Stack stack, Subject subject) noexcept {
+		return decide<Pos>(stack, subject);
+	}
+	// if rule is string with current character at the beginning (term<V>) => move to next character 
+	// and push string without the character (quick LL(1))
+	template <size_t Pos, auto V, typename... Content, typename Stack, typename Subject>
+	static constexpr auto move(push<term<V>, Content...>, term<V>, Stack stack, Subject) noexcept {
+		constexpr auto local_input = input;
+		return typename parser<Grammar, local_input, ActionSelector, IgnoreUnknownActions>::template results<Pos+1, decltype(push_front(list<Content...>(), stack)), Subject, decision::undecided>();
+	}
+	// if rule is string with any character at the beginning (compatible with current term<T>) => move to next character 
+	// and push string without the character (quick LL(1))
+	template <size_t Pos, auto V, typename... Content, auto T, typename Stack, typename Subject>
+	static constexpr auto move(push<anything, Content...>, term<T>, Stack stack, Subject) noexcept {
+		constexpr auto local_input = input;
+		return typename parser<Grammar, local_input, ActionSelector, IgnoreUnknownActions>::template results<Pos+1, decltype(push_front(list<Content...>(), stack)), Subject, decision::undecided>();
+	}
+	// decide if we need to take action or move
+	template <size_t Pos, typename Stack, typename Subject> 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<ctll::action, decltype(top_symbol)>) {
+			auto subject = Actions::apply(top_symbol, get_previous_term<Pos>(), previous_subject);
+			
+			// in case that semantic action is error => reject input
+			if constexpr (std::is_same_v<ctll::reject, decltype(subject)>) {
+				return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos, Stack, Subject, decision::reject>();
+			} else {
+				return decide<Pos>(stack, subject);
+			}
+		} else {
+			// all other cases are ordinary for LL(1) parser
+			auto current_term = get_current_term<Pos>();
+			auto rule = decltype(grammar::rule(top_symbol,current_term))();
+			return move<Pos>(rule, current_term, stack, previous_subject);
+		}
+	}
+	
+	// trampolines with folded expression
+	template <typename Subject, size_t... Pos> static constexpr auto trampoline_decide(Subject, std::index_sequence<Pos...>) 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<Pos+1>());
+		return v;
+	}
+	
+	template <typename Subject = empty_subject> 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<input.size()>());
+	}
+	
+	template <typename Subject = empty_subject> using output = decltype(trampoline_decide<Subject>());
+	template <typename Subject = empty_subject> static inline constexpr bool correct_with = trampoline_decide<Subject>();
+
+};
+
+} // 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_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 opt_content {};
+	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_empty: 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<ctll::anything, backslash, repeat, string2, content2>;
+	static constexpr auto rule(s, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2>;
+	static constexpr auto rule(s, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2>;
+	static constexpr auto rule(s, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2>;
+	static constexpr auto rule(s, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2>;
+	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>;
+	static constexpr auto rule(s, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
+	static constexpr auto rule(s, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2>;
+	static constexpr auto rule(s, ctll::term<'|'>) -> ctll::push<ctll::anything, push_empty, opt_content, make_alternate>;
+	static constexpr auto rule(s, ctll::epsilon) -> ctll::push<push_empty>;
+	static constexpr auto rule(s, ctll::set<'\x29','*','+','?','\x7B','\x7D'>) -> ctll::reject;
+
+	static constexpr auto rule(a, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2, make_alternate>;
+	static constexpr auto rule(a, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2, make_alternate>;
+	static constexpr auto rule(a, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2, make_alternate>;
+	static constexpr auto rule(a, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2, make_alternate>;
+	static constexpr auto rule(a, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2, make_alternate>;
+	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>;
+	static constexpr auto rule(a, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2, make_alternate>;
+	static constexpr auto rule(a, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2, make_alternate>;
+	static constexpr auto rule(a, ctll::term<'\x29'>) -> ctll::push<push_empty, make_alternate>;
+	static constexpr auto rule(a, ctll::epsilon) -> ctll::push<push_empty, make_alternate>;
+	static constexpr auto rule(a, ctll::set<'*','+','?','\x7B','|','\x7D'>) -> ctll::reject;
+
+	static constexpr auto rule(b, ctll::term<','>) -> ctll::push<ctll::anything, n>;
+	static constexpr auto rule(b, ctll::term<'\x7D'>) -> ctll::push<repeat_exactly, ctll::anything>;
+
+	static constexpr auto rule(backslash, ctll::term<'d'>) -> ctll::push<ctll::anything, class_digit>;
+	static constexpr auto rule(backslash, ctll::term<'h'>) -> ctll::push<ctll::anything, class_horizontal_space>;
+	static constexpr auto rule(backslash, ctll::term<'H'>) -> ctll::push<ctll::anything, class_non_horizontal_space>;
+	static constexpr auto rule(backslash, ctll::term<'V'>) -> ctll::push<ctll::anything, class_non_vertical_space>;
+	static constexpr auto rule(backslash, ctll::term<'D'>) -> ctll::push<ctll::anything, class_nondigit>;
+	static constexpr auto rule(backslash, ctll::term<'N'>) -> ctll::push<ctll::anything, class_nonnewline>;
+	static constexpr auto rule(backslash, ctll::term<'S'>) -> ctll::push<ctll::anything, class_nonspace>;
+	static constexpr auto rule(backslash, ctll::term<'W'>) -> ctll::push<ctll::anything, class_nonword>;
+	static constexpr auto rule(backslash, ctll::term<'s'>) -> ctll::push<ctll::anything, class_space>;
+	static constexpr auto rule(backslash, ctll::term<'v'>) -> ctll::push<ctll::anything, class_vertical_space>;
+	static constexpr auto rule(backslash, ctll::term<'w'>) -> ctll::push<ctll::anything, class_word>;
+	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>;
+	static constexpr auto rule(backslash, ctll::term<'g'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, m>;
+	static constexpr auto rule(backslash, ctll::term<'p'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property>;
+	static constexpr auto rule(backslash, ctll::term<'P'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property_negative>;
+	static constexpr auto rule(backslash, ctll::term<'u'>) -> ctll::push<ctll::anything, k>;
+	static constexpr auto rule(backslash, ctll::term<'x'>) -> ctll::push<ctll::anything, l>;
+	static constexpr auto rule(backslash, ctll::term<'A'>) -> ctll::push<ctll::anything, push_assert_subject_begin>;
+	static constexpr auto rule(backslash, ctll::term<'z'>) -> ctll::push<ctll::anything, push_assert_subject_end>;
+	static constexpr auto rule(backslash, ctll::term<'Z'>) -> ctll::push<ctll::anything, push_assert_subject_end_with_lineend>;
+	static constexpr auto rule(backslash, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character>;
+	static constexpr auto rule(backslash, ctll::term<'a'>) -> ctll::push<ctll::anything, push_character_alarm>;
+	static constexpr auto rule(backslash, ctll::term<'e'>) -> ctll::push<ctll::anything, push_character_escape>;
+	static constexpr auto rule(backslash, ctll::term<'f'>) -> ctll::push<ctll::anything, push_character_formfeed>;
+	static constexpr auto rule(backslash, ctll::term<'n'>) -> ctll::push<ctll::anything, push_character_newline>;
+	static constexpr auto rule(backslash, ctll::term<'0'>) -> ctll::push<ctll::anything, push_character_null>;
+	static constexpr auto rule(backslash, ctll::term<'r'>) -> ctll::push<ctll::anything, push_character_return_carriage>;
+	static constexpr auto rule(backslash, ctll::term<'t'>) -> ctll::push<ctll::anything, push_character_tab>;
+	static constexpr auto rule(backslash, ctll::term<'B'>) -> ctll::push<ctll::anything, push_not_word_boundary>;
+	static constexpr auto rule(backslash, ctll::term<'b'>) -> ctll::push<ctll::anything, push_word_boundary>;
+
+	static constexpr auto rule(backslash_range, ctll::term<'u'>) -> ctll::push<ctll::anything, k>;
+	static constexpr auto rule(backslash_range, ctll::term<'x'>) -> ctll::push<ctll::anything, l>;
+	static constexpr auto rule(backslash_range, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character>;
+	static constexpr auto rule(backslash_range, ctll::term<'a'>) -> ctll::push<ctll::anything, push_character_alarm>;
+	static constexpr auto rule(backslash_range, ctll::term<'e'>) -> ctll::push<ctll::anything, push_character_escape>;
+	static constexpr auto rule(backslash_range, ctll::term<'f'>) -> ctll::push<ctll::anything, push_character_formfeed>;
+	static constexpr auto rule(backslash_range, ctll::term<'n'>) -> ctll::push<ctll::anything, push_character_newline>;
+	static constexpr auto rule(backslash_range, ctll::term<'0'>) -> ctll::push<ctll::anything, push_character_null>;
+	static constexpr auto rule(backslash_range, ctll::term<'r'>) -> ctll::push<ctll::anything, push_character_return_carriage>;
+	static constexpr auto rule(backslash_range, ctll::term<'t'>) -> ctll::push<ctll::anything, push_character_tab>;
+
+	static constexpr auto rule(block, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
+	static constexpr auto rule(block, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
+	static constexpr auto rule(block, ctll::term<'?'>) -> ctll::push<ctll::anything, d>;
+	static constexpr auto rule(block, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
+	static constexpr auto rule(block, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
+	static constexpr auto rule(block, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
+	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'>>;
+	static constexpr auto rule(block, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
+	static constexpr auto rule(block, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2, make_capture, ctll::term<'\x29'>>;
+	static constexpr auto rule(block, ctll::term<'|'>) -> ctll::push<ctll::anything, push_empty, content_or_empty, make_alternate, make_capture, ctll::term<'\x29'>>;
+	static constexpr auto rule(block, ctll::term<'\x29'>) -> ctll::push<push_empty, make_capture, ctll::anything>;
+	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<ctll::anything, push_name, block_name2>;
+
+	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>;
+
+	static constexpr auto rule(c, ctll::term<'['>) -> ctll::push<ctll::anything, ctll::term<':'>, i, range, set_start, set2b, set_make, ctll::term<']'>>;
+	static constexpr auto rule(c, ctll::term<'\\'>) -> ctll::push<ctll::anything, e, set_start, set2b, set_make, ctll::term<']'>>;
+	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<']'>>;
+	static constexpr auto rule(c, _others) -> ctll::push<ctll::anything, push_character, range, set_start, set2b, set_make, ctll::term<']'>>;
+	static constexpr auto rule(c, ctll::term<'^'>) -> ctll::push<ctll::anything, set2a, set_make_negative, ctll::term<']'>>;
+	static constexpr auto rule(c, ctll::set<'-',']'>) -> ctll::reject;
+
+	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>;
+	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>;
+	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>;
+	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>;
+	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>;
+	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>;
+	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>;
+	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>;
+	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>;
+	static constexpr auto rule(class_named_name, ctll::term<'a'>) -> ctll::push<ctll::anything, g>;
+	static constexpr auto rule(class_named_name, ctll::term<'p'>) -> ctll::push<ctll::anything, h>;
+
+	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<ctll::anything, a>;
+
+	static constexpr auto rule(content_in_capture, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2>;
+	static constexpr auto rule(content_in_capture, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2>;
+	static constexpr auto rule(content_in_capture, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2>;
+	static constexpr auto rule(content_in_capture, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2>;
+	static constexpr auto rule(content_in_capture, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2>;
+	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>;
+	static constexpr auto rule(content_in_capture, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
+	static constexpr auto rule(content_in_capture, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2>;
+	static constexpr auto rule(content_in_capture, ctll::term<'|'>) -> ctll::push<ctll::anything, push_empty, content_or_empty, make_alternate>;
+	static constexpr auto rule(content_in_capture, ctll::term<'\x29'>) -> ctll::push<push_empty>;
+	static constexpr auto rule(content_in_capture, ctll::set<'*','+','?','\x7B','\x7D'>) -> ctll::reject;
+
+	static constexpr auto rule(content_or_empty, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2>;
+	static constexpr auto rule(content_or_empty, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2>;
+	static constexpr auto rule(content_or_empty, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2>;
+	static constexpr auto rule(content_or_empty, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2>;
+	static constexpr auto rule(content_or_empty, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2>;
+	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>;
+	static constexpr auto rule(content_or_empty, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
+	static constexpr auto rule(content_or_empty, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2>;
+	static constexpr auto rule(content_or_empty, ctll::term<'\x29'>) -> ctll::push<push_empty>;
+	static constexpr auto rule(content_or_empty, ctll::set<'*','+','?','\x7B','|','\x7D'>) -> ctll::reject;
+
+	static constexpr auto rule(d, ctll::term<'i'>) -> ctll::push<ctll::anything, mode_case_insensitive, mode_switch2>;
+	static constexpr auto rule(d, ctll::term<'c'>) -> ctll::push<ctll::anything, mode_case_sensitive, mode_switch2>;
+	static constexpr auto rule(d, ctll::term<'m'>) -> ctll::push<ctll::anything, mode_multiline, mode_switch2>;
+	static constexpr auto rule(d, ctll::term<'s'>) -> ctll::push<ctll::anything, mode_singleline, mode_switch2>;
+	static constexpr auto rule(d, ctll::term<'<'>) -> ctll::push<ctll::anything, o>;
+	static constexpr auto rule(d, ctll::term<':'>) -> ctll::push<ctll::anything, reset_capture, content_in_capture, ctll::term<'\x29'>>;
+	static constexpr auto rule(d, ctll::term<'>'>) -> ctll::push<ctll::anything, reset_capture, start_atomic, content_in_capture, make_atomic, ctll::term<'\x29'>>;
+	static constexpr auto rule(d, ctll::term<'!'>) -> ctll::push<ctll::anything, reset_capture, start_lookahead_negative, content_in_capture, look_finish, ctll::term<'\x29'>>;
+	static constexpr auto rule(d, ctll::term<'='>) -> ctll::push<ctll::anything, reset_capture, start_lookahead_positive, content_in_capture, look_finish, ctll::term<'\x29'>>;
+
+	static constexpr auto rule(e, ctll::term<'d'>) -> ctll::push<ctll::anything, class_digit>;
+	static constexpr auto rule(e, ctll::term<'h'>) -> ctll::push<ctll::anything, class_horizontal_space>;
+	static constexpr auto rule(e, ctll::term<'H'>) -> ctll::push<ctll::anything, class_non_horizontal_space>;
+	static constexpr auto rule(e, ctll::term<'V'>) -> ctll::push<ctll::anything, class_non_vertical_space>;
+	static constexpr auto rule(e, ctll::term<'D'>) -> ctll::push<ctll::anything, class_nondigit>;
+	static constexpr auto rule(e, ctll::term<'N'>) -> ctll::push<ctll::anything, class_nonnewline>;
+	static constexpr auto rule(e, ctll::term<'S'>) -> ctll::push<ctll::anything, class_nonspace>;
+	static constexpr auto rule(e, ctll::term<'W'>) -> ctll::push<ctll::anything, class_nonword>;
+	static constexpr auto rule(e, ctll::term<'s'>) -> ctll::push<ctll::anything, class_space>;
+	static constexpr auto rule(e, ctll::term<'v'>) -> ctll::push<ctll::anything, class_vertical_space>;
+	static constexpr auto rule(e, ctll::term<'w'>) -> ctll::push<ctll::anything, class_word>;
+	static constexpr auto rule(e, ctll::term<'p'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property>;
+	static constexpr auto rule(e, ctll::term<'P'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property_negative>;
+	static constexpr auto rule(e, ctll::term<'u'>) -> ctll::push<ctll::anything, k, range>;
+	static constexpr auto rule(e, ctll::term<'x'>) -> ctll::push<ctll::anything, l, range>;
+	static constexpr auto rule(e, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character, range>;
+	static constexpr auto rule(e, ctll::term<'a'>) -> ctll::push<ctll::anything, push_character_alarm, range>;
+	static constexpr auto rule(e, ctll::term<'e'>) -> ctll::push<ctll::anything, push_character_escape, range>;
+	static constexpr auto rule(e, ctll::term<'f'>) -> ctll::push<ctll::anything, push_character_formfeed, range>;
+	static constexpr auto rule(e, ctll::term<'n'>) -> ctll::push<ctll::anything, push_character_newline, range>;
+	static constexpr auto rule(e, ctll::term<'0'>) -> ctll::push<ctll::anything, push_character_null, range>;
+	static constexpr auto rule(e, ctll::term<'r'>) -> ctll::push<ctll::anything, push_character_return_carriage, range>;
+	static constexpr auto rule(e, ctll::term<'t'>) -> ctll::push<ctll::anything, push_character_tab, range>;
+
+	static constexpr auto rule(f, ctll::term<'d'>) -> ctll::push<ctll::anything, class_digit>;
+	static constexpr auto rule(f, ctll::term<'h'>) -> ctll::push<ctll::anything, class_horizontal_space>;
+	static constexpr auto rule(f, ctll::term<'H'>) -> ctll::push<ctll::anything, class_non_horizontal_space>;
+	static constexpr auto rule(f, ctll::term<'V'>) -> ctll::push<ctll::anything, class_non_vertical_space>;
+	static constexpr auto rule(f, ctll::term<'D'>) -> ctll::push<ctll::anything, class_nondigit>;
+	static constexpr auto rule(f, ctll::term<'N'>) -> ctll::push<ctll::anything, class_nonnewline>;
+	static constexpr auto rule(f, ctll::term<'S'>) -> ctll::push<ctll::anything, class_nonspace>;
+	static constexpr auto rule(f, ctll::term<'W'>) -> ctll::push<ctll::anything, class_nonword>;
+	static constexpr auto rule(f, ctll::term<'s'>) -> ctll::push<ctll::anything, class_space>;
+	static constexpr auto rule(f, ctll::term<'v'>) -> ctll::push<ctll::anything, class_vertical_space>;
+	static constexpr auto rule(f, ctll::term<'w'>) -> ctll::push<ctll::anything, class_word>;
+	static constexpr auto rule(f, ctll::term<'p'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property>;
+	static constexpr auto rule(f, ctll::term<'P'>) -> ctll::push<ctll::anything, ctll::term<'\x7B'>, property_name, ctll::term<'\x7D'>, make_property_negative>;
+	static constexpr auto rule(f, ctll::term<'u'>) -> ctll::push<ctll::anything, k, range>;
+	static constexpr auto rule(f, ctll::term<'x'>) -> ctll::push<ctll::anything, l, range>;
+	static constexpr auto rule(f, ctll::set<'$','\x28','\x29','*','+','-','.','/','<','>','?','[','\\','\"',']','^','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character, range>;
+	static constexpr auto rule(f, ctll::term<'a'>) -> ctll::push<ctll::anything, push_character_alarm, range>;
+	static constexpr auto rule(f, ctll::term<'e'>) -> ctll::push<ctll::anything, push_character_escape, range>;
+	static constexpr auto rule(f, ctll::term<'f'>) -> ctll::push<ctll::anything, push_character_formfeed, range>;
+	static constexpr auto rule(f, ctll::term<'n'>) -> ctll::push<ctll::anything, push_character_newline, range>;
+	static constexpr auto rule(f, ctll::term<'0'>) -> ctll::push<ctll::anything, push_character_null, range>;
+	static constexpr auto rule(f, ctll::term<'r'>) -> ctll::push<ctll::anything, push_character_return_carriage, range>;
+	static constexpr auto rule(f, ctll::term<'t'>) -> ctll::push<ctll::anything, push_character_tab, range>;
+
+	static constexpr auto rule(g, ctll::term<'s'>) -> ctll::push<ctll::anything, ctll::term<'c'>, ctll::term<'i'>, ctll::term<'i'>, class_named_ascii>;
+	static constexpr auto rule(g, ctll::term<'l'>) -> ctll::push<ctll::anything, p>;
+
+	static constexpr auto rule(h, ctll::term<'r'>) -> ctll::push<ctll::anything, ctll::term<'i'>, ctll::term<'n'>, ctll::term<'t'>, class_named_print>;
+	static constexpr auto rule(h, ctll::term<'u'>) -> ctll::push<ctll::anything, ctll::term<'n'>, 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<ctll::anything, push_hexdec, hexdec_repeat>;
+
+	static constexpr auto rule(i, ctll::term<'^'>) -> ctll::push<ctll::anything, class_named_name, negate_class_named, ctll::term<':'>, ctll::term<']'>>;
+	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<']'>>;
+	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<']'>>;
+	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<']'>>;
+	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<']'>>;
+	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<']'>>;
+	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<']'>>;
+	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<']'>>;
+	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<']'>>;
+	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<']'>>;
+	static constexpr auto rule(i, ctll::term<'a'>) -> ctll::push<ctll::anything, g, ctll::term<':'>, ctll::term<']'>>;
+	static constexpr auto rule(i, ctll::term<'p'>) -> ctll::push<ctll::anything, h, ctll::term<':'>, ctll::term<']'>>;
+
+	static constexpr auto rule(j, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash_range, make_range>;
+	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>;
+	static constexpr auto rule(j, _others) -> ctll::push<ctll::anything, push_character, make_range>;
+	static constexpr auto rule(j, ctll::set<'-','[',']'>) -> ctll::reject;
+
+	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>;
+	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>;
+
+	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>;
+	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>;
+
+	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>;
+	static constexpr auto rule(m, ctll::term<'-'>) -> ctll::push<ctll::anything, number, ctll::term<'\x7D'>, 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<ctll::anything, push_name, block_name2, ctll::term<'\x7D'>, 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<ctll::anything, make_lazy>;
+	static constexpr auto rule(mod, ctll::term<'+'>) -> ctll::push<ctll::anything, make_possessive>;
+	static constexpr auto rule(mod, ctll::set<'*','\x7B','\x7D'>) -> ctll::reject;
+
+	static constexpr auto rule(mode_switch2, ctll::term<'i'>) -> ctll::push<ctll::anything, mode_case_insensitive, mode_switch2>;
+	static constexpr auto rule(mode_switch2, ctll::term<'c'>) -> ctll::push<ctll::anything, mode_case_sensitive, mode_switch2>;
+	static constexpr auto rule(mode_switch2, ctll::term<'m'>) -> ctll::push<ctll::anything, mode_multiline, mode_switch2>;
+	static constexpr auto rule(mode_switch2, ctll::term<'s'>) -> ctll::push<ctll::anything, mode_singleline, mode_switch2>;
+	static constexpr auto rule(mode_switch2, ctll::term<'\x29'>) -> ctll::push<ctll::anything>;
+
+	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>;
+	static constexpr auto rule(n, ctll::term<'\x7D'>) -> ctll::push<repeat_at_least, ctll::anything, mod>;
+
+	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<ctll::anything, push_number, number2>;
+
+	static constexpr auto rule(number, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push<ctll::anything, create_number, number2>;
+
+	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'>>;
+	static constexpr auto rule(o, ctll::term<'!'>) -> ctll::push<ctll::anything, reset_capture, start_lookbehind_negative, content_in_capture, look_finish, ctll::term<'\x29'>>;
+	static constexpr auto rule(o, ctll::term<'='>) -> ctll::push<ctll::anything, reset_capture, start_lookbehind_positive, content_in_capture, look_finish, ctll::term<'\x29'>>;
+
+	static constexpr auto rule(opt_content, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2>;
+	static constexpr auto rule(opt_content, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2>;
+	static constexpr auto rule(opt_content, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2>;
+	static constexpr auto rule(opt_content, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2>;
+	static constexpr auto rule(opt_content, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2>;
+	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>;
+	static constexpr auto rule(opt_content, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
+	static constexpr auto rule(opt_content, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2>;
+	static constexpr auto rule(opt_content, ctll::epsilon) -> ctll::push<push_empty>;
+	static constexpr auto rule(opt_content, ctll::set<'\x29','*','+','?','\x7B','|','\x7D'>) -> ctll::reject;
+
+	static constexpr auto rule(p, ctll::term<'p'>) -> ctll::push<ctll::anything, ctll::term<'h'>, ctll::term<'a'>, class_named_alpha>;
+	static constexpr auto rule(p, ctll::term<'n'>) -> ctll::push<ctll::anything, ctll::term<'u'>, 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<ctll::anything, property_value>;
+	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>;
+
+	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>;
+
+	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<ctll::anything, push_property_value, property_value2>;
+
+	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>;
+
+	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<ctll::anything, j>;
+
+	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<ctll::anything, make_optional, mod>;
+	static constexpr auto rule(repeat, ctll::term<'\x7B'>) -> ctll::push<ctll::anything, number, b>;
+	static constexpr auto rule(repeat, ctll::term<'+'>) -> ctll::push<ctll::anything, repeat_plus, mod>;
+	static constexpr auto rule(repeat, ctll::term<'*'>) -> ctll::push<ctll::anything, repeat_star, mod>;
+	static constexpr auto rule(repeat, ctll::term<'\x7D'>) -> ctll::reject;
+
+	static constexpr auto rule(set2a, ctll::term<'['>) -> ctll::push<ctll::anything, ctll::term<':'>, i, range, set_start, set2b>;
+	static constexpr auto rule(set2a, ctll::term<'\\'>) -> ctll::push<ctll::anything, f, set_start, set2b>;
+	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>;
+	static constexpr auto rule(set2a, _others) -> ctll::push<ctll::anything, push_character, range, set_start, set2b>;
+	static constexpr auto rule(set2a, ctll::term<']'>) -> ctll::push<set_empty>;
+	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<ctll::anything, ctll::term<':'>, i, range, set_combine, set2b>;
+	static constexpr auto rule(set2b, ctll::term<'\\'>) -> ctll::push<ctll::anything, f, set_combine, set2b>;
+	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>;
+	static constexpr auto rule(set2b, _others) -> ctll::push<ctll::anything, push_character, range, set_combine, set2b>;
+	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<ctll::anything, backslash, repeat, string2, make_sequence>;
+	static constexpr auto rule(string2, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, make_sequence>;
+	static constexpr auto rule(string2, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, make_sequence>;
+	static constexpr auto rule(string2, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, make_sequence>;
+	static constexpr auto rule(string2, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, make_sequence>;
+	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>;
+	static constexpr auto rule(string2, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, make_sequence>;
+	static constexpr auto rule(string2, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, make_sequence>;
+	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 <typename... Flags> 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 <typename... Args> constexpr CTRE_FORCE_INLINE flags(ctll::list<Args...>) 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 <cstdint>
+#endif
+
+namespace ctre {
+	
+// sfinae check for types here
+
+template <typename T> class MatchesCharacter {
+	template <typename Y, typename CharT> static auto test(CharT c) -> decltype(Y::match_char(c, std::declval<const flags &>()), std::true_type());
+	template <typename> static auto test(...) -> std::false_type;
+public:
+	template <typename CharT> static inline constexpr bool value = decltype(test<T>(std::declval<CharT>()))();
+};
+
+template <typename T> constexpr CTRE_FORCE_INLINE bool is_ascii_alpha(T v) {
+	return ((v >= static_cast<T>('a') && v <= static_cast<T>('z')) || (v >= static_cast<T>('A') && v <= static_cast<T>('Z')));
+}
+
+template <typename T> constexpr CTRE_FORCE_INLINE bool is_ascii_alpha_lowercase(T v) {
+	return (v >= static_cast<T>('a')) && (v <= static_cast<T>('z'));
+}
+
+template <typename T> constexpr CTRE_FORCE_INLINE bool is_ascii_alpha_uppercase(T v) {
+	return (v >= static_cast<T>('A')) && v <= (static_cast<T>('Z'));
+}
+
+template <auto V> struct character {
+	template <typename CharT> 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<decltype(V)>(0x20))) {
+					return true;//
+				}
+			}	
+		}
+		return static_cast<std::make_unsigned_t<CharT>>(value) == V;
+	}
+};
+
+template <typename... Content> struct negative_set {
+	template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char([[maybe_unused]] CharT value, const flags & f) noexcept {
+		return !(Content::match_char(value, f) || ... || false);
+	}
+};
+
+template <typename... Content> struct set {
+	template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char([[maybe_unused]]  CharT value, const flags & f) noexcept {
+		return (Content::match_char(value, f) || ... || false);
+	}
+};
+
+template <auto... Cs> struct enumeration : set<character<Cs>...> { };
+
+template <typename... Content> struct negate {
+	template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char([[maybe_unused]] CharT value, const flags & f) noexcept {
+		return !(Content::match_char(value, f) || ... || false);
+	}
+};
+
+template <auto A, auto B> struct char_range {
+	template <typename CharT> 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<decltype(A)>(0x20)) && value <= (B ^ static_cast<decltype(B)>(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<decltype(A)>(0x20)) && value <= (B ^ static_cast<decltype(B)>(0x20))) {
+					return true;//
+				}
+			}	
+		}
+		return (static_cast<std::make_unsigned_t<CharT>>(value) >= A) && (static_cast<std::make_unsigned_t<CharT>>(value) <= B);
+	}
+};
+using word_chars = set<char_range<'A','Z'>, 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<'a','z'>, char_range<'0','9'> >;
+
+using alpha_chars = set<char_range<'A','Z'>, char_range<'a','z'> >;
+
+using xdigit_chars = set<char_range<'A','F'>, 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 <cstdint>
+#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 <size_t Id> struct numeric_mark { };
+
+struct any { };
+
+// actual AST of regexp
+template <auto... Str> struct string { };
+template <typename... Opts> struct select { };
+template <typename... Content> struct sequence { };
+struct empty { };
+
+template <size_t a, size_t b, typename... Content> struct repeat { };
+template <typename... Content> using plus = repeat<1,0,Content...>;
+template <typename... Content> using star = repeat<0,0,Content...>;
+
+template <size_t a, size_t b, typename... Content> struct lazy_repeat { };
+template <typename... Content> using lazy_plus = lazy_repeat<1,0,Content...>;
+template <typename... Content> using lazy_star = lazy_repeat<0,0,Content...>;
+
+template <size_t a, size_t b, typename... Content> struct possessive_repeat { };
+template <typename... Content> using possessive_plus = possessive_repeat<1,0,Content...>;
+template <typename... Content> using possessive_star = possessive_repeat<0,0,Content...>;
+
+template <typename... Content> using optional = repeat<0,1,Content...>;
+template <typename... Content> using lazy_optional = lazy_repeat<0,1,Content...>;
+template <typename... Content> using possessive_optional = possessive_repeat<0,1,Content...>;
+
+template <size_t Index, typename... Content> struct capture { };
+
+template <size_t Index, typename Name, typename... Content> struct capture_with_name { };
+
+template <size_t Index> struct back_reference { };
+template <typename Name> struct back_reference_with_name { };
+
+template <typename Type> struct look_start { };
+
+template <typename... Content> struct lookahead_positive { };
+template <typename... Content> struct lookahead_negative { };
+
+template <typename... Content> struct lookbehind_positive { };
+template <typename... Content> struct lookbehind_negative { };
+
+struct atomic_start { };
+
+template <typename... Content> struct atomic_group { };
+
+template <typename... Content> struct boundary { };
+template <typename... Content> struct not_boundary { };
+
+using word_boundary = boundary<word_chars>;
+using not_word_boundary = not_boundary<word_chars>;
+
+struct assert_subject_begin { };
+struct assert_subject_end { };
+struct assert_subject_end_line{ };
+struct assert_line_begin { };
+struct assert_line_end { };
+
+template <typename> 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 <string_view>
+#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<script>
+    constexpr bool cp_script_is(char32_t);
+    template<property>
+    constexpr bool cp_property_is(char32_t);
+    template<category>
+    constexpr bool cp_category_is(char32_t);
+
+    namespace detail
+    {
+        enum class binary_prop;
+        constexpr int propnamecomp(std::string_view sa, std::string_view sb);
+        constexpr binary_prop binary_prop_from_string(std::string_view s);
+
+        template<binary_prop p>
+        constexpr bool get_binary_prop(char32_t) = delete;
+
+        constexpr script   script_from_string(std::string_view s);
+        constexpr block    block_from_string(std::string_view s);
+        constexpr version  age_from_string(std::string_view a);
+        constexpr category category_from_string(std::string_view a);
+
+        constexpr bool is_unassigned(category cat);
+        constexpr bool is_unknown(script s);
+        constexpr bool is_unknown(block b);
+        constexpr bool is_unassigned(version v);
+        constexpr bool is_unknown(binary_prop s);
+    }
+}
+
+#endif
+
+namespace ctre {
+
+// properties name & value
+
+template <auto... Str> struct property_name { };
+template <auto... Str> struct property_value { };
+
+template <size_t Sz> constexpr std::string_view get_string_view(const char (& arr)[Sz]) noexcept {
+	return std::string_view(arr, Sz);
+}
+
+// basic support for binary and type-value properties
+
+template <typename T, T Type> struct binary_property;
+template <typename T, T Type, auto Value> struct property;
+
+template <auto Type> using make_binary_property = binary_property<std::remove_const_t<decltype(Type)>, Type>;
+template <auto Type, auto Value> using make_property = property<std::remove_const_t<decltype(Type)>, Type, Value>;
+
+// unicode TS#18 level 1.2 general_category
+template <uni::detail::binary_prop Property> struct binary_property<uni::detail::binary_prop, Property> {
+	template <typename CharT> inline static constexpr bool match_char(CharT c, const flags &) noexcept {
+		return uni::detail::get_binary_prop<Property>(static_cast<char32_t>(static_cast<std::make_unsigned_t<CharT>>(c)));
+	}
+};
+
+// unicode TS#18 level 1.2.2
+
+enum class property_type {
+	script, script_extension, age, block, unknown
+};
+
+// unicode TS#18 level 1.2.2
+
+template <uni::script Script> struct binary_property<uni::script, Script> {
+	template <typename CharT> inline static constexpr bool match_char(CharT c, const flags &) noexcept {
+		return uni::cp_script(c) == Script;
+	}
+};
+
+template <uni::script Script> struct property<property_type, property_type::script_extension, Script> {
+	template <typename CharT> inline static constexpr bool match_char(CharT c, const flags &) noexcept {
+		for (uni::script sc: uni::cp_script_extensions(c)) {
+			if (sc == Script) return true;
+		}
+		return false;
+	}
+};
+
+template <uni::version Age> struct binary_property<uni::version, Age> {
+	template <typename CharT> inline static constexpr bool match_char(CharT c, const flags &) noexcept {
+		return uni::cp_age(c) <= Age;
+	}
+};
+
+template <uni::block Block> struct binary_property<uni::block, Block> {
+	template <typename CharT> inline static constexpr bool match_char(CharT c, const flags &) noexcept {
+		return uni::cp_block(c) == Block;
+	}
+};
+
+// nonbinary properties
+
+template <typename = void> // Make it always a template as propnamecomp isn't defined yet
+constexpr property_type property_type_from_name(std::string_view str) noexcept {
+	using namespace std::string_view_literals;
+	if (uni::detail::propnamecomp(str, "script"sv) == 0 || uni::detail::propnamecomp(str, "sc"sv) == 0) {
+		return property_type::script;
+	} else if (uni::detail::propnamecomp(str, "script_extension"sv) == 0 || uni::detail::propnamecomp(str, "scx"sv) == 0) {
+		return property_type::script_extension;
+	} else if (uni::detail::propnamecomp(str, "age"sv) == 0) {
+		return property_type::age;
+	} else if (uni::detail::propnamecomp(str, "block"sv) == 0) {
+		return property_type::block;
+	} else {
+		return property_type::unknown;
+	}
+}
+
+template <property_type Property> struct property_type_builder {
+	template <auto... Value> static constexpr auto get() {
+		return ctll::reject{};
+	}
+};
+
+template <auto... Name> struct property_builder {
+	static constexpr char name[sizeof...(Name)]{static_cast<char>(Name)...};
+	static constexpr property_type type = property_type_from_name(get_string_view(name));
+
+	using helper = property_type_builder<type>;
+
+	template <auto... Value> static constexpr auto get() {
+		return helper::template get<Value...>();
+	}
+};
+
+// unicode TS#18 level 1.2.2 script support
+
+template <> struct property_type_builder<property_type::script> {
+	template <auto... Value> static constexpr auto get() {
+		constexpr char value[sizeof...(Value)]{static_cast<char>(Value)...};
+		constexpr auto sc = uni::detail::script_from_string(get_string_view(value));
+		if constexpr (uni::detail::is_unknown(sc)) {
+			return ctll::reject{};
+		} else {
+			return make_binary_property<sc>();
+		}
+	}
+};
+
+template <> struct property_type_builder<property_type::script_extension> {
+	template <auto... Value> static constexpr auto get() {
+		constexpr char value[sizeof...(Value)]{static_cast<char>(Value)...};
+		constexpr auto sc = uni::detail::script_from_string(get_string_view(value));
+		if constexpr (uni::detail::is_unknown(sc)) {
+			return ctll::reject{};
+		} else {
+			return make_property<property_type::script_extension, sc>();
+		}
+	}
+};
+
+template <> struct property_type_builder<property_type::age> {
+	template <auto... Value> static constexpr auto get() {
+		constexpr char value[sizeof...(Value)]{static_cast<char>(Value)...};
+		constexpr auto age = uni::detail::age_from_string(get_string_view(value));
+		if constexpr (uni::detail::is_unassigned(age)) {
+			return ctll::reject{};
+		} else {
+			return make_binary_property<age>();
+		}
+	}
+};
+
+template <> struct property_type_builder<property_type::block> {
+	template <auto... Value> static constexpr auto get() {
+		constexpr char value[sizeof...(Value)]{static_cast<char>(Value)...};
+		constexpr auto block = uni::detail::block_from_string(get_string_view(value));
+		if constexpr (uni::detail::is_unknown(block)) {
+			return ctll::reject{};
+		} else {
+			return make_binary_property<block>();
+		}
+	}
+};
+
+}
+
+#endif
+
+namespace ctre {
+
+// helper functions
+template <size_t Index, typename... Content> auto convert_to_capture(ctll::list<Content...>) -> capture<Index, Content...>;
+template <size_t Index, typename Name, typename... Content> auto convert_to_named_capture(ctll::list<Content...>) -> capture_with_name<Index, Name, Content...>;
+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...>;
+template <template <typename...> typename ListType, typename... Content> auto convert_to_basic_list(ctll::list<Content...>) -> ListType<Content...>;
+
+template <auto V> struct rotate_value {
+	template <auto... Vs> friend constexpr auto operator+(string<Vs...>, rotate_value<V>) noexcept -> string<V, Vs...> { return {}; }
+};
+
+struct rotate_for_lookbehind {
+
+// from atoms_characters.hpp
+template <auto V> static auto rotate(character<V>) -> character<V>;
+template <typename... Content> static auto rotate(negative_set<Content...>) -> negative_set<Content...>;
+template <typename... Content> static auto rotate(set<Content...>) -> set<Content...>;
+template <auto... Cs> static auto rotate(enumeration<Cs...>) -> enumeration<Cs...>;
+template <typename... Content> static auto rotate(negate<Content...>) -> negate<Content...>;
+template <auto A, auto B> static auto rotate(char_range<A,B>) -> char_range<A,B>;
+
+// from atoms_unicode.hpp
+template <auto... Str> static auto rotate(property_name<Str...>) -> property_name<Str...>;
+template <auto... Str> static auto rotate(property_value<Str...>) -> property_value<Str...>;
+template <typename T, T Type> static auto rotate(binary_property<T, Type>) -> binary_property<T, Type>;
+template <typename T, T Type, auto Value> static auto rotate(property<T, Type, Value>) -> property<T, Type, Value>;
+
+// from atoms.hpp
+static auto rotate(accept) -> accept;
+static auto rotate(reject) -> reject;
+static auto rotate(start_mark) -> start_mark;
+static auto rotate(end_mark) -> end_mark;
+static auto rotate(end_cycle_mark) -> end_cycle_mark;
+static auto rotate(end_lookahead_mark) -> end_lookahead_mark;
+static auto rotate(end_lookbehind_mark) -> end_lookbehind_mark;
+template <size_t Id> static auto rotate(numeric_mark<Id>) -> numeric_mark<Id>;
+static auto rotate(any) -> any;
+
+static auto rotate(empty) -> empty;
+
+// select rotates only insides of selection, not select itself
+template <typename... Content> static auto rotate(select<Content...>) {
+  return select<decltype(rotate(Content{}))...>{};
+}
+
+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{}))...>{})));
+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{}))...>{})));
+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{}))...>{})));
+
+template <size_t Index, typename... Content> static auto rotate(capture<Index, Content...>) {
+	return ctre::convert_to_capture<Index>(ctll::rotate(ctll::list<decltype(rotate(Content{}))...>{}));
+}
+
+template <size_t Index, typename Name, typename... Content> static auto rotate(capture_with_name<Index, Name, Content...>) {
+	return ctre::convert_to_named_capture<Index, Name>(ctll::rotate(ctll::list<decltype(rotate(Content{}))...>{}));
+}
+
+template <size_t Index> static auto rotate(back_reference<Index>) -> back_reference<Index>;
+template <typename Name> static auto rotate(back_reference_with_name<Name>) -> back_reference_with_name<Name>;
+
+template <typename... Content> static auto rotate(look_start<Content...>) -> look_start<Content...>;
+
+template <auto... Str> static auto rotate(string<Str...>) -> decltype((string<>{} + ... + rotate_value<Str>{}));
+
+template <typename... Content> static auto rotate(sequence<Content...>) {
+	return ctre::convert_to_basic_list<sequence>(ctll::rotate(ctll::list<decltype(rotate(Content{}))...>{}));
+}
+
+// we don't rotate lookaheads
+template <typename... Content> static auto rotate(lookahead_positive<Content...>) -> lookahead_positive<Content...>;
+template <typename... Content> static auto rotate(lookahead_negative<Content...>) -> lookahead_negative<Content...>;
+template <typename... Content> static auto rotate(lookbehind_positive<Content...>) -> lookbehind_positive<Content...>;
+template <typename... Content> static auto rotate(lookbehind_negative<Content...>) -> lookbehind_negative<Content...>;
+
+static auto rotate(atomic_start) -> atomic_start;
+
+template <typename... Content> static auto rotate(atomic_group<Content...>) {
+	return ctre::convert_to_basic_list<atomic_group>(ctll::rotate(ctll::list<decltype(rotate(Content{}))...>{}));
+}
+
+template <typename... Content> static auto rotate(boundary<Content...>) -> boundary<Content...>;
+template <typename... Content> static auto rotate(not_boundary<Content...>) -> not_boundary<Content...>;
+
+static auto rotate(assert_subject_begin) -> assert_subject_begin;
+static auto rotate(assert_subject_end) -> assert_subject_end;
+static auto rotate(assert_subject_end_line) -> assert_subject_end_line;
+static auto rotate(assert_line_begin) -> assert_line_begin;
+static auto rotate(assert_line_end) -> assert_line_end;
+
+};
+
+}
+
+#endif
+
+#ifndef CTRE__ID__HPP
+#define CTRE__ID__HPP
+
+#ifndef CTRE_IN_A_MODULE
+#include <type_traits>
+#endif
+
+namespace ctre {
+	
+template <auto... Name> struct id {
+	static constexpr auto name = ctll::fixed_string<sizeof...(Name)>{{Name...}};
+	
+	friend constexpr auto operator==(id<Name...>, id<Name...>) noexcept -> std::true_type { return {}; }
+
+	template <auto... Other> friend constexpr auto operator==(id<Name...>, id<Other...>) noexcept -> std::false_type { return {}; }
+	
+	template <typename T> friend constexpr auto operator==(id<Name...>, T) noexcept -> std::false_type { return {}; }
+
+	template <typename T> friend constexpr auto operator==(T, id<Name...>) noexcept -> std::false_type { return {}; }
+};
+
+}
+
+#endif
+
+#ifndef CTRE_IN_A_MODULE
+#include <cstdint>
+#include <limits>
+#endif
+
+namespace ctre {
+	
+template <size_t Counter> struct pcre_parameters {
+	static constexpr size_t current_counter = Counter;
+};
+	
+template <typename Stack = ctll::list<>, typename Parameters = pcre_parameters<0>, typename Mode = ctll::list<>> struct pcre_context {
+	using stack_type = Stack;
+	using parameters_type = Parameters;
+	using mode_list = Mode;
+	static constexpr inline auto stack = stack_type();
+	static constexpr inline auto parameters = parameters_type();
+	static constexpr inline auto mode = mode_list();
+	constexpr pcre_context() noexcept { }
+	constexpr pcre_context(Stack, Parameters) noexcept { }
+	constexpr pcre_context(Stack, Parameters, Mode) noexcept { }
+};
+
+template <typename... Content, typename Parameters> pcre_context(ctll::list<Content...>, Parameters) -> pcre_context<ctll::list<Content...>, Parameters>;
+	
+template <size_t Value> struct number { };
+
+template <size_t Id> struct capture_id { };
+	
+struct pcre_actions {
+// i know it's ugly, but it's more readable
+#ifndef CTRE__ACTIONS__ASSERTS__HPP
+#define CTRE__ACTIONS__ASSERTS__HPP
+
+// push_assert_begin
+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) {
+	return pcre_context{ctll::push_front(assert_line_begin(), subject.stack), subject.parameters};
+}
+
+// push_assert_end
+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) {
+	return pcre_context{ctll::push_front(assert_line_end(), subject.stack), subject.parameters};
+}
+
+// push_assert_begin
+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) {
+	return pcre_context{ctll::push_front(assert_subject_begin(), subject.stack), subject.parameters};
+}
+
+// push_assert_subject_end
+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) {
+	return pcre_context{ctll::push_front(assert_subject_end(), subject.stack), subject.parameters};
+}
+
+// push_assert_subject_end_with_lineend
+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) {
+	return pcre_context{ctll::push_front(assert_subject_end_line(), subject.stack), subject.parameters};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__ATOMIC_GROUP__HPP
+#define CTRE__ACTIONS__ATOMIC_GROUP__HPP
+
+// atomic start
+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>>) {
+	return pcre_context{ctll::list<atomic_start, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// atomic
+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>>) {
+	return pcre_context{ctll::list<atomic_group<Atomic>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// atomic sequence
+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>>) {
+	return pcre_context{ctll::list<atomic_group<Atomic...>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__BACKREFERENCE__HPP
+#define CTRE__ACTIONS__BACKREFERENCE__HPP
+
+// backreference with name
+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>>) {	
+	return pcre_context{ctll::push_front(back_reference_with_name<id<Str...>>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
+}
+
+// with just a number
+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>>) {
+	// if we are looking outside of existing list of Ids ... reject input during parsing
+	if constexpr (Counter < Id) {
+		return ctll::reject{};
+	} else {
+		return pcre_context{ctll::push_front(back_reference<Id>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
+	}
+}
+
+// relative backreference
+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>>) {	
+	// if we are looking outside of existing list of Ids ... reject input during parsing
+	if constexpr (Counter < Id) {
+		return ctll::reject{};
+	} else {
+		constexpr size_t absolute_id = (Counter + 1) - Id;
+		return pcre_context{ctll::push_front(back_reference<absolute_id>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
+	}
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__BOUNDARIES__HPP
+#define CTRE__ACTIONS__BOUNDARIES__HPP
+
+// push_word_boundary
+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) {
+	return pcre_context{ctll::push_front(boundary<word_chars>(), subject.stack), subject.parameters};
+}
+
+// push_not_word_boundary
+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) {
+	return pcre_context{ctll::push_front(boundary<negative_set<word_chars>>(), subject.stack), subject.parameters};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__CAPTURE__HPP
+#define CTRE__ACTIONS__CAPTURE__HPP
+
+// prepare_capture
+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>>) {
+	return pcre_context{ctll::push_front(capture_id<Counter+1>(), ctll::list<Ts...>()), pcre_parameters<Counter+1>()};
+}
+
+// reset_capture
+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>>) {
+	return pcre_context{ctll::list<Ts...>(), pcre_parameters<Counter-1>()};
+}
+
+// capture
+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>>) {
+	return pcre_context{ctll::push_front(capture<Id, A>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
+}
+// capture (sequence)
+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>>) {
+	return pcre_context{ctll::push_front(capture<Id, Content...>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
+}
+// push_name
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_name, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(id<V>(), subject.stack), subject.parameters};
+}
+// push_name (concat)
+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) {
+	return pcre_context{ctll::push_front(id<Str..., V>(), ctll::list<Ts...>()), subject.parameters};
+}
+// capture with name
+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>>) {
+	return pcre_context{ctll::push_front(capture_with_name<Id, id<Str...>, A>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
+}
+// capture with name (sequence)
+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>>) {
+	return pcre_context{ctll::push_front(capture_with_name<Id, id<Str...>, Content...>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__CHARACTERS__HPP
+#define CTRE__ACTIONS__CHARACTERS__HPP
+
+// push character
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_character, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(character<V>(), subject.stack), subject.parameters};
+}
+// push_any_character
+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) {
+	return pcre_context{ctll::push_front(any(), subject.stack), subject.parameters};
+}
+// character_alarm
+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) {
+	return pcre_context{ctll::push_front(character<'\x07'>(), subject.stack), subject.parameters};
+}
+// character_escape
+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) {
+	return pcre_context{ctll::push_front(character<'\x14'>(), subject.stack), subject.parameters};
+}
+// character_formfeed
+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) {
+	return pcre_context{ctll::push_front(character<'\x0C'>(), subject.stack), subject.parameters};
+}
+// push_character_newline
+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) {
+	return pcre_context{ctll::push_front(character<'\x0A'>(), subject.stack), subject.parameters};
+}
+// push_character_null
+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) {
+	return pcre_context{ctll::push_front(character<'\0'>(), subject.stack), subject.parameters};
+}
+// push_character_return_carriage
+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) {
+	return pcre_context{ctll::push_front(character<'\x0D'>(), subject.stack), subject.parameters};
+}
+// push_character_tab
+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) {
+	return pcre_context{ctll::push_front(character<'\x09'>(), subject.stack), subject.parameters};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__CLASS__HPP
+#define CTRE__ACTIONS__CLASS__HPP
+
+// class_digit
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_digit, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(ctre::set<ctre::digit_chars>(), subject.stack), subject.parameters};
+}
+// class_non_digit
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_nondigit, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(ctre::negative_set<ctre::digit_chars>(), subject.stack), subject.parameters};
+}
+// class_space
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_space, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(ctre::set<ctre::space_chars>(), subject.stack), subject.parameters};
+}
+// class_nonspace
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_nonspace, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(ctre::negative_set<ctre::space_chars>(), subject.stack), subject.parameters};
+}
+
+// class_horizontal_space
+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) {
+	return pcre_context{ctll::push_front(ctre::set<ctre::horizontal_space_chars>(), subject.stack), subject.parameters};
+}
+// class_horizontal_nonspace
+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) {
+	return pcre_context{ctll::push_front(ctre::negative_set<ctre::horizontal_space_chars>(), subject.stack), subject.parameters};
+}
+// class_vertical_space
+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) {
+	return pcre_context{ctll::push_front(ctre::set<ctre::vertical_space_chars>(), subject.stack), subject.parameters};
+}
+// class_vertical_nonspace
+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) {
+	return pcre_context{ctll::push_front(ctre::negative_set<ctre::vertical_space_chars>(), subject.stack), subject.parameters};
+}
+
+// class_word
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_word, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(ctre::set<ctre::word_chars>(), subject.stack), subject.parameters};
+}
+// class_nonword
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_nonword, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(ctre::negative_set<ctre::word_chars>(), subject.stack), subject.parameters};
+}
+// class_nonnewline
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::class_nonnewline, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(ctre::negative_set<character<'\n'>>(), subject.stack), subject.parameters};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__FUSION__HPP
+#define CTRE__ACTIONS__FUSION__HPP
+
+static constexpr size_t combine_max_repeat_length(size_t A, size_t B) {
+	if (A && B) return A+B;
+	else return 0;
+}
+
+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...>) {
+	return repeat<MinA + MinB, combine_max_repeat_length(MaxA, MaxB), Content...>();
+}
+
+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...>) {
+	return lazy_repeat<MinA + MinB, combine_max_repeat_length(MaxA, MaxB), Content...>();
+}
+
+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...>) {
+	[[maybe_unused]] constexpr bool first_is_unbounded = (MaxA == 0);
+	[[maybe_unused]] constexpr bool second_is_nonempty = (MinB > 0);
+	[[maybe_unused]] constexpr bool second_can_be_empty = (MinB == 0);
+
+	if constexpr (first_is_unbounded && second_is_nonempty) {
+		// will always reject, but I keep the content, so I have some amount of captures
+		return sequence<reject, Content...>();
+	} else if constexpr (first_is_unbounded) {
+		return possessive_repeat<MinA, MaxA, Content...>();
+	} else if constexpr (second_can_be_empty) {
+		return possessive_repeat<MinA, combine_max_repeat_length(MaxA, MaxB), Content...>();
+	} else {
+		return possessive_repeat<MaxA + MinB, combine_max_repeat_length(MaxA, MaxB), Content...>();
+	}
+}
+
+// concat repeat sequences
+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) {
+	return pcre_context{ctll::push_front(combine_repeat(repeat<MinA, MaxA, Content...>(), repeat<MinB, MaxB, Content...>()), ctll::list<Ts...>()), subject.parameters};
+}
+
+// concat lazy repeat sequences
+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) {
+	return pcre_context{ctll::push_front(combine_repeat(lazy_repeat<MinA, MaxA, Content...>(), lazy_repeat<MinB, MaxB, Content...>()), ctll::list<Ts...>()), subject.parameters};
+}
+
+// concat possessive repeat seqeunces
+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) {
+	return pcre_context{ctll::push_front(combine_repeat(possessive_repeat<MinA, MaxA, Content...>(), possessive_repeat<MinB, MaxB, Content...>()), ctll::list<Ts...>()), subject.parameters};
+}
+
+// concat repeat sequences into sequence
+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) {
+	using result = decltype(combine_repeat(repeat<MinB, MaxB, Content...>(), repeat<MinA, MaxA, Content...>()));
+	
+	return pcre_context{ctll::push_front(sequence<result,As...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// concat lazy repeat sequences into sequence
+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) {
+	using result = decltype(combine_repeat(lazy_repeat<MinB, MaxB, Content...>(), lazy_repeat<MinA, MaxA, Content...>()));
+	
+	return pcre_context{ctll::push_front(sequence<result,As...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// concat possessive repeat sequences into sequence
+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) {
+	using result = decltype(combine_repeat(possessive_repeat<MinB, MaxB, Content...>(), possessive_repeat<MinA, MaxA, Content...>()));
+	
+	return pcre_context{ctll::push_front(sequence<result,As...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__HEXDEC__HPP
+#define CTRE__ACTIONS__HEXDEC__HPP
+
+// hexdec character support (seed)
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::create_hexdec, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(number<0ull>(), subject.stack), subject.parameters};
+}
+// hexdec character support (push value)
+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) {
+	constexpr auto previous = N << 4ull;	
+	if constexpr (V >= 'a' && V <= 'f') {
+		return pcre_context{ctll::push_front(number<(previous + (V - 'a' + 10))>(), ctll::list<Ts...>()), subject.parameters};
+	} else if constexpr (V >= 'A' && V <= 'F') {
+		return pcre_context{ctll::push_front(number<(previous + (V - 'A' + 10))>(), ctll::list<Ts...>()), subject.parameters};
+	} else {
+		return pcre_context{ctll::push_front(number<(previous + (V - '0'))>(), ctll::list<Ts...>()), subject.parameters};
+	}
+}
+// hexdec character support (convert to character)
+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) {
+	constexpr size_t max_char = (std::numeric_limits<char>::max)();
+	if constexpr (N <= max_char) {
+		return pcre_context{ctll::push_front(character<char{N}>(), ctll::list<Ts...>()), subject.parameters};
+	} else {
+		return pcre_context{ctll::push_front(character<char32_t{N}>(), ctll::list<Ts...>()), subject.parameters};
+	} 
+}	
+
+#endif
+
+#ifndef CTRE__ACTIONS__LOOKAHEAD__HPP
+#define CTRE__ACTIONS__LOOKAHEAD__HPP
+
+// lookahead positive start
+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>>) {
+	return pcre_context{ctll::list<look_start<lookahead_positive<>>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// lookahead positive end
+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>>) {
+	return pcre_context{ctll::list<lookahead_positive<Look>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// lookahead positive end (sequence)
+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>>) {
+	return pcre_context{ctll::list<lookahead_positive<Look...>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// lookahead negative start
+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>>) {
+	return pcre_context{ctll::list<look_start<lookahead_negative<>>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// lookahead negative end
+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>>) {
+	return pcre_context{ctll::list<lookahead_negative<Look>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// lookahead negative end (sequence)
+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>>) {
+	return pcre_context{ctll::list<lookahead_negative<Look...>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// LOOKBEHIND
+
+// lookbehind positive start
+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>>) {
+	return pcre_context{ctll::list<look_start<lookbehind_positive<>>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// lookbehind positive end
+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>>) {
+	return pcre_context{ctll::list<lookbehind_positive<decltype(ctre::rotate_for_lookbehind::rotate(Look{}))>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// lookbehind positive end (sequence)
+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>>) {
+	using my_lookbehind = decltype(ctre::convert_to_basic_list<lookbehind_positive>(ctll::rotate(ctll::list<decltype(ctre::rotate_for_lookbehind::rotate(Look{}))...>{})));
+	return pcre_context{ctll::list<my_lookbehind, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// lookbehind negative start
+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>>) {
+	return pcre_context{ctll::list<look_start<lookbehind_negative<>>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// lookbehind negative end
+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>>) {
+	return pcre_context{ctll::list<lookbehind_negative<decltype(ctre::rotate_for_lookbehind::rotate(Look{}))>, Ts...>(), pcre_parameters<Counter>()};
+}
+
+// lookbehind negative end (sequence)
+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>>) {
+	using my_lookbehind = decltype(ctre::convert_to_basic_list<lookbehind_negative>(ctll::rotate(ctll::list<decltype(ctre::rotate_for_lookbehind::rotate(Look{}))...>{})));
+	return pcre_context{ctll::list<my_lookbehind, Ts...>(), pcre_parameters<Counter>()};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__NAMED_CLASS__HPP
+#define CTRE__ACTIONS__NAMED_CLASS__HPP
+
+// class_named_alnum
+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) {
+	return pcre_context{ctll::push_front(ctre::alphanum_chars(), subject.stack), subject.parameters};
+}
+// class_named_alpha
+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) {
+	return pcre_context{ctll::push_front(ctre::alpha_chars(), subject.stack), subject.parameters};
+}
+// class_named_digit
+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) {
+	return pcre_context{ctll::push_front(ctre::digit_chars(), subject.stack), subject.parameters};
+}
+// class_named_ascii
+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) {
+	return pcre_context{ctll::push_front(ctre::ascii_chars(), subject.stack), subject.parameters};
+}
+// class_named_blank
+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) {
+	return pcre_context{ctll::push_front(ctre::enumeration<' ','\t'>(), subject.stack), subject.parameters};
+}
+// class_named_cntrl
+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) {
+	return pcre_context{ctll::push_front(ctre::set<ctre::char_range<'\x00','\x1F'>, ctre::character<'\x7F'>>(), subject.stack), subject.parameters};
+}
+// class_named_graph
+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) {
+	return pcre_context{ctll::push_front(ctre::char_range<'\x21','\x7E'>(), subject.stack), subject.parameters};
+}
+// class_named_lower
+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) {
+	return pcre_context{ctll::push_front(ctre::char_range<'a','z'>(), subject.stack), subject.parameters};
+}
+// class_named_upper
+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) {
+	return pcre_context{ctll::push_front(ctre::char_range<'A','Z'>(), subject.stack), subject.parameters};
+}
+// class_named_print
+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) {
+	return pcre_context{ctll::push_front(ctre::char_range<'\x20','\x7E'>(), subject.stack), subject.parameters};
+}
+// class_named_space
+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) {
+	return pcre_context{ctll::push_front(space_chars(), subject.stack), subject.parameters};
+}
+// class_named_word
+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) {
+	return pcre_context{ctll::push_front(word_chars(), subject.stack), subject.parameters};
+}
+// class_named_punct
+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) {
+	return pcre_context{ctll::push_front(punct_chars(), subject.stack), subject.parameters};
+}
+// class_named_xdigit
+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) {
+	return pcre_context{ctll::push_front(xdigit_chars(), subject.stack), subject.parameters};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__OPTIONS__HPP
+#define CTRE__ACTIONS__OPTIONS__HPP
+
+// empty option for alternate
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::push_empty, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(empty(), subject.stack), subject.parameters};
+}
+
+// empty option for empty regex
+template <typename Parameters> static constexpr auto apply(pcre::push_empty, ctll::epsilon, pcre_context<ctll::list<>, Parameters> subject) {
+	return pcre_context{ctll::push_front(empty(), subject.stack), subject.parameters};
+}
+
+// make_alternate (A|B)
+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) {
+	return pcre_context{ctll::push_front(select<A,B>(), ctll::list<Ts...>()), subject.parameters};
+}
+// make_alternate (As..)|B => (As..|B)
+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) {
+	return pcre_context{ctll::push_front(select<A,Bs...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// make_optional
+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) {
+	return pcre_context{ctll::push_front(optional<A>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+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) {
+	return pcre_context{ctll::push_front(optional<Content...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// prevent from creating wrapped optionals
+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) {
+	return pcre_context{ctll::push_front(optional<A>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// in case inner optional is lazy, result should be lazy too
+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) {
+	return pcre_context{ctll::push_front(lazy_optional<A>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// make_lazy (optional)
+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) {
+	return pcre_context{ctll::push_front(lazy_optional<Subject...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// if you already got a lazy optional, make_lazy is no-op
+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) {
+	return pcre_context{ctll::push_front(lazy_optional<Subject...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__PROPERTIES__HPP
+#define CTRE__ACTIONS__PROPERTIES__HPP
+
+// push_property_name
+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) {
+	return pcre_context{ctll::push_front(property_name<V>(), subject.stack), subject.parameters};
+}
+// push_property_name (concat)
+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) {
+	return pcre_context{ctll::push_front(property_name<Str..., V>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// push_property_value
+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) {
+	return pcre_context{ctll::push_front(property_value<V>(), subject.stack), subject.parameters};
+}
+// push_property_value (concat)
+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) {
+	return pcre_context{ctll::push_front(property_value<Str..., V>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// make_property
+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) {
+	//return ctll::reject{};
+	constexpr char name[sizeof...(Name)]{static_cast<char>(Name)...};
+	constexpr auto p = uni::detail::binary_prop_from_string(get_string_view(name));
+
+	if constexpr (uni::detail::is_unknown(p)) {
+		return ctll::reject{};
+	} else {
+		return pcre_context{ctll::push_front(make_binary_property<p>(), ctll::list<Ts...>()), subject.parameters};
+	}
+}
+
+// make_property
+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) {
+	//return ctll::reject{};
+	constexpr auto prop = property_builder<Name...>::template get<Value...>();
+
+	if constexpr (std::is_same_v<decltype(prop), ctll::reject>) {
+		return ctll::reject{};
+	} else {
+		return pcre_context{ctll::push_front(prop, ctll::list<Ts...>()), subject.parameters};
+	}
+}
+
+// make_property_negative
+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) {
+	//return ctll::reject{};
+	constexpr char name[sizeof...(Name)]{static_cast<char>(Name)...};
+	constexpr auto p = uni::detail::binary_prop_from_string(get_string_view(name));
+
+	if constexpr (uni::detail::is_unknown(p)) {
+		return ctll::reject{};
+	} else {
+		return pcre_context{ctll::push_front(negate<make_binary_property<p>>(), ctll::list<Ts...>()), subject.parameters};
+	}
+}
+
+// make_property_negative
+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) {
+	//return ctll::reject{};
+	constexpr auto prop = property_builder<Name...>::template get<Value...>();
+
+	if constexpr (std::is_same_v<decltype(prop), ctll::reject>) {
+		return ctll::reject{};
+	} else {
+		return pcre_context{ctll::push_front(negate<decltype(prop)>(), ctll::list<Ts...>()), subject.parameters};
+	}
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__REPEAT__HPP
+#define CTRE__ACTIONS__REPEAT__HPP
+
+// repeat 1..N
+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) {
+	return pcre_context{ctll::push_front(plus<A>(), ctll::list<Ts...>()), subject.parameters};
+}
+// repeat 1..N (sequence)
+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) {
+	return pcre_context{ctll::push_front(plus<Content...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// repeat 0..N
+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) {
+	return pcre_context{ctll::push_front(star<A>(), ctll::list<Ts...>()), subject.parameters};
+}
+// repeat 0..N (sequence)
+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) {
+	return pcre_context{ctll::push_front(star<Content...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// create_number (seed)
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::create_number, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(number<static_cast<size_t>(V - '0')>(), subject.stack), subject.parameters};
+}
+// push_number
+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) {
+	constexpr size_t previous = N * 10ull;	
+	return pcre_context{ctll::push_front(number<(previous + (V - '0'))>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// repeat A..B
+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) {
+	return pcre_context{ctll::push_front(repeat<A,B,Subject>(), ctll::list<Ts...>()), subject.parameters};
+}
+// repeat A..B (sequence)
+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) {
+	return pcre_context{ctll::push_front(repeat<A,B,Content...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// repeat_exactly 
+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) {
+	return pcre_context{ctll::push_front(repeat<A,A,Subject>(), ctll::list<Ts...>()), subject.parameters};
+}
+// repeat_exactly A..B (sequence)
+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) {
+	return pcre_context{ctll::push_front(repeat<A,A,Content...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// repeat_at_least (A+) 
+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) {
+	return pcre_context{ctll::push_front(repeat<A,0,Subject>(), ctll::list<Ts...>()), subject.parameters};
+}
+// repeat_at_least (A+) (sequence)
+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) {
+	return pcre_context{ctll::push_front(repeat<A,0,Content...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// make_lazy (plus)
+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) {
+	return pcre_context{ctll::push_front(lazy_plus<Subject...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// make_lazy (star)
+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) {
+	return pcre_context{ctll::push_front(lazy_star<Subject...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// make_lazy (repeat<A,B>)
+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) {
+	return pcre_context{ctll::push_front(lazy_repeat<A,B,Subject...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// make_possessive (plus)
+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) {
+	return pcre_context{ctll::push_front(possessive_plus<Subject...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// make_possessive (star)
+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) {
+	return pcre_context{ctll::push_front(possessive_star<Subject...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// make_possessive (repeat<A,B>)
+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) {
+	return pcre_context{ctll::push_front(possessive_repeat<A,B,Subject...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__SEQUENCE__HPP
+#define CTRE__ACTIONS__SEQUENCE__HPP
+
+// make_sequence
+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) {
+	return pcre_context{ctll::push_front(sequence<A,B>(), ctll::list<Ts...>()), subject.parameters};
+}
+// make_sequence (concat)
+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) {
+	return pcre_context{ctll::push_front(sequence<A,Bs...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// make_sequence (make string)
+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) {
+	return pcre_context{ctll::push_front(string<A,B>(), ctll::list<Ts...>()), subject.parameters};
+}
+// make_sequence (concat string)
+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) {
+	return pcre_context{ctll::push_front(string<A,Bs...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// make_sequence (make string in front of different items)
+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) {
+	return pcre_context{ctll::push_front(sequence<string<A,B>,Sq...>(), ctll::list<Ts...>()), subject.parameters};
+}
+// make_sequence (concat string in front of different items)
+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) {
+	return pcre_context{ctll::push_front(sequence<string<A,Bs...>,Sq...>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__SET__HPP
+#define CTRE__ACTIONS__SET__HPP
+
+// UTILITY
+// add into set if not exists
+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 {}; }
+
+//template <template <typename...> typename SetType, typename A, typename BHead, typename... Bs> struct set_merge_helper {
+//	using step = decltype(push_back_into_set<SetType>(BHead(), A()));
+//	using type = ctll::conditional<(sizeof...(Bs) > 0), set_merge_helper<SetType, step, Bs...>, step>;
+//};
+//
+//// add set into set if not exists
+//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}}
+//
+//template <template <typename...> typename SetType, typename... As> static constexpr auto push_back_into_set(SetType<As...>, SetType<>) -> SetType<As...> { return pcre_context{{};), subject.parameters}}
+
+// END OF UTILITY
+
+// set_start
+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) {
+	return pcre_context{ctll::push_front(set<A>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// set_empty
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_empty, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
+	return pcre_context{ctll::push_front(set<>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// set_make
+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) {
+	return pcre_context{ctll::push_front(set<Content...>(), ctll::list<Ts...>()), subject.parameters};
+}
+// set_make_negative
+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) {
+	return pcre_context{ctll::push_front(negative_set<Content...>(), ctll::list<Ts...>()), subject.parameters};
+}
+// set{A...} + B = set{A,B}
+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) {
+	auto new_set = push_back_into_set<set>(A(), set<Content...>());
+	return pcre_context{ctll::push_front(new_set, ctll::list<Ts...>()), subject.parameters};
+}
+// TODO checkme
+//// set{A...} + set{B...} = set{A...,B...}
+//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) {
+//	auto new_set = push_back_into_set<set>(set<As...>(), set<Bs...>());
+//	return pcre_context{ctll::push_front(new_set, ctll::list<Ts...>()), subject.parameters};
+//}
+
+// negative_set{A...} + B = negative_set{A,B}
+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) {
+	auto new_set = push_back_into_set<set>(A(), set<Content...>());
+	return pcre_context{ctll::push_front(new_set, ctll::list<Ts...>()), subject.parameters};
+}
+// TODO checkme
+//// negative_set{A...} + negative_set{B...} = negative_set{A...,B...}
+//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) {
+//	auto new_set = push_back_into_set<negative_set>(negative_set<As...>(), negative_set<Bs...>());
+//	return pcre_context{ctll::push_front(new_set, ctll::list<Ts...>()), subject.parameters};
+//}
+// negate_class_named: [[^:digit:]] = [^[:digit:]]
+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) {
+	return pcre_context{ctll::push_front(negate<A>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+// add range to set
+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) {
+	return pcre_context{ctll::push_front(char_range<A,B>(), ctll::list<Ts...>()), subject.parameters};
+}
+
+#endif
+
+#ifndef CTRE__ACTIONS__MODE__HPP
+#define CTRE__ACTIONS__MODE__HPP
+
+// we need to reset counter and wrap Mode into mode_switch
+template <typename Mode, typename... Ts, typename Parameters> static constexpr auto apply_mode(Mode, ctll::list<Ts...>, Parameters) {
+	return pcre_context<ctll::list<mode_switch<Mode>, Ts...>, Parameters>{};
+}
+
+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>) {
+	return pcre_context<ctll::list<mode_switch<Mode>, Ts...>, pcre_parameters<Counter-1>>{};
+}
+
+// catch a semantic action into mode
+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>) {
+	return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
+}
+
+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>) {
+	return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
+}
+
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_singleline mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
+	return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
+}
+
+template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_multiline mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
+	return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
+}
+
+// to properly reset capture
+
+#endif
+
+};
+
+}
+
+#endif
+
+#ifndef CTRE__EVALUATION__HPP
+#define CTRE__EVALUATION__HPP
+
+#ifndef CTRE__STARTS_WITH_ANCHOR__HPP
+#define CTRE__STARTS_WITH_ANCHOR__HPP
+
+namespace ctre {
+
+template <typename... Content> 
+constexpr bool starts_with_anchor(const flags &, ctll::list<Content...>) noexcept {
+	return false;
+}
+
+template <typename... Content> 
+constexpr bool starts_with_anchor(const flags &, ctll::list<assert_subject_begin, Content...>) noexcept {
+	// yes! start subject anchor is here
+	return true;
+}
+
+template <typename... Content> 
+constexpr bool starts_with_anchor(const flags & f, ctll::list<assert_line_begin, Content...>) noexcept {
+	// yes! start line anchor is here
+	return !ctre::multiline_mode(f) || starts_with_anchor(f, ctll::list<Content...>{});
+}
+
+template <typename CharLike, typename... Content> 
+constexpr bool starts_with_anchor(const flags & f, ctll::list<boundary<CharLike>, Content...>) noexcept {
+	// check if all options starts with anchor or if they are empty, there is an anchor behind them
+	return starts_with_anchor(f, ctll::list<Content...>{});
+}
+
+template <typename... Options, typename... Content> 
+constexpr bool starts_with_anchor(const flags & f, ctll::list<select<Options...>, Content...>) noexcept {
+	// check if all options starts with anchor or if they are empty, there is an anchor behind them
+	return (starts_with_anchor(f, ctll::list<Options, Content...>{}) && ... && true);
+}
+
+template <typename... Optional, typename... Content> 
+constexpr bool starts_with_anchor(const flags & f, ctll::list<optional<Optional...>, Content...>) noexcept {
+	// check if all options starts with anchor or if they are empty, there is an anchor behind them
+	return starts_with_anchor(f, ctll::list<Optional..., Content...>{}) && starts_with_anchor(f, ctll::list<Content...>{});
+}
+
+template <typename... Optional, typename... Content> 
+constexpr bool starts_with_anchor(const flags & f, ctll::list<lazy_optional<Optional...>, Content...>) noexcept {
+	// check if all options starts with anchor or if they are empty, there is an anchor behind them
+	return starts_with_anchor(f, ctll::list<Optional..., Content...>{}) && starts_with_anchor(f, ctll::list<Content...>{});
+}
+
+template <typename... Seq, typename... Content> 
+constexpr bool starts_with_anchor(const flags & f, ctll::list<sequence<Seq...>, Content...>) noexcept {
+	// check if all options starts with anchor or if they are empty, there is an anchor behind them
+	return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
+}
+
+template <size_t A, size_t B, typename... Seq, typename... Content> 
+constexpr bool starts_with_anchor(const flags & f, ctll::list<repeat<A, B, Seq...>, Content...>) noexcept {
+	// check if all options starts with anchor or if they are empty, there is an anchor behind them
+	return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
+}
+
+template <size_t A, size_t B, typename... Seq, typename... Content> 
+constexpr bool starts_with_anchor(const flags & f, ctll::list<lazy_repeat<A, B, Seq...>, Content...>) noexcept {
+	// check if all options starts with anchor or if they are empty, there is an anchor behind them
+	return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
+}
+
+template <size_t A, size_t B, typename... Seq, typename... Content> 
+constexpr bool starts_with_anchor(const flags & f, ctll::list<possessive_repeat<A, B, Seq...>, Content...>) noexcept {
+	// check if all options starts with anchor or if they are empty, there is an anchor behind them
+	return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
+}
+
+template <size_t Index, typename... Seq, typename... Content> 
+constexpr bool starts_with_anchor(const flags & f, ctll::list<capture<Index, Seq...>, Content...>) noexcept {
+	// check if all options starts with anchor or if they are empty, there is an anchor behind them
+	return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
+}
+
+template <size_t Index, typename... Seq, typename... Content> 
+constexpr bool starts_with_anchor(const flags & f, ctll::list<capture_with_name<Index, Seq...>, Content...>) noexcept {
+	// check if all options starts with anchor or if they are empty, there is an anchor behind them
+	return starts_with_anchor(f, ctll::list<Seq..., Content...>{});
+}
+
+}
+
+#endif
+
+#ifndef CTRE__RETURN_TYPE__HPP
+#define CTRE__RETURN_TYPE__HPP
+
+#ifndef CTRE__UTF8__HPP
+#define CTRE__UTF8__HPP
+
+#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
+
+#ifndef CTRE_IN_A_MODULE
+#include <string_view>
+#include <iterator>
+#endif
+
+#if defined(__cpp_char8_t) &&__cpp_lib_char8_t >= 201811L
+#define CTRE_ENABLE_UTF8_RANGE
+#endif
+
+#if defined(__cpp_impl_three_way_comparison) && (__cpp_impl_three_way_comparison >= 201907L)
+#define CTRE_NO_NEED_FOR_ADDITIONAL_COMPARISONS
+#endif
+
+namespace ctre {
+
+struct utf8_iterator {
+	using self_type = utf8_iterator;
+	using value_type = char8_t;
+	using reference = char8_t;
+	using pointer = const char8_t *;
+	using iterator_category = std::bidirectional_iterator_tag;
+	using difference_type = int;
+	
+	struct sentinel {
+		// this is here only because I want to support std::make_reverse_iterator
+		using self_type = sentinel;
+		using value_type = char8_t;
+		using reference = char8_t &;
+		using pointer = const char8_t *;
+		using iterator_category = std::bidirectional_iterator_tag;
+		using difference_type = int;
+		
+		// it's just sentinel it won't be ever called
+		auto operator++() noexcept -> self_type &;
+		auto operator++(int) noexcept -> self_type;
+		auto operator--() noexcept -> self_type &;
+		auto operator--(int) noexcept -> self_type;
+		friend auto operator==(self_type, self_type) noexcept -> bool;
+		auto operator*() noexcept -> reference;
+		
+		friend constexpr auto operator==(self_type, const char8_t * other_ptr) noexcept {
+			return *other_ptr == char8_t{0};
+		}
+#ifndef CTRE_NO_NEED_FOR_ADDITIONAL_COMPARISONS		
+		friend constexpr auto operator!=(self_type, const char8_t * other_ptr) noexcept {
+			return *other_ptr != char8_t{0};
+		}
+		
+		friend constexpr auto operator==(const char8_t * other_ptr, self_type) noexcept {
+			return *other_ptr == char8_t{0};
+		}
+
+		friend constexpr auto operator!=(const char8_t * other_ptr, self_type) noexcept {
+			return *other_ptr != char8_t{0};
+		}
+#endif
+	};
+	
+	const char8_t * ptr{nullptr};
+	const char8_t * end{nullptr};
+#ifndef CTRE_NO_NEED_FOR_ADDITIONAL_COMPARISONS
+	constexpr friend bool operator!=(const utf8_iterator & lhs, sentinel) {
+		return lhs.ptr < lhs.end;
+	}
+	
+	constexpr friend bool operator!=(const utf8_iterator & lhs, const char8_t * rhs) {
+		return lhs.ptr != rhs;
+	}
+	
+	constexpr friend bool operator!=(const utf8_iterator & lhs, const utf8_iterator & rhs) {
+		return lhs.ptr != rhs.ptr;
+	}
+#endif	
+	constexpr friend bool operator==(const utf8_iterator & lhs, sentinel) {
+		return lhs.ptr >= lhs.end;
+	}
+	
+	constexpr friend bool operator==(const utf8_iterator & lhs, const char8_t * rhs) {
+		return lhs.ptr == rhs;
+	}
+	
+	constexpr friend bool operator==(const utf8_iterator & lhs, const utf8_iterator & rhs) {
+		return lhs.ptr == rhs.ptr;
+	}
+	
+#ifndef CTRE_NO_NEED_FOR_ADDITIONAL_COMPARISONS
+	constexpr friend bool operator!=(sentinel, const utf8_iterator & rhs) {
+		return rhs.ptr < rhs.end;
+	}
+	
+	constexpr friend bool operator!=(const char8_t * lhs, const utf8_iterator & rhs) {
+		return lhs == rhs.ptr;
+	}
+	
+	constexpr friend bool operator==(sentinel, const utf8_iterator & rhs) {
+		return rhs.ptr >= rhs.end;
+	}
+	
+	constexpr friend bool operator==(const char8_t * lhs, const utf8_iterator & rhs) {
+		return lhs == rhs.ptr;
+	}
+#endif
+	
+	
+	constexpr utf8_iterator & operator=(const char8_t * rhs) {
+		ptr = rhs;
+		return *this;
+	}
+	
+	constexpr operator const char8_t *() const noexcept {
+		return ptr;
+	}
+	
+	constexpr utf8_iterator & operator++() noexcept {
+		// the contant is mapping from first 5 bits of first code unit to length of UTF8 code point -1
+		// xxxxx -> yy (5 bits to 2 bits)
+		// 5 bits are 32 combination, and for each I need 2 bits, hence 64 bit constant
+		// (*ptr >> 2) & 0b111110 look at the left 5 bits ignoring the least significant
+		// & 0b11u  selects only needed two bits
+		// +1  because each iteration is at least one code unit forward
+		
+		ptr += ((0x3A55000000000000ull >> ((*ptr >> 2) & 0b111110u)) & 0b11u) + 1;
+		return *this;
+	}
+	
+	constexpr utf8_iterator & operator--() noexcept {
+		if (ptr > end) {
+			ptr = end-1;
+		} else {
+			--ptr;
+		}
+		
+		while ((*ptr & 0b11000000u) == 0b10'000000) {
+			--ptr;
+		}
+		
+		return *this;
+	}
+	
+	constexpr utf8_iterator operator--(int) noexcept {
+		auto self = *this;
+		this->operator--();
+		return self;
+	}
+	
+	constexpr utf8_iterator operator++(int) noexcept {
+		auto self = *this;
+		this->operator++();
+		return self;
+	}
+	
+	constexpr utf8_iterator operator+(unsigned step) const noexcept {
+		utf8_iterator result = *this;
+		while (step > 0) {
+			++result;
+			step--;
+		}
+		return result;
+	}
+	
+	constexpr utf8_iterator operator-(unsigned step) const noexcept {
+		utf8_iterator result = *this;
+		while (step > 0) {
+			--result;
+			step--;
+		}
+		return result;
+	}
+	
+	constexpr char32_t operator*() const noexcept {
+		constexpr char32_t mojibake = 0xFFFDull;
+		
+		// quickpath
+		if (!(*ptr & 0b1000'0000u)) CTRE_LIKELY {
+			return static_cast<char32_t>(*ptr);
+		}
+ 
+		// calculate length based on first 5 bits
+		const unsigned length = ((0x3A55000000000000ull >> ((*ptr >> 2) & 0b111110u)) & 0b11u);
+
+		// actual length is number + 1 bytes
+		
+		// length 0 here means it's a bad front unit
+		if (!length) CTRE_UNLIKELY {
+			return mojibake;
+		}
+
+		// if part of the utf-8 sequence is past the end
+		if (((ptr + length) >= end)) CTRE_UNLIKELY {
+			return mojibake;
+		}
+		
+		if ((ptr[1] & 0b1100'0000u) != 0b1000'0000) CTRE_UNLIKELY {
+			return mojibake;
+		}
+
+		const char8_t mask = static_cast<char8_t>(0b0011'1111u >> length);
+		
+		// length = 1 (2 bytes) mask = 0b0001'1111u
+		// length = 2 (3 bytes) mask = 0b0000'1111u
+		// length = 3 (4 bytes) mask = 0b0000'0111u
+
+		// remove utf8 front bits, get only significant part
+		// and add first trailing unit
+
+		char32_t result = static_cast<char32_t>((ptr[0] & mask) << 6u) | (ptr[1] & 0b0011'1111u);
+
+		// add rest of trailing units
+		if (length == 1) CTRE_LIKELY {
+			return result;
+		}
+
+		if ((ptr[2] & 0b1100'0000u) != 0b1000'0000) CTRE_UNLIKELY {
+			return mojibake;
+		}
+
+		result = (result << 6) | (ptr[2] & 0b0011'1111u);
+
+		if (length == 2) CTRE_LIKELY {
+			return result;
+		}
+
+		if ((ptr[3] & 0b1100'0000u) != 0b1000'0000) CTRE_UNLIKELY {
+			return mojibake;
+		}
+
+		return (result << 6) | (ptr[3] & 0b0011'1111u);
+	}
+};
+
+#ifdef CTRE_ENABLE_UTF8_RANGE
+struct utf8_range {
+	std::u8string_view range;
+	constexpr utf8_range(std::u8string_view r) noexcept: range{r} { }
+	
+	constexpr auto begin() const noexcept {
+		return utf8_iterator{range.data(), range.data() + range.size()};
+	}
+	constexpr auto end() const noexcept {
+		return utf8_iterator::sentinel{};
+	}
+};
+#endif
+
+}
+
+#endif
+
+#endif
+
+#ifndef CTRE_IN_A_MODULE
+#include <type_traits>
+#include <tuple>
+#include <string_view>
+#include <string>
+#include <iterator>
+#include <optional>
+#ifdef _MSC_VER
+#include <memory>
+#endif
+#include <iosfwd>
+#if __has_include(<charconv>)
+#include <charconv>
+#endif
+#if defined(__cpp_concepts) && __cpp_concepts >= 202002L
+#include <concepts>
+#endif
+#endif
+
+namespace ctre {
+
+constexpr auto is_random_accessible_f(const std::random_access_iterator_tag &) { return std::true_type{}; }
+constexpr auto is_random_accessible_f(...) { return std::false_type{}; }
+
+template <typename T> constexpr auto is_reverse_iterator_f(const std::reverse_iterator<T> &) { return std::true_type{}; }
+constexpr auto is_reverse_iterator_f(...) { return std::false_type{}; }
+
+template <typename T> constexpr bool is_random_accessible = decltype(is_random_accessible_f(std::declval<const T &>())){};
+template <typename T> constexpr bool is_reverse_iterator = decltype(is_reverse_iterator_f(std::declval<const T &>())){};
+
+struct not_matched_tag_t { };
+
+constexpr inline auto not_matched = not_matched_tag_t{};
+	
+template <size_t Id, typename Name = void> struct captured_content {
+	template <typename Iterator> class storage {
+		Iterator _begin{};
+		Iterator _end{};
+		
+		bool _matched{false};
+	public:
+		using char_type = typename std::iterator_traits<Iterator>::value_type;
+		
+		using name = Name;
+	
+		constexpr CTRE_FORCE_INLINE storage() noexcept {}
+	
+		constexpr CTRE_FORCE_INLINE void matched() noexcept {
+			_matched = true;
+		}
+		constexpr CTRE_FORCE_INLINE void unmatch() noexcept {
+			_matched = false;
+		}
+		constexpr CTRE_FORCE_INLINE void set_start(Iterator pos) noexcept {
+			_begin = pos;
+		}
+		constexpr CTRE_FORCE_INLINE storage & set_end(Iterator pos) noexcept {
+			_end = pos;
+			return *this;
+		}
+		constexpr CTRE_FORCE_INLINE Iterator get_end() const noexcept {
+			return _end;
+		}
+		
+	
+		constexpr auto begin() const noexcept {
+			return _begin;
+		}
+		constexpr auto end() const noexcept {
+			return _end;
+		}
+	
+		constexpr explicit CTRE_FORCE_INLINE operator bool() const noexcept {
+			return _matched;
+		}
+		
+		template <typename It = Iterator> constexpr CTRE_FORCE_INLINE const auto * data_unsafe() const noexcept {
+			static_assert(!is_reverse_iterator<It>, "Iterator in your capture must not be reverse!");
+			
+#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
+			if constexpr (std::is_same_v<Iterator, utf8_iterator>) {
+				return _begin.ptr;
+			} else { // I'm doing this to avoid warning about dead code
+#endif
+			
+#ifdef _MSC_VER
+			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
+#else
+			return &*_begin; 
+#endif
+			
+#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
+			}
+#endif
+		}
+		
+		template <typename It = Iterator> constexpr CTRE_FORCE_INLINE const auto * data() const noexcept {
+			constexpr bool must_be_contiguous_nonreverse_iterator = is_random_accessible<typename std::iterator_traits<It>::iterator_category> && !is_reverse_iterator<It>;
+			
+			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).");
+			
+			return data_unsafe();
+		}
+
+		constexpr CTRE_FORCE_INLINE auto size() const noexcept {
+			return static_cast<size_t>(std::distance(begin(), end()));
+		}
+		
+		constexpr CTRE_FORCE_INLINE size_t unit_size() const noexcept {
+#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
+			if constexpr (std::is_same_v<Iterator, utf8_iterator>) {
+				return static_cast<size_t>(std::distance(_begin.ptr, _end.ptr));
+			} else {
+				return static_cast<size_t>(std::distance(begin(), end()));
+			}
+#else
+			return static_cast<size_t>(std::distance(begin(), end()));
+#endif
+		}
+		
+#if __has_include(<charconv>)
+		template <typename R = int, typename... Ts> constexpr CTRE_FORCE_INLINE auto to_number(Ts && ... args) const noexcept -> R {
+			R result{0};
+			const auto view = to_view();
+			std::from_chars(view.data(), view.data() + view.size(), result, std::forward<Ts>(args)...);
+			return result;
+		}
+		
+		template <typename R = int, typename... Ts> constexpr CTRE_FORCE_INLINE auto to_optional_number(Ts && ... args) const noexcept -> std::optional<R> {
+			if (!static_cast<bool>(*this)) {
+				return std::nullopt;
+			}
+		
+			return to_number<R>(std::forward<Ts>(args)...);
+		}
+#endif
+		
+		template <typename It = Iterator> constexpr CTRE_FORCE_INLINE auto to_view() const noexcept {
+			// random access, because C++ (waving hands around)
+			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>;
+			
+			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.");
+	
+			return std::basic_string_view<char_type>(data_unsafe(), static_cast<size_t>(unit_size()));
+		}
+		
+		constexpr CTRE_FORCE_INLINE auto view() const noexcept {
+			return to_view();
+		}
+		
+		template <typename It = Iterator> constexpr CTRE_FORCE_INLINE auto to_optional_view() const noexcept -> std::optional<std::basic_string_view<char_type>> {
+			if (!static_cast<bool>(*this)) {
+				return std::nullopt;
+			}
+			return to_view();
+		}
+		
+		constexpr CTRE_FORCE_INLINE std::basic_string<char_type> to_string() const noexcept {
+#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
+			if constexpr (std::is_same_v<Iterator, utf8_iterator>) {
+				return std::basic_string<char_type>(data_unsafe(), static_cast<size_t>(unit_size()));
+			} else {
+				return std::basic_string<char_type>(begin(), end());
+			}
+#else
+			return std::basic_string<char_type>(begin(), end());
+#endif
+		}
+		
+		constexpr CTRE_FORCE_INLINE auto str() const noexcept {
+			return to_string();
+		}
+		
+		template <typename It = Iterator> constexpr CTRE_FORCE_INLINE auto to_optional_string() const noexcept -> std::optional<std::basic_string<char_type>> {
+			if (!static_cast<bool>(*this)) {
+				return std::nullopt;
+			}
+			return to_string();
+		}
+		
+		constexpr CTRE_FORCE_INLINE operator std::basic_string_view<char_type>() const noexcept {
+			return to_view();
+		}
+		
+		constexpr CTRE_FORCE_INLINE explicit operator std::basic_string<char_type>() const noexcept {
+			return to_string();
+		}
+		
+		constexpr CTRE_FORCE_INLINE operator std::optional<std::basic_string_view<char_type>>() const noexcept {
+			return to_optional_view();
+		}
+		
+		constexpr CTRE_FORCE_INLINE explicit operator std::optional<std::basic_string<char_type>>() const noexcept {
+			return to_optional_string();
+		}
+		
+		constexpr CTRE_FORCE_INLINE static size_t get_id() noexcept {
+			return Id;
+		}
+		
+		friend CTRE_FORCE_INLINE constexpr bool operator==(const storage & lhs, std::basic_string_view<char_type> rhs) noexcept {
+			return bool(lhs) ? lhs.view() == rhs : false;
+		}
+		friend CTRE_FORCE_INLINE constexpr bool operator!=(const storage & lhs, std::basic_string_view<char_type> rhs) noexcept {
+			return bool(lhs) ? lhs.view() != rhs : false;
+		}
+		friend CTRE_FORCE_INLINE constexpr bool operator==(std::basic_string_view<char_type> lhs, const storage & rhs) noexcept {
+			return bool(rhs) ? lhs == rhs.view() : false;
+		}
+		friend CTRE_FORCE_INLINE constexpr bool operator!=(std::basic_string_view<char_type> lhs, const storage & rhs) noexcept {
+			return bool(rhs) ? lhs != rhs.view() : false;
+		}
+		friend CTRE_FORCE_INLINE std::ostream & operator<<(std::ostream & str, const storage & rhs) {
+			return str << rhs.view();
+		}
+	};
+};
+
+#if defined(__cpp_concepts) && __cpp_concepts >= 202002L
+template <typename T> concept capture_group = requires(const T & cap) {
+	{ T::get_id() } -> std::same_as<size_t>;
+	{ cap.view() };
+	{ cap.str() };
+	{ cap.to_string() };
+	{ cap.to_view() };
+	{ cap.unit_size() } -> std::same_as<size_t>;
+	{ cap.size() } -> std::same_as<size_t>;
+	{ static_cast<bool>(cap) };
+	{ cap.data() };
+	{ cap.data_unsafe() };
+	{ cap.begin() };
+	{ cap.end() };
+};
+#endif
+
+struct capture_not_exists_tag { };
+
+constexpr auto capture_not_exists = capture_not_exists_tag{};
+
+template <typename... Captures> struct captures;
+
+template <typename Head, typename... Tail> struct captures<Head, Tail...>: captures<Tail...> {
+	Head head{};
+	constexpr CTRE_FORCE_INLINE captures() noexcept { }
+	template <size_t id> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
+		if constexpr (id == Head::get_id()) {
+			return true;
+		} else {
+			return captures<Tail...>::template exists<id>();
+		}
+	}
+	template <typename Name> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
+		if constexpr (std::is_same_v<Name, typename Head::name>) {
+			return true;
+		} else {
+			return captures<Tail...>::template exists<Name>();
+		}
+	}
+#if CTRE_CNTTP_COMPILER_CHECK
+	template <ctll::fixed_string Name> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
+#else
+	template <const auto & Name> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
+#endif
+		if constexpr (std::is_same_v<typename Head::name, void>) {
+			return captures<Tail...>::template exists<Name>();
+		} else {
+			if constexpr (Head::name::name.is_same_as(Name)) {
+				return true;
+			} else {
+				return captures<Tail...>::template exists<Name>();
+			}
+		}
+	}
+	template <size_t id> CTRE_FORCE_INLINE constexpr auto & select() noexcept {
+		if constexpr (id == Head::get_id()) {
+			return head;
+		} else {
+			return captures<Tail...>::template select<id>();
+		}
+	}
+	template <typename Name> CTRE_FORCE_INLINE constexpr auto & select() noexcept {
+		if constexpr (std::is_same_v<Name, typename Head::name>) {
+			return head;
+		} else {
+			return captures<Tail...>::template select<Name>();
+		}
+	}
+	template <size_t id> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
+		if constexpr (id == Head::get_id()) {
+			return head;
+		} else {
+			return captures<Tail...>::template select<id>();
+		}
+	}
+	template <typename Name> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
+		if constexpr (std::is_same_v<Name, typename Head::name>) {
+			return head;
+		} else {
+			return captures<Tail...>::template select<Name>();
+		}
+	}
+#if CTRE_CNTTP_COMPILER_CHECK
+	template <ctll::fixed_string Name> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
+#else
+	template <const auto & Name> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
+#endif
+		if constexpr (std::is_same_v<typename Head::name, void>) {
+			return captures<Tail...>::template select<Name>();
+		} else {
+			if constexpr (Head::name::name.is_same_as(Name)) {
+				return head;
+			} else {
+				return captures<Tail...>::template select<Name>();
+			}
+		}
+	}
+};
+
+template <> struct captures<> {
+	constexpr CTRE_FORCE_INLINE captures() noexcept { }
+	template <size_t> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
+		return false;
+	}
+	template <typename> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
+		return false;
+	}
+#if CTRE_CNTTP_COMPILER_CHECK
+	template <ctll::fixed_string> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
+#else
+	template <const auto &> CTRE_FORCE_INLINE static constexpr bool exists() noexcept {
+#endif
+		return false;
+	}
+	template <size_t> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
+		return capture_not_exists;
+	}
+	template <typename> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
+		return capture_not_exists;
+	}
+#if CTRE_CNTTP_COMPILER_CHECK
+	template <ctll::fixed_string> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
+#else
+	template <const auto &> CTRE_FORCE_INLINE constexpr auto & select() const noexcept {
+#endif
+		return capture_not_exists;
+	}
+};
+
+template <typename Iterator, typename... Captures> class regex_results {
+	captures<captured_content<0>::template storage<Iterator>, typename Captures::template storage<Iterator>...> _captures{};
+public:
+	using char_type = typename std::iterator_traits<Iterator>::value_type;
+	
+	constexpr CTRE_FORCE_INLINE regex_results() noexcept { }
+	constexpr CTRE_FORCE_INLINE regex_results(not_matched_tag_t) noexcept { }
+	
+	// special constructor for deducting
+	constexpr CTRE_FORCE_INLINE regex_results(Iterator, ctll::list<Captures...>) noexcept { }
+	
+	template <size_t Id> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
+		constexpr bool capture_of_provided_id_must_exists = decltype(_captures)::template exists<Id>();
+		static_assert(capture_of_provided_id_must_exists);
+		
+		if constexpr (capture_of_provided_id_must_exists) {
+			return _captures.template select<Id>();
+		} else {
+			return false;
+		}
+	}
+	template <typename Name> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
+		constexpr bool capture_of_provided_name_must_exists = decltype(_captures)::template exists<Name>();
+		static_assert(capture_of_provided_name_must_exists);
+	
+		if constexpr (capture_of_provided_name_must_exists) {
+			return _captures.template select<Name>();
+		} else {
+			return false;
+		}
+	}
+#if CTRE_CNTTP_COMPILER_CHECK
+	template <ctll::fixed_string Name> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
+#else
+	template <const auto & Name> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
+#endif
+		constexpr bool capture_of_provided_name_must_exists = decltype(_captures)::template exists<Name>();
+		static_assert(capture_of_provided_name_must_exists);
+	
+		if constexpr (capture_of_provided_name_must_exists) {
+			return _captures.template select<Name>();
+		} else {
+			return false;
+		}
+	}
+	static constexpr size_t count() noexcept {
+		return sizeof...(Captures) + 1;
+	}
+	constexpr CTRE_FORCE_INLINE regex_results & matched() noexcept {
+		_captures.template select<0>().matched();
+		return *this;
+	}
+	constexpr CTRE_FORCE_INLINE regex_results & unmatch() noexcept {
+		_captures.template select<0>().unmatch();
+		return *this;
+	}
+	constexpr CTRE_FORCE_INLINE operator bool() const noexcept {
+		return bool(_captures.template select<0>());
+	}
+	
+	// implicit conversions
+	constexpr CTRE_FORCE_INLINE operator std::basic_string_view<char_type>() const noexcept {
+		return to_view();
+	}
+	
+	constexpr CTRE_FORCE_INLINE explicit operator std::basic_string<char_type>() const noexcept {
+		return to_string();
+	}
+	
+	constexpr CTRE_FORCE_INLINE operator std::optional<std::basic_string_view<char_type>>() const noexcept {
+		return to_optional_view();
+	}
+	
+	constexpr CTRE_FORCE_INLINE explicit operator std::optional<std::basic_string<char_type>>() const noexcept {
+		return to_optional_string();
+	}
+	
+	// conversion to numbers
+#if __has_include(<charconv>)
+	template <typename R = int, typename... Ts> constexpr CTRE_FORCE_INLINE auto to_number(Ts && ... args) const noexcept -> R {
+		return _captures.template select<0>().template to_number<R>(std::forward<Ts>(args)...);
+	}
+	
+	template <typename R = int, typename... Ts> constexpr CTRE_FORCE_INLINE auto to_optional_number(Ts && ... args) const noexcept -> std::optional<R> {
+		return _captures.template select<0>().template to_optional_number<R>(std::forward<Ts>(args)...);
+	}
+#endif
+	
+	// conversion to basic_string_view
+	constexpr CTRE_FORCE_INLINE auto to_view() const noexcept {
+		return _captures.template select<0>().to_view();
+	}
+	
+	constexpr CTRE_FORCE_INLINE auto view() const noexcept {
+		return _captures.template select<0>().view(); // this should be deprecated (??)
+	}
+	
+	constexpr CTRE_FORCE_INLINE auto to_optional_view() const noexcept {
+		return _captures.template select<0>().to_optional_view();
+	}
+	
+	// conversion to basic_string
+	constexpr CTRE_FORCE_INLINE auto to_string() const noexcept {
+		return _captures.template select<0>().to_string();
+	}
+	
+	constexpr CTRE_FORCE_INLINE auto str() const noexcept {
+		return _captures.template select<0>().to_string();  // this should be deprecated (??)
+	}
+	
+	constexpr CTRE_FORCE_INLINE auto to_optional_string() const noexcept {
+		return _captures.template select<0>().to_optional_string();
+	}
+	
+	
+	
+	
+	
+	constexpr CTRE_FORCE_INLINE size_t size() const noexcept {
+		return _captures.template select<0>().size();
+	}
+	
+	constexpr CTRE_FORCE_INLINE const auto * data() const noexcept {
+		return _captures.template select<0>().data();
+	}
+	
+	constexpr CTRE_FORCE_INLINE regex_results & set_start_mark(Iterator pos) noexcept {
+		_captures.template select<0>().set_start(pos);
+		return *this;
+	}
+	constexpr CTRE_FORCE_INLINE regex_results & set_end_mark(Iterator pos) noexcept {
+		_captures.template select<0>().set_end(pos);
+		return *this;
+	}
+	constexpr CTRE_FORCE_INLINE Iterator get_end_position() const noexcept {
+		return _captures.template select<0>().get_end();
+	}
+	template <size_t Id> CTRE_FORCE_INLINE constexpr regex_results & start_capture(Iterator pos) noexcept {
+		_captures.template select<Id>().set_start(pos);
+		return *this;
+	}
+	template <size_t Id> CTRE_FORCE_INLINE constexpr regex_results & end_capture(Iterator pos) noexcept {
+		_captures.template select<Id>().set_end(pos).matched();
+		return *this;
+	}
+	constexpr auto begin() const noexcept {
+		return _captures.template select<0>().begin();
+	}
+	constexpr auto end() const noexcept {
+		return _captures.template select<0>().end();
+	}
+	friend CTRE_FORCE_INLINE constexpr bool operator==(const regex_results & lhs, std::basic_string_view<char_type> rhs) noexcept {
+		return bool(lhs) ? lhs.view() == rhs : false;
+	}
+	friend CTRE_FORCE_INLINE constexpr bool operator!=(const regex_results & lhs, std::basic_string_view<char_type> rhs) noexcept {
+		return bool(lhs) ? lhs.view() != rhs : true;
+	}
+	friend CTRE_FORCE_INLINE constexpr bool operator==(std::basic_string_view<char_type> lhs, const regex_results & rhs) noexcept {
+		return bool(rhs) ? lhs == rhs.view() : false;
+	}
+	friend CTRE_FORCE_INLINE constexpr bool operator!=(std::basic_string_view<char_type> lhs, const regex_results & rhs) noexcept {
+		return bool(rhs) ? lhs != rhs.view() : true;
+	}
+	friend CTRE_FORCE_INLINE std::ostream & operator<<(std::ostream & str, const regex_results & rhs) {
+#ifdef CTRE_IN_A_MODULE
+		auto view = rhs.view();
+		str.write(view.data(), view.size());
+		return str;
+#else
+		return str << rhs.view();
+#endif
+	}
+};
+
+template <size_t Id, typename Iterator, typename... Captures> constexpr auto get(const regex_results<Iterator, Captures...> & results) noexcept {
+	return results.template get<Id>();
+}
+
+template <typename Iterator, typename... Captures> regex_results(Iterator, ctll::list<Captures...>) -> regex_results<Iterator, Captures...>;
+
+template <typename> struct is_regex_results_t: std::false_type { };
+
+template <typename Iterator, typename... Captures> struct is_regex_results_t<regex_results<Iterator, Captures...>>: std::true_type { };
+
+template <typename T> constexpr bool is_regex_results_v = is_regex_results_t<T>();
+
+#if defined(__cpp_concepts) && __cpp_concepts >= 201907L
+template <typename T> concept capture_groups = is_regex_results_v<T>;
+#endif
+
+template <typename ResultIterator, typename Pattern> using return_type = decltype(regex_results(std::declval<ResultIterator>(), find_captures(Pattern{})));
+
+}
+
+// support for structured bindings
+
+#ifndef __EDG__
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmismatched-tags"
+#endif
+
+namespace std {
+	template <typename... Captures> struct tuple_size<ctre::regex_results<Captures...>> : public std::integral_constant<size_t, ctre::regex_results<Captures...>::count()> { };
+	
+	template <size_t N, typename... Captures> struct tuple_element<N, ctre::regex_results<Captures...>> {
+	public:
+		using type = decltype(
+			std::declval<const ctre::regex_results<Captures...> &>().template get<N>()
+		);
+	};
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+#endif
+
+#endif
+
+#ifndef CTRE__FIND_CAPTURES__HPP
+#define CTRE__FIND_CAPTURES__HPP
+
+namespace ctre {
+
+CTRE_EXPORT template <typename Pattern> constexpr auto find_captures(Pattern) noexcept {
+	return find_captures(ctll::list<Pattern>(), ctll::list<>());
+}
+
+CTRE_EXPORT template <typename... Output> constexpr auto find_captures(ctll::list<>, ctll::list<Output...> output) noexcept {
+	return output;
+}
+
+CTRE_EXPORT template <auto... String, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<string<String...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Options, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<select<Options...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Options..., Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<optional<Content...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<lazy_optional<Content...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<sequence<Content...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Tail, typename Output> constexpr auto find_captures(ctll::list<empty, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Tail, typename Output> constexpr auto find_captures(ctll::list<assert_subject_begin, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Tail, typename Output> constexpr auto find_captures(ctll::list<assert_subject_end, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Tail...>(), output);
+}
+
+// , typename = std::enable_if_t<(MatchesCharacter<CharacterLike>::template value<char>)
+CTRE_EXPORT template <typename CharacterLike, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<CharacterLike, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<plus<Content...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<star<Content...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+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 {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<lazy_plus<Content...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<lazy_star<Content...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+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 {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<possessive_plus<Content...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<possessive_star<Content...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+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 {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<lookahead_positive<Content...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+CTRE_EXPORT template <typename... Content, typename... Tail, typename Output> constexpr auto find_captures(ctll::list<lookahead_negative<Content...>, Tail...>, Output output) noexcept {
+	return find_captures(ctll::list<Content..., Tail...>(), output);
+}
+
+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 {
+	return find_captures(ctll::list<Content..., Tail...>(), ctll::list<Output..., captured_content<Id>>());
+}
+
+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 {
+	return find_captures(ctll::list<Content..., Tail...>(), ctll::list<Output..., captured_content<Id, Name>>());
+}
+
+}
+
+#endif
+
+#ifndef CTRE__FIRST__HPP
+#define CTRE__FIRST__HPP
+
+namespace ctre {
+	
+struct can_be_anything {};
+	
+
+template <typename... Content> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<>) noexcept {
+	return l;
+}
+
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<accept, Tail...>) noexcept {
+	return l;
+}
+
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<end_mark, Tail...>) noexcept {
+	return l;
+}
+
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<end_cycle_mark, Tail...>) noexcept {
+	return l;
+}
+
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<end_lookahead_mark, Tail...>) noexcept {
+	return l;
+}
+
+template <typename... Content, size_t Id, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<numeric_mark<Id>, Tail...>) noexcept {
+	return first(l, ctll::list<Tail...>{});
+}
+
+// empty
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<empty, Tail...>) noexcept {
+	return first(l, ctll::list<Tail...>{});
+}
+
+// boundary
+template <typename... Content, typename CharLike, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<boundary<CharLike>, Tail...>) noexcept {
+	return first(l, ctll::list<Tail...>{});
+}
+
+// asserts
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<assert_subject_begin, Tail...>) noexcept {
+	return first(l, ctll::list<Tail...>{});
+}
+
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<assert_subject_end, Tail...>) noexcept {
+	return l;
+}
+
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<assert_subject_end_line, Tail...>) noexcept {
+	// FIXME allow endline here
+	return l;
+}
+
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<assert_line_begin, Tail...>) noexcept {
+	// FIXME line begin is a bit different than subject begin
+	return first(l, ctll::list<Tail...>{});
+}
+
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<assert_line_end, Tail...>) noexcept {
+	// FIXME line end is a bit different than subject begin
+	return l;
+}
+
+// sequence
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<sequence<Seq...>, Tail...>) noexcept {
+	return first(l, ctll::list<Seq..., Tail...>{});
+}
+
+// atomic group
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<atomic_group<Seq...>, Tail...>) noexcept {
+	return first(l, ctll::list<possessive_repeat<1, 1, Seq...>, Tail...>{});
+}
+
+// plus
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<plus<Seq...>, Tail...>) noexcept {
+	return first(l, ctll::list<Seq..., Tail...>{});
+}
+
+// lazy_plus
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<lazy_plus<Seq...>, Tail...>) noexcept {
+	return first(l, ctll::list<Seq..., Tail...>{});
+}
+
+// possessive_plus
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<possessive_plus<Seq...>, Tail...>) noexcept {
+	return first(l, ctll::list<Seq..., Tail...>{});
+}
+
+// star
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<star<Seq...>, Tail...>) noexcept {
+	return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
+}
+
+// lazy_star
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<lazy_star<Seq...>, Tail...>) noexcept {
+	return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
+}
+
+// possessive_star
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<possessive_star<Seq...>, Tail...>) noexcept {
+	return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
+}
+
+// lazy_repeat
+template <typename... Content, size_t A, size_t B, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<lazy_repeat<A, B, Seq...>, Tail...>) noexcept {
+	return first(l, ctll::list<Seq..., Tail...>{});
+}
+
+template <typename... Content, size_t B, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<lazy_repeat<0, B, Seq...>, Tail...>) noexcept {
+	return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
+}
+
+// possessive_repeat
+template <typename... Content, size_t A, size_t B, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<possessive_repeat<A, B, Seq...>, Tail...>) noexcept {
+	return first(l, ctll::list<Seq..., Tail...>{});
+}
+
+template <typename... Content, size_t B, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<possessive_repeat<0, B, Seq...>, Tail...>) noexcept {
+	return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
+}
+
+// repeat
+template <typename... Content, size_t A, size_t B, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<repeat<A, B, Seq...>, Tail...>) noexcept {
+	return first(l, ctll::list<Seq..., Tail...>{});
+}
+
+template <typename... Content, size_t B, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<repeat<0, B, Seq...>, Tail...>) noexcept {
+	return first(first(l, ctll::list<Tail...>{}), ctll::list<Seq..., Tail...>{});
+}
+
+// lookahead_positive
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<lookahead_positive<Seq...>, Tail...>) noexcept {
+	return ctll::list<can_be_anything>{};
+}
+
+// lookbehind_negative TODO fixme
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<lookbehind_negative<Seq...>, Tail...>) noexcept {
+	return ctll::list<can_be_anything>{};
+}
+
+// lookbehind_positive
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<lookbehind_positive<Seq...>, Tail...>) noexcept {
+	return ctll::list<can_be_anything>{};
+}
+
+// lookahead_negative TODO fixme
+template <typename... Content, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<lookahead_negative<Seq...>, Tail...>) noexcept {
+	return ctll::list<can_be_anything>{};
+}
+
+// capture
+template <typename... Content, size_t Id, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<capture<Id, Seq...>, Tail...>) noexcept {
+	return first(l, ctll::list<Seq..., Tail...>{});
+}
+
+template <typename... Content, size_t Id, typename Name, typename... Seq, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<capture_with_name<Id, Name, Seq...>, Tail...>) noexcept {
+	return first(l, ctll::list<Seq..., Tail...>{});
+}
+
+// backreference
+template <typename... Content, size_t Id, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<back_reference<Id>, Tail...>) noexcept {
+	return ctll::list<can_be_anything>{};
+}
+
+template <typename... Content, typename Name, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<back_reference_with_name<Name>, Tail...>) noexcept {
+	return ctll::list<can_be_anything>{};
+}
+
+// string First extraction
+template <typename... Content, auto First, auto... String, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<string<First, String...>, Tail...>) noexcept {
+	return ctll::list<Content..., character<First>>{};
+}
+
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<string<>, Tail...>) noexcept {
+	return first(l, ctll::list<Tail...>{});
+}
+
+// optional
+template <typename... Content, typename... Opt, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<optional<Opt...>, Tail...>) noexcept {
+	return first(first(l, ctll::list<Opt..., Tail...>{}), ctll::list<Tail...>{});
+}
+
+template <typename... Content, typename... Opt, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<lazy_optional<Opt...>, Tail...>) noexcept {
+	return first(first(l, ctll::list<Opt..., Tail...>{}), ctll::list<Tail...>{});
+}
+
+// select (alternation)
+template <typename... Content, typename SHead, typename... STail, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<select<SHead, STail...>, Tail...>) noexcept {
+	return first(first(l, ctll::list<SHead, Tail...>{}), ctll::list<select<STail...>, Tail...>{});
+}
+
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...> l, ctll::list<select<>, Tail...>) noexcept {
+	return l;
+}
+
+// unicode property => anything
+template <typename... Content, typename PropertyType, PropertyType Property, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<ctre::binary_property<PropertyType, Property>, Tail...>) noexcept {
+	return ctll::list<can_be_anything>{};
+}
+
+template <typename... Content, typename PropertyType, PropertyType Property, auto Value, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<ctre::property<PropertyType, Property, Value>, Tail...>) noexcept {
+	return ctll::list<can_be_anything>{};
+}
+
+// characters / sets
+
+template <typename... Content, auto V, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<character<V>, Tail...>) noexcept {
+	return ctll::list<Content..., character<V>>{};
+}
+
+template <typename... Content, auto... Values, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<enumeration<Values...>, Tail...>) noexcept {
+	return ctll::list<Content..., character<Values>...>{};
+}
+
+template <typename... Content, typename... SetContent, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<set<SetContent...>, Tail...>) noexcept {
+	return ctll::list<Content..., SetContent...>{};
+}
+
+template <typename... Content, auto A, auto B, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<char_range<A,B>, Tail...>) noexcept {
+	return ctll::list<Content..., char_range<A,B>>{};
+}
+
+template <typename... Content, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<any, Tail...>) noexcept {
+	return ctll::list<can_be_anything>{};
+}
+
+// negative
+template <typename... Content, typename... SetContent, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<negate<SetContent...>, Tail...>) noexcept {
+	return ctll::list<Content..., negative_set<SetContent...>>{};
+}
+
+template <typename... Content, typename... SetContent, typename... Tail> 
+constexpr auto first(ctll::list<Content...>, ctll::list<negative_set<SetContent...>, Tail...>) noexcept {
+	return ctll::list<Content..., negative_set<SetContent...>>{};
+}
+
+// user facing interface
+template <typename... Content> constexpr auto calculate_first(Content...) noexcept {
+	return first(ctll::list<>{}, ctll::list<Content...>{});
+}
+
+// calculate mutual exclusivity
+template <typename... Content> constexpr size_t calculate_size_of_first(ctre::negative_set<Content...>) {
+	return 1 + calculate_size_of_first(ctre::set<Content...>{});
+}
+
+template <auto... V> constexpr size_t calculate_size_of_first(ctre::enumeration<V...>) {
+	return sizeof...(V);
+}
+
+constexpr size_t calculate_size_of_first(...) {
+	return 1;
+}
+
+template <typename... Content> constexpr size_t calculate_size_of_first(ctll::list<Content...>) {
+	return (calculate_size_of_first(Content{}) + ... + 0);
+}
+
+template <typename... Content> constexpr size_t calculate_size_of_first(ctre::set<Content...>) {
+	return (calculate_size_of_first(Content{}) + ... + 0);
+}
+
+template <auto A, typename CB> constexpr int64_t negative_helper(ctre::character<A>, CB & cb, int64_t start) {
+	if (A != (std::numeric_limits<int64_t>::min)()) {
+		if (start < A) {
+			cb(start, A-1);
+		}
+	}
+	if (A != (std::numeric_limits<int64_t>::max)()) {
+		return A+1;
+	} else {
+		return A;
+	}
+}	
+
+template <auto A, auto B, typename CB> constexpr int64_t negative_helper(ctre::char_range<A,B>, CB & cb, int64_t start) {
+	if (A != (std::numeric_limits<int64_t>::min)()) {
+		if (start < A) {
+			cb(start, A-1);
+		}
+	}
+	if (B != (std::numeric_limits<int64_t>::max)()) {
+		return B+1;
+	} else {
+		return B;
+	}
+}	
+
+template <auto Head, auto... Tail, typename CB> constexpr int64_t negative_helper(ctre::enumeration<Head, Tail...>, CB & cb, int64_t start) {
+	int64_t nstart = negative_helper(ctre::character<Head>{}, cb, start);
+	return negative_helper(ctre::enumeration<Tail...>{}, cb, nstart);
+}
+
+template <typename CB> constexpr int64_t negative_helper(ctre::enumeration<>, CB &, int64_t start) {
+	return start;
+}
+
+template <typename CB> constexpr int64_t negative_helper(ctre::set<>, CB &, int64_t start) {
+	return start;
+}
+
+template <typename PropertyType, PropertyType Property, typename CB> 
+constexpr auto negative_helper(ctre::binary_property<PropertyType, Property>, CB &&, int64_t start) {
+	return start;
+}
+
+template <typename PropertyType, PropertyType Property, auto Value, typename CB> 
+constexpr auto negative_helper(ctre::property<PropertyType, Property, Value>, CB &&, int64_t start) {
+	return start;
+}
+
+template <typename Head, typename... Rest, typename CB> constexpr int64_t negative_helper(ctre::set<Head, Rest...>, CB & cb, int64_t start) {
+	start = negative_helper(Head{}, cb, start);
+	return negative_helper(ctre::set<Rest...>{}, cb, start);
+}
+
+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)()) {
+	start = negative_helper(Head{}, cb, start);
+	negative_helper(ctre::negative_set<Rest...>{}, std::forward<CB>(cb), start);
+}
+
+template <typename CB> constexpr void negative_helper(ctre::negative_set<>, CB && cb, int64_t start = (std::numeric_limits<int64_t>::min)()) {
+	if (start < (std::numeric_limits<int64_t>::max)()) {
+		cb(start, (std::numeric_limits<int64_t>::max)());
+	}
+}
+
+// simple fixed set
+// TODO: this needs some optimizations
+template <size_t Capacity> class point_set {
+	struct point {
+		int64_t low{};
+		int64_t high{};
+		constexpr bool operator<(const point & rhs) const {
+			return low < rhs.low;
+		}
+		constexpr point() { }
+		constexpr point(int64_t l, int64_t h): low{l}, high{h} { }
+	};
+	point points[Capacity+1]{};
+	size_t used{0};
+	constexpr point * begin() {
+		return points;
+	}
+	constexpr point * begin() const {
+		return points;
+	}
+	constexpr point * end() {
+		return points + used;
+	}
+	constexpr point * end() const {
+		return points + used;
+	}
+	constexpr point * lower_bound(point obj) {
+		auto first = begin();
+		auto last = end();
+		auto it = first;
+		auto count = std::distance(first, last);
+		while (count != 0) {
+			it = first;
+			auto step = count / 2;
+			std::advance(it, step);
+			if (*it < obj) {
+				first = ++it;
+				count -= step + 1;
+			} else {
+				count = step;
+			}
+		}
+		return it;
+	}
+	constexpr point * insert_point(int64_t position, int64_t other) {
+		point obj{position, other};
+		auto it = lower_bound(obj);
+		if (it == end()) {
+			*it = obj;
+			used++;
+			return it;
+		} else {
+			auto out = it;
+			auto e = end();
+			while (it != e) {
+				auto tmp = *it;
+				*it = obj;
+				obj = tmp;
+				//std::swap(*it, obj);
+				it++;
+			}
+			auto tmp = *it;
+			*it = obj;
+			obj = tmp;
+			//std::swap(*it, obj);
+			
+			used++;
+			return out;
+		}
+	}
+public:
+	constexpr point_set() { }
+	constexpr void insert(int64_t low, int64_t high) {
+		insert_point(low, high);
+		//insert_point(high, low);
+	}
+	constexpr bool check(int64_t low, int64_t high) {
+		for (const auto & r: *this) {
+			if (r.low <= low && low <= r.high) {
+				return true;
+			} else if (r.low <= high && high <= r.high) {
+				return true;
+			} else if (low <= r.low && r.low <= high) {
+				return true;
+			} else if (low <= r.high && r.high <= high) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	
+	template <auto V> constexpr bool check(ctre::character<V>) {
+		return check(V,V);
+	}
+	template <auto A, auto B> constexpr bool check(ctre::char_range<A,B>) {
+		return check(A,B);
+	}
+	constexpr bool check(can_be_anything) {
+		return used > 0;
+	}
+	template <typename PropertyType, PropertyType Property> 
+	constexpr bool check(ctre::binary_property<PropertyType, Property>) {
+		return check(can_be_anything{});
+	}
+
+	template <typename PropertyType, PropertyType Property, auto Value> 
+	constexpr bool check(ctre::property<PropertyType, Property, Value>) {
+		return check(can_be_anything{});
+	}
+	template <typename... Content> constexpr bool check(ctre::negative_set<Content...> nset) {
+		bool collision = false;
+		negative_helper(nset, [&](int64_t low, int64_t high){
+			collision |= this->check(low, high);
+		});
+		return collision;
+	}
+	template <auto... V> constexpr bool check(ctre::enumeration<V...>) {
+		
+		return (check(V,V) || ... || false);
+	}
+	template <typename... Content> constexpr bool check(ctll::list<Content...>) {
+		return (check(Content{}) || ... || false);
+	}
+	template <typename... Content> constexpr bool check(ctre::set<Content...>) {
+		return (check(Content{}) || ... || false);
+	}
+	
+	
+	template <auto V> constexpr void populate(ctre::character<V>) {
+		insert(V,V);
+	}
+	template <auto A, auto B> constexpr void populate(ctre::char_range<A,B>) {
+		insert(A,B);
+	}
+	constexpr void populate(...) {
+		points[0].low = (std::numeric_limits<int64_t>::min)();
+		points[0].high = (std::numeric_limits<int64_t>::max)();
+		used = 1;
+	}
+	template <typename... Content> constexpr void populate(ctre::negative_set<Content...> nset) {
+		negative_helper(nset, [&](int64_t low, int64_t high){
+			this->insert(low, high);
+		});
+	}
+	template <typename... Content> constexpr void populate(ctre::set<Content...>) {
+		(populate(Content{}), ...);
+	}
+	template <typename... Content> constexpr void populate(ctll::list<Content...>) {
+		(populate(Content{}), ...);
+	}
+};
+
+template <typename... A, typename... B> constexpr bool collides(ctll::list<A...> rhs, ctll::list<B...> lhs) {
+	constexpr size_t capacity = calculate_size_of_first(rhs);
+	
+	point_set<capacity> set;
+	set.populate(rhs);
+	
+	return set.check(lhs);
+}
+
+}
+
+#endif
+
+#ifndef CTRE_IN_A_MODULE
+#include <iterator>
+#endif
+
+// remove me when MSVC fix the constexpr bug
+#ifdef _MSC_VER
+#ifndef CTRE_MSVC_GREEDY_WORKAROUND
+#define CTRE_MSVC_GREEDY_WORKAROUND
+#endif
+#endif
+
+namespace ctre {
+
+template <size_t Limit> constexpr CTRE_FORCE_INLINE bool less_than_or_infinite([[maybe_unused]] size_t i) noexcept {
+	if constexpr (Limit == 0) {
+		// infinite
+		return true;
+	} else {
+		return i < Limit;
+	}
+}
+
+template <size_t Limit> constexpr CTRE_FORCE_INLINE bool less_than([[maybe_unused]] size_t i) noexcept {
+	if constexpr (Limit == 0) {
+		// infinite
+		return false;
+	} else {
+		return i < Limit;
+	}
+}
+
+constexpr bool is_bidirectional(const std::bidirectional_iterator_tag &) { return true; }
+constexpr bool is_bidirectional(...) { return false; }
+
+// sink for making the errors shorter
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator> 
+constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R, ...) noexcept {
+	return not_matched;
+}
+
+// if we found "accept" object on stack => ACCEPT
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator> 
+constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R captures, ctll::list<accept>) noexcept {
+	return captures.matched();
+}
+
+// if we found "reject" object on stack => REJECT
+template <typename R, typename... Rest, typename BeginIterator, typename Iterator, typename EndIterator> 
+constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R, ctll::list<reject, Rest...>) noexcept {
+	return not_matched;
+}
+
+// mark start of outer capture
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+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 {
+	return evaluate(begin, current, last, f, captures.set_start_mark(current), ctll::list<Tail...>());
+}
+
+// mark end of outer capture
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+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 {
+	return evaluate(begin, current, last, f, captures.set_end_mark(current), ctll::list<Tail...>());
+}
+
+// mark end of cycle
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+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 {
+	if (cannot_be_empty_match(f)) {
+		return not_matched;
+	}
+	
+	return captures.set_end_mark(current).matched();
+}
+
+// matching everything which behave as a one character matcher
+
+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>())>)>> 
+constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<CharacterLike, Tail...>) noexcept {
+	if (current == last) return not_matched;
+	if (!CharacterLike::match_char(*current, f)) return not_matched;
+	
+	return evaluate(begin, ++current, last, consumed_something(f), captures, ctll::list<Tail...>());
+}
+
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<any, Tail...>) noexcept {
+	if (current == last) return not_matched;
+	
+	if (multiline_mode(f)) {
+		// TODO add support for different line ending and unicode (in a future unicode mode)
+		if (*current == '\n') return not_matched;
+	}
+	return evaluate(begin, ++current, last, consumed_something(f), captures, ctll::list<Tail...>());
+}
+
+// matching strings in patterns
+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) {
+	return ((current != last && character<String>::match_char(*current++, f)) && ... && true);
+}
+
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, auto... String, typename... Tail> 
+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 {
+	if (!match_string<String...>(current, last, f)) {
+		return not_matched;
+	}
+
+	return evaluate(begin, current, last, consumed_something(f, sizeof...(String) > 0), captures, ctll::list<Tail...>());
+}
+
+// matching select in patterns
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename HeadOptions, typename... TailOptions, typename... Tail> 
+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 {
+	if (auto r = evaluate(begin, current, last, f, captures, ctll::list<HeadOptions, Tail...>())) {
+		return r;
+	} else {
+		return evaluate(begin, current, last, f, captures, ctll::list<select<TailOptions...>, Tail...>());
+	}
+}
+
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R, ctll::list<select<>, Tail...>) noexcept {
+	// no previous option was matched => REJECT
+	return not_matched;
+}
+
+// matching sequence in patterns
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename HeadContent, typename... TailContent, typename... Tail> 
+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 {
+	if constexpr (sizeof...(TailContent) > 0) {
+		return evaluate(begin, current, last, f, captures, ctll::list<HeadContent, sequence<TailContent...>, Tail...>());
+	} else {
+		return evaluate(begin, current, last, f, captures, ctll::list<HeadContent, Tail...>());
+	}
+}
+
+// matching empty in patterns
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<empty, Tail...>) noexcept {
+	return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+}
+
+// matching asserts
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+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 {
+	if (begin != current) {
+		return not_matched;
+	}
+	return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+}
+
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+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 {
+	if (last != current) {
+		return not_matched;
+	}
+	return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+}
+
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+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 {
+	if (multiline_mode(f)) {
+		if (last == current) {
+			return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+		} else if (*current == '\n' && std::next(current) == last) {
+			return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+		} else {
+			return not_matched;
+		}
+	} else {
+		if (last != current) {
+			return not_matched;
+		}
+		return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+	}
+}
+
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+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 {
+	if (multiline_mode(f)) {
+		if (begin == current) {
+			return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+		} else if (*std::prev(current) == '\n') {
+			return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+		} else {
+			return not_matched;
+		}
+	} else {
+		if (begin != current) {
+			return not_matched;
+		}
+		return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+	}
+}
+
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+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 {
+	if (multiline_mode(f)) {
+		if (last == current) {
+			return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+		} else if (*current == '\n') {
+			return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+		} else {
+			return not_matched;
+		}
+	}
+	
+	// TODO properly match line end
+	if (last != current) {
+		return not_matched;
+	}
+	return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+}
+
+// matching boundary
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename CharacterLike, typename... Tail> 
+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 {
+	
+	// reason why I need bidirectional iterators or some clever hack
+	bool before = false;
+	bool after = false;
+	
+	static_assert(is_bidirectional(typename std::iterator_traits<Iterator>::iterator_category{}), "To use boundary in regex you need to provide bidirectional iterator or range.");
+	
+	if (last != current) {
+		after = CharacterLike::match_char(*current, f);
+	}
+	if (begin != current) {
+		before = CharacterLike::match_char(*std::prev(current), f);
+	}
+	
+	if (before == after) return not_matched;
+	
+	return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+}
+
+// matching not_boundary
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename CharacterLike, typename... Tail> 
+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 {
+	
+	// reason why I need bidirectional iterators or some clever hack
+	bool before = false;
+	bool after = false;
+	
+	static_assert(is_bidirectional(typename std::iterator_traits<Iterator>::iterator_category{}), "To use boundary in regex you need to provide bidirectional iterator or range.");
+	
+	if (last != current) {
+		after = CharacterLike::match_char(*current, f);
+	}
+	if (begin != current) {
+		before = CharacterLike::match_char(*std::prev(current), f);
+	}
+	
+	if (before != after) return not_matched;
+	
+	return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+}
+
+// lazy repeat
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail> 
+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 {
+
+	if constexpr (B != 0 && A > B) {
+		return not_matched;
+	} else {
+		const Iterator backup_current = current;
+	
+		size_t i{0};
+	
+		while (less_than<A>(i)) {
+			auto outer_result = evaluate(begin, current, last, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());
+		
+			if (!outer_result) return not_matched;
+		
+			captures = outer_result.unmatch();
+			current = outer_result.get_end_position();
+		
+			++i;
+		}
+	
+		if (auto outer_result = evaluate(begin, current, last, consumed_something(f, backup_current != current), captures, ctll::list<Tail...>())) {
+			return outer_result;
+		}
+	
+		while (less_than_or_infinite<B>(i)) {
+			auto inner_result = evaluate(begin, current, last, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());
+		
+			if (!inner_result) return not_matched;
+		
+			auto outer_result = evaluate(begin, inner_result.get_end_position(), last, consumed_something(f), inner_result.unmatch(), ctll::list<Tail...>());
+		
+			if (outer_result) {
+				return outer_result;
+			}
+		
+			captures = inner_result.unmatch();
+			current = inner_result.get_end_position();
+		
+			++i;
+		}
+	
+		// rest of regex
+		return evaluate(begin, current, last, consumed_something(f), captures, ctll::list<Tail...>());
+	}
+}
+
+// possessive repeat
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail> 
+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 {
+
+	if constexpr ((B != 0) && (A > B)) {
+		return not_matched;
+	} else {
+		const auto backup_current = current;
+
+		for (size_t i{0}; less_than_or_infinite<B>(i); ++i) {
+			// try as many of inner as possible and then try outer once
+			auto inner_result = evaluate(begin, current, last, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());
+		
+			if (!inner_result) {
+				if (!less_than<A>(i)) break;
+				return not_matched;
+			}
+		
+			captures = inner_result.unmatch();
+			current = inner_result.get_end_position();
+		}
+	
+		return evaluate(begin, current, last, consumed_something(f, backup_current != current), captures, ctll::list<Tail...>());
+	}
+}
+
+// (gready) repeat
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail> 
+#ifdef CTRE_MSVC_GREEDY_WORKAROUND
+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 {
+#else
+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 {
+#endif
+	if (less_than_or_infinite<B>(i)) {
+		 
+		// a*ab
+		// aab
+		
+		if (auto inner_result = evaluate(begin, current, last, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>())) {
+			// TODO MSVC issue:
+			// if I uncomment this return it will not fail in constexpr (but the matching result will not be correct)
+			//  return inner_result
+			// I tried to add all constructors to R but without any success
+			auto tmp_current = current;
+			tmp_current = inner_result.get_end_position();
+			#ifdef CTRE_MSVC_GREEDY_WORKAROUND
+			evaluate_recursive(result, i+1, begin, tmp_current, last, f, inner_result.unmatch(), stack);
+			if (result) {
+				return;
+			}
+			#else
+			if (auto rec_result = evaluate_recursive(i+1, begin, tmp_current, last, f, inner_result.unmatch(), stack)) {
+				return rec_result;
+			}
+			#endif
+		}
+	}
+	#ifdef CTRE_MSVC_GREEDY_WORKAROUND
+	result = evaluate(begin, current, last, consumed_something(f), captures, ctll::list<Tail...>());
+	#else
+	return evaluate(begin, current, last, consumed_something(f), captures, ctll::list<Tail...>());
+	#endif
+}	
+
+// (greedy) repeat 
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail> 
+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) {
+
+	if constexpr ((B != 0) && (A > B)) {
+		return not_matched;
+	}
+
+#ifndef CTRE_DISABLE_GREEDY_OPT
+	else if constexpr (!collides(calculate_first(Content{}...), calculate_first(Tail{}...))) {
+		return evaluate(begin, current, last, f, captures, ctll::list<possessive_repeat<A,B,Content...>, Tail...>());
+	}
+#endif
+	else {
+		// A..B
+		size_t i{0};
+		while (less_than<A>(i)) {
+			auto inner_result = evaluate(begin, current, last, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());
+		
+			if (!inner_result) return not_matched;
+		
+			captures = inner_result.unmatch();
+			current = inner_result.get_end_position();
+		
+			++i;
+		}
+	
+#ifdef CTRE_MSVC_GREEDY_WORKAROUND
+		R result;
+		evaluate_recursive(result, i, begin, current, last, f, captures, stack);
+		return result;
+#else
+		return evaluate_recursive(i, begin, current, last, f, captures, stack);
+#endif
+	}
+
+}
+
+// capture (numeric ID)
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t Id, typename... Content, typename... Tail> 
+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 {
+	return evaluate(begin, current, last, f, captures.template start_capture<Id>(current), ctll::list<sequence<Content...>, numeric_mark<Id>, Tail...>());
+}
+
+// capture end mark (numeric and string ID)
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t Id, typename... Tail> 
+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 {
+	return evaluate(begin, current, last, f, captures.template end_capture<Id>(current), ctll::list<Tail...>());
+}
+
+// capture (string ID)
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, size_t Id, typename Name, typename... Content, typename... Tail> 
+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 {
+	return evaluate(begin, current, last, f, captures.template start_capture<Id>(current), ctll::list<sequence<Content...>, numeric_mark<Id>, Tail...>());
+}
+
+// backreference support (match agains content of iterators)
+template <typename Iterator> struct string_match {
+	Iterator position;
+	bool match;
+};
+
+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 {
+	while (last != current && range_end != range_current) {
+		if (*current == *range_current) {
+			current++;
+			range_current++;
+		} else {
+			return {current, false};
+		}
+	}
+	return {current, range_current == range_end};
+}
+
+// backreference with name
+template <typename R, typename Id, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+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 {
+	
+	if (const auto ref = captures.template get<Id>()) {
+		if (auto result = match_against_range(current, last, ref.begin(), ref.end(), f); result.match) {
+			return evaluate(begin, result.position, last, consumed_something(f, ref.begin() != ref.end()), captures, ctll::list<Tail...>());
+		}
+	}
+	return not_matched;
+}
+
+// backreference
+template <typename R, size_t Id, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+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 {
+	
+	if (const auto ref = captures.template get<Id>()) {
+		if (auto result = match_against_range(current, last, ref.begin(), ref.end(), f); result.match) {
+			return evaluate(begin, result.position, last, consumed_something(f, ref.begin() != ref.end()), captures, ctll::list<Tail...>());
+		}
+	}
+	return not_matched;
+}
+
+// end of lookahead
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R captures, ctll::list<end_lookahead_mark>) noexcept {
+	// TODO check interaction with non-empty flag
+	return captures.matched();
+}
+
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Tail> 
+constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator, Iterator, const EndIterator, flags, R captures, ctll::list<end_lookbehind_mark>) noexcept {
+	// TODO check interaction with non-empty flag
+	return captures.matched();
+}
+
+// lookahead positive
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Content, typename... Tail> 
+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 {
+	
+	if (auto lookahead_result = evaluate(begin, current, last, f, captures, ctll::list<sequence<Content...>, end_lookahead_mark>())) {
+		captures = lookahead_result.unmatch();
+		return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+	} else {
+		return not_matched;
+	}
+}
+
+// lookahead negative
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Content, typename... Tail> 
+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 {
+	
+	if (auto lookahead_result = evaluate(begin, current, last, f, captures, ctll::list<sequence<Content...>, end_lookahead_mark>())) {
+		return not_matched;
+	} else {
+		return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+	}
+}
+
+// lookbehind positive
+constexpr bool is_at_least_bidirectional(std::input_iterator_tag) {
+	return false;
+}
+
+constexpr bool is_at_least_bidirectional(std::bidirectional_iterator_tag) {
+	return true;
+}
+
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Content, typename... Tail> 
+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 {
+	static_assert(is_at_least_bidirectional(typename std::iterator_traits<Iterator>::iterator_category{}), "to use lookbehind you must provide bi-directional iterator");
+	
+	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>())) {
+		captures = lookbehind_result.unmatch();
+		return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+	} else {
+		return not_matched;
+	}
+}
+
+// lookbehind negative
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Content, typename... Tail> 
+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 {
+	static_assert(is_at_least_bidirectional(typename std::iterator_traits<Iterator>::iterator_category{}), "to use negative lookbehind you must provide bi-directional iterator");
+	
+	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>())) {
+		return not_matched;
+	} else {
+		return evaluate(begin, current, last, f, captures, ctll::list<Tail...>());
+	}
+}
+
+template <typename...> constexpr auto dependent_false = false;
+
+// atomic_group<...> is just transformation to possessive_repeat<1,1,...>
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename... Content, typename... Tail> 
+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 {
+	return evaluate(begin, current, last, f, captures, ctll::list<possessive_repeat<1,1,Content...>, Tail...>{});
+}
+
+// switching modes
+template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename Mode, typename... Tail> 
+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 {
+	return evaluate(begin, current, last, f + Mode{}, captures, ctll::list<Tail...>());
+}
+
+}
+
+#endif
+
+#ifndef CTRE__WRAPPER__HPP
+#define CTRE__WRAPPER__HPP
+
+#ifndef CTRE_V2__CTRE__RANGE__HPP
+#define CTRE_V2__CTRE__RANGE__HPP
+
+#ifndef CTRE_V2__CTRE__ITERATOR__HPP
+#define CTRE_V2__CTRE__ITERATOR__HPP
+
+#ifndef CTRE_IN_A_MODULE
+#include <cstddef>
+#endif
+
+namespace ctre {
+
+// TODO make proper iterator traits here
+
+struct regex_end_iterator {
+	constexpr regex_end_iterator() noexcept { }
+};
+
+template <typename BeginIterator, typename EndIterator, typename RE, typename ResultIterator = BeginIterator> struct regex_iterator {
+	using value_type = decltype(RE::template exec_with_result_iterator<ResultIterator>(std::declval<BeginIterator>(), std::declval<EndIterator>()));
+	using iterator_category = std::forward_iterator_tag;
+	using pointer = void;
+	using reference = const value_type &;
+	using difference_type = int;
+	
+	BeginIterator orig_begin{};
+	BeginIterator current{};
+	EndIterator end{};
+	value_type current_match{};
+	
+	constexpr CTRE_FORCE_INLINE regex_iterator() noexcept = default;
+	constexpr CTRE_FORCE_INLINE regex_iterator(const regex_iterator &) noexcept = default;
+	constexpr CTRE_FORCE_INLINE regex_iterator(regex_iterator &&) noexcept = default;
+
+	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)} {
+		if (current_match) {
+			current = current_match.template get<0>().end();
+		}
+	}
+	
+	constexpr CTRE_FORCE_INLINE regex_iterator & operator=(const regex_iterator &) noexcept = default;
+	constexpr CTRE_FORCE_INLINE regex_iterator & operator=(regex_iterator &&) noexcept = default;
+	
+	constexpr CTRE_FORCE_INLINE const value_type & operator*() const noexcept {
+		return current_match;
+	}
+	constexpr CTRE_FORCE_INLINE regex_iterator & operator++() noexcept {
+		if (current == end) {
+			current_match = decltype(current_match){};
+			return *this;
+		}
+		
+		current_match = RE::template exec_with_result_iterator<ResultIterator>(orig_begin, current, end);
+		
+		if (current_match) {
+			current = current_match.template get<0>().end();
+		}
+		return *this;
+	}
+	constexpr CTRE_FORCE_INLINE regex_iterator operator++(int) noexcept {
+		auto previous = *this;
+		this->operator++();
+		return previous;
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator==(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
+		return left.current == right.current;
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator!=(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
+		return !(left.current == right.current);
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator<(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
+		return left.current < right.current;
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator>(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
+		return left.current > right.current;
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator<=(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
+		return left.current <= right.current;
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator>=(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
+		return left.current >= right.current;
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator==(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, regex_end_iterator) noexcept {
+		return !bool(left.current_match);
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator==(regex_end_iterator, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
+		return !bool(right.current_match);
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator!=(const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, regex_end_iterator) noexcept {
+		return bool(left.current_match);
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator!=(regex_end_iterator, const regex_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
+		return bool(right.current_match);
+	}
+};
+
+template <typename BeginIterator, typename EndIterator, typename RE, typename ResultIterator = BeginIterator> struct regex_split_iterator {
+	using value_type = decltype(RE::template exec_with_result_iterator<ResultIterator>(std::declval<BeginIterator>(), std::declval<EndIterator>()));
+	using iterator_category = std::forward_iterator_tag;
+	using pointer = void;
+	using reference = const value_type &;
+	using difference_type = int;
+
+	BeginIterator orig_begin{};
+	BeginIterator current{};
+	EndIterator end{};
+	value_type current_match{};
+	bool last_match{false};
+
+	constexpr CTRE_FORCE_INLINE void modify_match() {
+		auto tmp = current_match.template get<0>().end();
+		current_match.set_end_mark(current_match.template get<0>().begin());
+		current_match.set_start_mark(current);
+		current = tmp;
+	}
+	
+	constexpr CTRE_FORCE_INLINE void match_rest() {
+		// the end is there set by search_method
+		current_match.set_start_mark(current);
+		current_match.matched();
+		current = current_match.template get<0>().end();
+		last_match = true;
+	}
+
+	constexpr CTRE_FORCE_INLINE regex_split_iterator() noexcept = default;
+	constexpr CTRE_FORCE_INLINE regex_split_iterator(const regex_split_iterator &) noexcept = default;
+	constexpr CTRE_FORCE_INLINE regex_split_iterator(regex_split_iterator &&) noexcept = default;
+
+	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)} {
+		if (current_match) {
+			modify_match();
+		} else {
+			match_rest();
+		}
+	}
+	
+	constexpr CTRE_FORCE_INLINE regex_split_iterator & operator=(const regex_split_iterator &) noexcept = default;
+	constexpr CTRE_FORCE_INLINE regex_split_iterator & operator=(regex_split_iterator &&) noexcept = default;
+	
+	constexpr CTRE_FORCE_INLINE const value_type & operator*() const noexcept {
+		return current_match;
+	}
+	constexpr CTRE_FORCE_INLINE regex_split_iterator & operator++() noexcept {
+		if (current == end && last_match) {
+			current_match = decltype(current_match){};
+			return *this;
+		}
+	
+		current_match = RE::template exec_with_result_iterator<ResultIterator>(orig_begin, current, end);
+	
+		if (current_match) {
+			modify_match();
+		} else {
+			match_rest();
+		}
+		return *this;
+	}
+	constexpr CTRE_FORCE_INLINE regex_split_iterator operator++(int) noexcept {
+		auto previous = *this;
+		this->operator++();
+		return previous;
+	}
+	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 {
+		return left.current == right.current;
+	}
+	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 {
+		return !(left.current == right.current);
+	}
+	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 {
+		return left.current < right.current;
+	}
+	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 {
+		return left.current > right.current;
+	}
+	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 {
+		return left.current <= right.current;
+	}
+	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 {
+		return left.current >= right.current;
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator==(const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, regex_end_iterator) noexcept {
+		return !bool(left.current_match);
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator==(regex_end_iterator, const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
+		return !bool(right.current_match);
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator!=(const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & left, regex_end_iterator) noexcept {
+		return bool(left.current_match);
+	}
+	friend constexpr CTRE_FORCE_INLINE bool operator!=(regex_end_iterator, const regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator> & right) noexcept {
+		return bool(right.current_match);
+	}
+};
+
+} // ctre
+
+#endif
+
+namespace ctre {
+
+template <typename> constexpr bool is_range = false;
+
+template <typename BeginIterator, typename EndIterator, typename RE, typename ResultIterator = BeginIterator> struct regex_range {
+	BeginIterator _begin;
+	EndIterator _end;
+	
+	constexpr CTRE_FORCE_INLINE regex_range(BeginIterator begin, EndIterator end) noexcept: _begin{begin}, _end{end} { }
+	
+	constexpr CTRE_FORCE_INLINE auto begin() const noexcept {
+		return regex_iterator<BeginIterator, EndIterator, RE, ResultIterator>(_begin, _end);
+	}
+	constexpr CTRE_FORCE_INLINE auto end() const noexcept {
+		return regex_end_iterator{};
+	}
+};
+
+template <typename... Ts> constexpr bool is_range<regex_range<Ts...>> = true;
+
+template <typename BeginIterator, typename EndIterator, typename RE, typename ResultIterator = BeginIterator> struct regex_split_range {
+	BeginIterator _begin;
+	EndIterator _end;
+	
+	constexpr CTRE_FORCE_INLINE regex_split_range(BeginIterator begin, EndIterator end) noexcept: _begin{begin}, _end{end} { }
+	
+	constexpr CTRE_FORCE_INLINE auto begin() const noexcept {
+		return regex_split_iterator<BeginIterator, EndIterator, RE, ResultIterator>(_begin, _end);
+	}
+	constexpr CTRE_FORCE_INLINE auto end() const noexcept {
+		return regex_end_iterator{};
+	}
+};
+
+template <typename... Ts> constexpr bool is_range<regex_split_range<Ts...>> = true;
+
+template <typename Range, typename RE> struct multi_subject_range {
+	struct end_iterator { };
+	
+	using first_type = decltype(std::declval<Range>().begin());
+	using last_type = decltype(std::declval<Range>().end());
+	
+	struct iterator {
+		using value_type = decltype(RE::exec(std::declval<typename std::iterator_traits<first_type>::value_type>()));
+		using iterator_category = std::forward_iterator_tag;
+		using reference = const value_type &;
+		using pointer = const value_type *;
+		using difference_type = int;
+		
+		first_type first{};
+		last_type last{};
+		value_type current_result{};
+		
+		constexpr CTRE_FORCE_INLINE iterator() noexcept = default;
+		constexpr CTRE_FORCE_INLINE iterator(first_type f, last_type l) noexcept: first{f}, last{l}, current_result{find_first()} { }
+		
+		constexpr CTRE_FORCE_INLINE value_type find_first() noexcept {
+			while (first != last) {
+				if (auto res = RE::exec(*first)) return res;
+				else ++first;
+			}
+			return {};
+		}
+		
+		constexpr CTRE_FORCE_INLINE reference operator*() const noexcept {
+			return current_result;
+		}
+		
+		constexpr CTRE_FORCE_INLINE pointer operator->() const noexcept {
+			return &current_result;
+		}
+		
+		constexpr CTRE_FORCE_INLINE iterator & operator++() noexcept {
+			++first;
+			current_result = find_first();
+			return *this;
+		}
+		constexpr CTRE_FORCE_INLINE iterator operator++(int) noexcept {
+			auto previous = *this;
+			this->operator++();
+			return previous;
+		}
+		
+		friend constexpr CTRE_FORCE_INLINE bool operator==(const iterator & left, const iterator & right) noexcept {
+			return left.first == right.first;
+		}
+		friend constexpr CTRE_FORCE_INLINE bool operator!=(const iterator & left, const iterator & right) noexcept {
+			return !(left.first == right.first);
+		}
+		friend constexpr CTRE_FORCE_INLINE bool operator<(const iterator & left, const iterator & right) noexcept {
+			return left.first < right.first;
+		}
+		friend constexpr CTRE_FORCE_INLINE bool operator>(const iterator & left, const iterator & right) noexcept {
+			return left.first > right.first;
+		}
+		friend constexpr CTRE_FORCE_INLINE bool operator<=(const iterator & left, const iterator & right) noexcept {
+			return left.first <= right.first;
+		}
+		friend constexpr CTRE_FORCE_INLINE bool operator>=(const iterator & left, const iterator & right) noexcept {
+			return left.first >= right.first;
+		}
+		friend constexpr CTRE_FORCE_INLINE bool operator==(const iterator & left, end_iterator) noexcept {
+			return left.first == left.last;
+		}
+		friend constexpr CTRE_FORCE_INLINE bool operator==(end_iterator, const iterator & right) noexcept {
+			return right.first == right.last;
+		}
+		friend constexpr CTRE_FORCE_INLINE bool operator!=(const iterator & left, end_iterator) noexcept {
+			return left.first != left.last;
+		}
+		friend constexpr CTRE_FORCE_INLINE bool operator!=(end_iterator, const iterator & right) noexcept {
+			return right.first == right.last;
+		}
+	};
+	
+	Range range{};
+	
+	constexpr CTRE_FORCE_INLINE multi_subject_range() noexcept = default;
+	constexpr CTRE_FORCE_INLINE multi_subject_range(Range r) noexcept: range{r} { }
+	
+	constexpr CTRE_FORCE_INLINE auto begin() const noexcept {
+		return iterator{range.begin(), range.end()};
+	}
+	constexpr CTRE_FORCE_INLINE auto end() const noexcept {
+		return end_iterator{};
+	}
+};
+
+// this is not regex range!
+template <typename... Ts> constexpr bool is_range<multi_subject_range<Ts...>> = true;
+
+}
+
+#if defined __cpp_lib_ranges && __cpp_lib_ranges >= 201911
+namespace std::ranges {
+
+	template <typename... Ts> inline constexpr bool enable_borrowed_range<::ctre::regex_range<Ts...>> = true;
+	template <typename... Ts> inline constexpr bool enable_borrowed_range<::ctre::regex_split_range<Ts...>> = true;
+	template <typename Range, typename RE> inline constexpr bool enable_borrowed_range<::ctre::multi_subject_range<Range, RE>> = enable_borrowed_range<Range>;
+	template <typename Range, typename RE> inline constexpr bool enable_view<::ctre::multi_subject_range<Range, RE>> = true;
+
+}
+#endif 
+
+#endif
+
+#ifndef CTRE_IN_A_MODULE
+#include <string_view>
+#endif
+
+namespace ctre {
+
+CTRE_EXPORT template <typename RE, typename Method = void, typename Modifier = singleline> struct regular_expression;
+
+struct zero_terminated_string_end_iterator {
+	// this is here only because I want to support std::make_reverse_iterator
+	using self_type = zero_terminated_string_end_iterator;
+	using value_type = char;
+	using reference = char &;
+	using pointer = const char *;
+	using iterator_category = std::bidirectional_iterator_tag;
+	using difference_type = int;
+
+	// it's just sentinel it won't be ever called
+	auto operator++() noexcept -> self_type &;
+	auto operator++(int) noexcept -> self_type;
+	auto operator--() noexcept -> self_type &;
+	auto operator--(int) noexcept -> self_type;
+	friend auto operator==(self_type, self_type) noexcept -> bool;
+	auto operator*() noexcept -> reference;
+
+	constexpr CTRE_FORCE_INLINE friend bool operator==(const char * ptr, zero_terminated_string_end_iterator) noexcept {
+		return *ptr == '\0';
+	}
+	constexpr CTRE_FORCE_INLINE friend bool operator==(const wchar_t * ptr, zero_terminated_string_end_iterator) noexcept {
+		return *ptr == 0;
+	}
+	constexpr CTRE_FORCE_INLINE friend bool operator!=(const char * ptr, zero_terminated_string_end_iterator) noexcept {
+		return *ptr != '\0';
+	}
+	constexpr CTRE_FORCE_INLINE friend bool operator!=(const wchar_t * ptr, zero_terminated_string_end_iterator) noexcept {
+		return *ptr != 0;
+	}
+	constexpr CTRE_FORCE_INLINE friend bool operator==(zero_terminated_string_end_iterator, const char * ptr) noexcept {
+		return *ptr == '\0';
+	}
+	constexpr CTRE_FORCE_INLINE friend bool operator==(zero_terminated_string_end_iterator, const wchar_t * ptr) noexcept {
+		return *ptr == 0;
+	}
+	constexpr CTRE_FORCE_INLINE friend bool operator!=(zero_terminated_string_end_iterator, const char * ptr) noexcept {
+		return *ptr != '\0';
+	}
+	constexpr CTRE_FORCE_INLINE friend bool operator!=(zero_terminated_string_end_iterator, const wchar_t * ptr) noexcept {
+		return *ptr != 0;
+	}
+};
+
+template <typename T> class RangeLikeType {
+	template <typename Y> static auto test(Y *) -> decltype(std::declval<const Y &>().begin(), std::declval<const Y &>().end(), std::true_type());
+	template <typename> static auto test(...) -> std::false_type;
+
+public:
+	static constexpr bool value = decltype(test<std::remove_reference_t<std::remove_const_t<T>>>(nullptr))::value;
+};
+
+struct match_method {
+	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 {
+		using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
+
+		return evaluate(orig_begin, begin, end, Modifier{}, return_type<result_iterator, RE>{}, ctll::list<start_mark, RE, assert_subject_end, end_mark, accept>());
+	}
+
+	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 {
+		return exec<Modifier, ResultIterator>(begin, begin, end, RE{});
+	}
+};
+
+struct search_method {
+	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 {
+		using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
+
+		constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list<RE>{});
+
+		auto it = begin;
+
+		for (; end != it && !fixed; ++it) {
+			if (auto out = evaluate(orig_begin, it, end, Modifier{}, return_type<result_iterator, RE>{}, ctll::list<start_mark, RE, end_mark, accept>())) {
+				return out;
+			}
+		}
+
+		// in case the RE is empty or fixed
+		auto out = evaluate(orig_begin, it, end, Modifier{}, return_type<result_iterator, RE>{}, ctll::list<start_mark, RE, end_mark, accept>());
+
+		// ALERT: ugly hack
+		// propagate end even if it didn't match (this is needed for split function)
+		if (!out) out.set_end_mark(it);
+		return out;
+	}
+
+	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 {
+		return exec<Modifier, ResultIterator>(begin, begin, end, RE{});
+	}
+};
+
+struct starts_with_method {
+	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 {
+		using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
+		return evaluate(orig_begin, begin, end, Modifier{}, return_type<result_iterator, RE>{}, ctll::list<start_mark, RE, end_mark, accept>());
+	}
+
+	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 {
+		return exec<Modifier, ResultIterator>(begin, begin, end, RE{});
+	}
+};
+
+// wrapper which calls search on input
+struct range_method {
+	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 {
+		using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
+		using wrapped_regex = regular_expression<RE, search_method, Modifier>;
+
+		return regex_range<IteratorBegin, IteratorEnd, wrapped_regex, result_iterator>(begin, end);
+	}
+};
+
+struct tokenize_method {
+	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 {
+		using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
+		using wrapped_regex = regular_expression<RE, starts_with_method, Modifier>;
+
+		return regex_range<IteratorBegin, IteratorEnd, wrapped_regex, result_iterator>(begin, end);
+	}
+};
+
+struct split_method {
+	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 {
+		using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
+		using wrapped_regex = regular_expression<RE, search_method, Modifier>;
+
+		return regex_split_range<IteratorBegin, IteratorEnd, wrapped_regex, result_iterator>(begin, end);
+	}
+};
+
+struct iterator_method {
+	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 {
+		using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
+		using wrapped_regex = regular_expression<RE, search_method, Modifier>;
+
+		return regex_iterator<IteratorBegin, IteratorEnd, wrapped_regex, result_iterator>(begin, end);
+	}
+	constexpr CTRE_FORCE_INLINE static auto exec() noexcept {
+		return regex_end_iterator{};
+	}
+};
+
+CTRE_EXPORT template <typename RE, typename Method, typename Modifier> struct regular_expression {
+	constexpr CTRE_FORCE_INLINE regular_expression() noexcept { }
+	constexpr CTRE_FORCE_INLINE regular_expression(RE) noexcept { }
+
+	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 {
+		return Method::template exec<Modifier, ResultIterator>(orig_begin, begin, end, RE{});
+	}
+	template <typename ResultIterator, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec_with_result_iterator(IteratorBegin begin, IteratorEnd end) noexcept {
+		return Method::template exec<Modifier, ResultIterator>(begin, end, RE{});
+	}
+	template <typename Range> constexpr CTRE_FORCE_INLINE static auto multi_exec(Range && range) noexcept {
+		return multi_subject_range<Range, regular_expression>{std::forward<Range>(range)};
+	}
+	constexpr CTRE_FORCE_INLINE static auto exec() noexcept {
+		return Method::exec();
+	}
+	template <typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin begin, IteratorEnd end) noexcept {
+		return Method::template exec<Modifier>(begin, end, RE{});
+	}
+	static constexpr CTRE_FORCE_INLINE auto exec(const char * s) noexcept {
+		return Method::template exec<Modifier>(s, zero_terminated_string_end_iterator(), RE{});
+	}
+	static constexpr CTRE_FORCE_INLINE auto exec(const wchar_t * s) noexcept {
+		return Method::template exec<Modifier>(s, zero_terminated_string_end_iterator(), RE{});
+	}
+	static constexpr CTRE_FORCE_INLINE auto exec(std::string_view sv) noexcept {
+		return exec(sv.begin(), sv.end());
+	}
+	static constexpr CTRE_FORCE_INLINE auto exec(std::wstring_view sv) noexcept {
+		return exec(sv.begin(), sv.end());
+	}
+#ifdef CTRE_ENABLE_UTF8_RANGE
+	static constexpr CTRE_FORCE_INLINE auto exec(std::u8string_view sv) noexcept {
+		return exec_with_result_iterator<const char8_t *>(utf8_range(sv).begin(), utf8_range(sv).end());
+	}
+#endif
+	static constexpr CTRE_FORCE_INLINE auto exec(std::u16string_view sv) noexcept {
+		return exec(sv.begin(), sv.end());
+	}
+	static constexpr CTRE_FORCE_INLINE auto exec(std::u32string_view sv) noexcept {
+		return exec(sv.begin(), sv.end());
+	}
+	template <typename Range, typename = typename std::enable_if<RangeLikeType<Range>::value>::type> static constexpr CTRE_FORCE_INLINE auto exec(Range && range) noexcept {
+		return exec(std::begin(range), std::end(range));
+	}
+
+	// another api
+	template <typename... Args> CTRE_FORCE_INLINE constexpr auto operator()(Args &&... args) const noexcept {
+		return exec(std::forward<Args>(args)...);
+	}
+	// api for pattern matching
+	template <typename... Args> CTRE_FORCE_INLINE constexpr auto try_extract(Args &&... args) const noexcept {
+		return exec(std::forward<Args>(args)...);
+	}
+
+	// for compatibility with _ctre literal
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto match(Args &&... args) noexcept {
+		return regular_expression<RE, match_method, singleline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto search(Args &&... args) noexcept {
+		return regular_expression<RE, search_method, singleline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto starts_with(Args &&... args) noexcept {
+		return regular_expression<RE, starts_with_method, singleline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto range(Args &&... args) noexcept {
+		return regular_expression<RE, range_method, singleline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto split(Args &&... args) noexcept {
+		return regular_expression<RE, split_method, singleline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto tokenize(Args &&... args) noexcept {
+		return regular_expression<RE, tokenize_method, singleline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto iterator(Args &&... args) noexcept {
+		return regular_expression<RE, iterator_method, singleline>::exec(std::forward<Args>(args)...);
+	}
+
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_match(Args &&... args) noexcept {
+		return regular_expression<RE, match_method, multiline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_search(Args &&... args) noexcept {
+		return regular_expression<RE, search_method, multiline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_starts_with(Args &&... args) noexcept {
+		return regular_expression<RE, starts_with_method, multiline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_range(Args &&... args) noexcept {
+		return regular_expression<RE, range_method, multiline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_split(Args &&... args) noexcept {
+		return regular_expression<RE, split_method, multiline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_tokenize(Args &&... args) noexcept {
+		return regular_expression<RE, tokenize_method, multiline>::exec(std::forward<Args>(args)...);
+	}
+	template <typename... Args> static constexpr CTRE_FORCE_INLINE auto multiline_iterator(Args &&... args) noexcept {
+		return regular_expression<RE, iterator_method, multiline>::exec(std::forward<Args>(args)...);
+	}
+};
+
+// range style API support for tokenize/range/split operations
+template <typename Range, typename RE, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, range_method, Modifier> re) noexcept {
+	return re.exec(std::forward<Range>(range));
+}
+
+template <typename Range, typename RE, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, tokenize_method, Modifier> re) noexcept {
+	return re.exec(std::forward<Range>(range));
+}
+
+template <typename Range, typename RE, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, split_method, Modifier> re) noexcept {
+	return re.exec(std::forward<Range>(range));
+}
+
+template <typename Range, typename RE, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, iterator_method, Modifier> re) noexcept = delete;
+
+template <typename Range, typename RE, typename Method, typename Modifier> constexpr auto operator|(Range && range, regular_expression<RE, Method, Modifier> re) noexcept {
+	return re.multi_exec(std::forward<Range>(range));
+}
+
+// error reporting of problematic position in a regex
+template <size_t> struct problem_at_position; // do not define!
+
+template <> struct problem_at_position<~static_cast<size_t>(0)> {
+	constexpr operator bool() const noexcept {
+		return true;
+	}
+};
+
+#if CTRE_CNTTP_COMPILER_CHECK
+#define CTRE_REGEX_INPUT_TYPE ctll::fixed_string
+#define CTRE_REGEX_TEMPLATE_COPY_TYPE auto
+#else
+#define CTRE_REGEX_INPUT_TYPE const auto &
+#define CTRE_REGEX_TEMPLATE_COPY_TYPE const auto &
+#endif
+
+template <CTRE_REGEX_TEMPLATE_COPY_TYPE input> struct regex_builder {
+	static constexpr auto _input = input;
+	using result = typename ctll::parser<ctre::pcre, _input, ctre::pcre_actions>::template output<pcre_context<>>;
+
+	static constexpr auto n = result::is_correct ? ~static_cast<size_t>(0) : result::position;
+
+	static_assert(result::is_correct && problem_at_position<n>{}, "Regular Expression contains syntax error.");
+
+	using type = ctll::conditional<result::is_correct, decltype(ctll::front(typename result::output_type::stack_type())), ctll::list<reject>>;
+};
+
+// case-sensitive
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+CTRE_EXPORT constexpr auto sentinel = regex_end_iterator();
+
+// multiline
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+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...>>();
+
+CTRE_EXPORT constexpr auto multiline_sentinel = regex_end_iterator();
+
+} // namespace ctre
+
+#endif
+
+#ifndef __EDG__
+
+namespace ctre {
+
+// in C++17 (clang & gcc with gnu extension) we need translate character pack into ctll::fixed_string
+// in C++20 we have `class nontype template parameters`
+
+#if !CTRE_CNTTP_COMPILER_CHECK
+template <typename CharT, CharT... input> static inline constexpr auto _fixed_string_reference = ctll::fixed_string< sizeof...(input)>({input...});
+#endif	
+
+namespace literals {
+	
+// clang and GCC <9 supports LITERALS with packs
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template"
+#define CTRE_ENABLE_LITERALS
+#endif
+  
+#ifdef _MSC_VER
+#ifdef _MSVC_LANG
+#if _MSVC_LANG >= 202002L
+#define CTRE_ENABLE_LITERALS
+#endif
+#else
+#define CTRE_ENABLE_LITERALS
+#endif
+#endif
+
+#ifdef __INTEL_COMPILER
+// not enable literals
+#elif defined __GNUC__
+#if __GNUC__ < 9
+#define CTRE_ENABLE_LITERALS
+#elif __GNUC__ >= 10
+#if !CTRE_CNTTP_COMPILER_CHECK 
+// newer versions of GCC will give error when trying to use GNU extension
+#else
+#define CTRE_ENABLE_LITERALS
+#endif	
+#endif
+#endif
+
+#ifdef CTRE_ENABLE_LITERALS
+	
+// add this when we will have concepts
+// requires ctll::parser<ctre::pcre, _fixed_string_reference<CharT, charpack...>, ctre::pcre_actions>::template correct_with<pcre_context<>>
+
+#if !CTRE_CNTTP_COMPILER_CHECK
+template <typename CharT, CharT... charpack> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto operator""_ctre() noexcept {
+	constexpr auto & _input = _fixed_string_reference<CharT, charpack...>;
+#else
+template <ctll::fixed_string input> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto operator""_ctre() noexcept {
+	constexpr auto _input = input; // workaround for GCC 9 bug 88092
+#endif
+	using tmp = typename ctll::parser<ctre::pcre, _input, ctre::pcre_actions>::template output<pcre_context<>>;
+	static_assert(tmp(), "Regular Expression contains syntax error.");
+	if constexpr (tmp()) {
+		using re = decltype(front(typename tmp::output_type::stack_type()));
+		return ctre::regular_expression(re());
+	} else {
+		return ctre::regular_expression(reject());
+	}
+}
+
+// this will need to be fixed with C++20
+#if !CTRE_CNTTP_COMPILER_CHECK
+template <typename CharT, CharT... charpack> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto operator""_ctre_id() noexcept {
+	return id<charpack...>();
+}
+#endif
+
+#endif // CTRE_ENABLE_LITERALS
+
+}
+
+namespace test_literals {
+	
+#ifdef CTRE_ENABLE_LITERALS
+
+#if !CTRE_CNTTP_COMPILER_CHECK
+template <typename CharT, CharT... charpack> CTRE_FLATTEN constexpr inline auto operator""_ctre_test() noexcept {
+	constexpr auto & _input = _fixed_string_reference<CharT, charpack...>;
+#else
+template <ctll::fixed_string input> CTRE_FLATTEN constexpr inline auto operator""_ctre_test() noexcept {
+	constexpr auto _input = input; // workaround for GCC 9 bug 88092
+#endif
+	return ctll::parser<ctre::pcre, _input>::template correct_with<>;
+}
+
+#if !CTRE_CNTTP_COMPILER_CHECK
+template <typename CharT, CharT... charpack> CTRE_FLATTEN constexpr inline auto operator""_ctre_gen() noexcept {
+	constexpr auto & _input = _fixed_string_reference<CharT, charpack...>;
+#else
+template <ctll::fixed_string input> CTRE_FLATTEN constexpr inline auto operator""_ctre_gen() noexcept {
+	constexpr auto _input = input; // workaround for GCC 9 bug 88092
+#endif
+	using tmp = typename ctll::parser<ctre::pcre, _input, ctre::pcre_actions>::template output<pcre_context<>>;
+	static_assert(tmp(), "Regular Expression contains syntax error.");
+	return typename tmp::output_type::stack_type();
+}
+
+#if !CTRE_CNTTP_COMPILER_CHECK
+template <typename CharT, CharT... charpack> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto operator""_ctre_syntax() noexcept {
+	constexpr auto & _input = _fixed_string_reference<CharT, charpack...>;
+#else
+template <ctll::fixed_string input> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto operator""_ctre_syntax() noexcept {
+	constexpr auto _input = input; // workaround for GCC 9 bug 88092
+#endif
+	return ctll::parser<ctre::pcre, _input, ctre::pcre_actions>::template correct_with<pcre_context<>>;
+}
+
+#endif
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+} // literals
+
+} // ctre
+
+#endif
+
+#endif
+
+#ifndef CTRE_V2__CTRE__FUNCTIONS__HPP
+#define CTRE_V2__CTRE__FUNCTIONS__HPP
+
+namespace ctre {
+
+#if !CTRE_CNTTP_COMPILER_CHECK
+// avoiding CTAD limitation in C++17
+template <typename CharT, size_t N> class pattern: public ctll::fixed_string<N> {
+	using parent = ctll::fixed_string<N>;
+public:
+	constexpr pattern(const CharT (&input)[N]) noexcept: parent(input) { }
+};
+
+template <typename CharT, size_t N> pattern(const CharT (&)[N]) -> pattern<CharT, N>;
+
+// for better examples
+template <typename CharT, size_t N> class fixed_string: public ctll::fixed_string<N> {
+	using parent = ctll::fixed_string<N>;
+public:
+	constexpr fixed_string(const CharT (&input)[N]) noexcept: parent(input) { }
+};
+
+template <typename CharT, size_t N> fixed_string(const CharT (&)[N]) -> fixed_string<CharT, N>;
+#endif
+
+#if CTRE_CNTTP_COMPILER_CHECK
+template <ctll::fixed_string input, typename Modifier = void> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto re() noexcept {
+constexpr auto _input = input; // workaround for GCC 9 bug 88092
+#else
+template <auto & input, typename Modifier = void> CTRE_FLATTEN constexpr CTRE_FORCE_INLINE auto re() noexcept {	
+constexpr auto & _input = input; 
+#endif
+	
+	using tmp = typename ctll::parser<ctre::pcre, _input, ctre::pcre_actions>::template output<pcre_context<>>;
+	static_assert(tmp(), "Regular Expression contains syntax error.");
+	using regex = decltype(front(typename tmp::output_type::stack_type()));
+	return ctre::regular_expression<regex, Modifier, singleline>();
+}
+
+}
+
+#endif
+
+#ifndef CTRE_V2__CTRE__OPERATORS__HPP
+#define CTRE_V2__CTRE__OPERATORS__HPP
+
+template <typename A, typename B> constexpr auto operator|(ctre::regular_expression<A>, ctre::regular_expression<B>) -> ctre::regular_expression<ctre::select<A,B>> {
+	return {};
+}
+
+template <typename A, typename B> constexpr auto operator>>(ctre::regular_expression<A>, ctre::regular_expression<B>) -> ctre::regular_expression<ctre::sequence<A,B>> {
+	return {};
+}
+
+#endif
+
+#endif

commit 96dac7bb38b88abd8321ea2f33b3bba100ef21e3
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sat May 16 18:27:08 2026 +0800

    [gnc-filepath-utils.cpp] null check char* arguments

diff --git a/libgnucash/core-utils/gnc-filepath-utils.cpp b/libgnucash/core-utils/gnc-filepath-utils.cpp
index 4f4080b2db..fe3e31e5ee 100644
--- a/libgnucash/core-utils/gnc-filepath-utils.cpp
+++ b/libgnucash/core-utils/gnc-filepath-utils.cpp
@@ -1326,6 +1326,7 @@ backup_regex (".*[.](?:xac|gnucash)[.][0-9]{14}[.](?:xac|gnucash)$");
 
 gboolean gnc_filename_is_backup (const char *filename)
 {
+    g_return_val_if_fail (filename, FALSE);
     return std::regex_match (filename, backup_regex);
 }
 
@@ -1334,6 +1335,7 @@ datafile_regex (".*[.](?:xac|gnucash)$");
 
 gboolean gnc_filename_is_datafile (const char *filename)
 {
+    g_return_val_if_fail (filename, FALSE);
     return !gnc_filename_is_backup (filename) &&
         std::regex_match (filename, datafile_regex);
 }
diff --git a/libgnucash/core-utils/test/gtest-path-utilities.cpp b/libgnucash/core-utils/test/gtest-path-utilities.cpp
index 017252293b..873fecd531 100644
--- a/libgnucash/core-utils/test/gtest-path-utilities.cpp
+++ b/libgnucash/core-utils/test/gtest-path-utilities.cpp
@@ -141,10 +141,12 @@ TEST_F(PathTest, gnc_path_get_sysconfdir)
 
 TEST_F (PathTest, gnc_filename_is_backup)
 {
+    EXPECT_EQ (gnc_filename_is_backup (nullptr), false);
     EXPECT_EQ (gnc_filename_is_backup (""), false);
     EXPECT_EQ (gnc_filename_is_backup ("a.gnucash"), false);
     EXPECT_EQ (gnc_filename_is_backup ("a.gnucash.20201131010203.gnucash"), true);
 
+    EXPECT_EQ (gnc_filename_is_datafile (nullptr), false);
     EXPECT_EQ (gnc_filename_is_datafile (""), false);
     EXPECT_EQ (gnc_filename_is_datafile ("a.gnucash"), true);
     EXPECT_EQ (gnc_filename_is_datafile ("a.gnucash.20201131010203.gnucash"), false);



Summary of changes:
 CMakeLists.txt                                     |    1 +
 borrowed/CMakeLists.txt                            |    2 +
 borrowed/ctre/CMakeLists.txt                       |   13 +
 borrowed/ctre/LICENSE                              |  218 +
 borrowed/ctre/ctre.hpp                             | 5993 ++++++++++++++++++++
 libgnucash/core-utils/CMakeLists.txt               |    1 +
 libgnucash/core-utils/gnc-filepath-utils.cpp       |   13 +-
 libgnucash/core-utils/test/CMakeLists.txt          |    1 +
 .../core-utils/test/gtest-path-utilities.cpp       |    2 +
 9 files changed, 6238 insertions(+), 6 deletions(-)
 create mode 100644 borrowed/ctre/CMakeLists.txt
 create mode 100644 borrowed/ctre/LICENSE
 create mode 100644 borrowed/ctre/ctre.hpp



More information about the gnucash-changes mailing list