5798 lines
270 KiB
C++
5798 lines
270 KiB
C++
/*
|
|
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
|
|
|
|
#include <utility>
|
|
#include <cstddef>
|
|
#include <string_view>
|
|
#include <array>
|
|
#include <cstdint>
|
|
|
|
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{};
|
|
|
|
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) {
|
|
if ((i == (N-1)) && (input[i] == 0)) break;
|
|
length_value_t info = length_and_value_of_utf8_code_point(input[i]);
|
|
switch (info.length) {
|
|
case 6:
|
|
if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
|
|
[[fallthrough]];
|
|
case 5:
|
|
if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
|
|
[[fallthrough]];
|
|
case 4:
|
|
if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
|
|
[[fallthrough]];
|
|
case 3:
|
|
if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
|
|
[[fallthrough]];
|
|
case 2:
|
|
if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
|
|
[[fallthrough]];
|
|
case 1:
|
|
content[out++] = static_cast<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]);
|
|
if ((i == (N-1)) && (input[i] == 0)) break;
|
|
real_size++;
|
|
}
|
|
#endif
|
|
#if __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) {
|
|
if ((i == (N-1)) && (input[i] == 0)) break;
|
|
length_value_t info = length_and_value_of_utf8_code_point(input[i]);
|
|
switch (info.length) {
|
|
case 6:
|
|
if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
|
|
[[fallthrough]];
|
|
case 5:
|
|
if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
|
|
[[fallthrough]];
|
|
case 4:
|
|
if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
|
|
[[fallthrough]];
|
|
case 3:
|
|
if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
|
|
[[fallthrough]];
|
|
case 2:
|
|
if (++i < N) info.value = (info.value << 6) | value_of_trailing_utf8_code_point(input[i], correct_flag);
|
|
[[fallthrough]];
|
|
case 1:
|
|
content[out++] = static_cast<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 {
|
|
if ((i == (N-1)) && (input[i] == 0)) break;
|
|
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]);
|
|
if ((i == (N-1)) && (input[i] == 0)) break;
|
|
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
|
|
|
|
#ifndef CTLL__UTILITIES__HPP
|
|
#define CTLL__UTILITIES__HPP
|
|
|
|
#include <type_traits>
|
|
|
|
#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 {
|
|
|
|
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 inline 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 inline set(term<V>) noexcept;
|
|
#else
|
|
template <auto V, typename = std::enable_if_t<((Def == V) || ... || false)>> constexpr inline 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 inline neg_set(term<V>) noexcept;
|
|
#else
|
|
template <auto V, typename = std::enable_if_t<!((Def == V) || ... || false)>> constexpr inline 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
|
|
|
|
#include <limits>
|
|
|
|
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 c {};
|
|
struct class_named_name {};
|
|
struct content2 {};
|
|
struct content {};
|
|
struct content_in_capture {};
|
|
struct d {};
|
|
struct e {};
|
|
struct f {};
|
|
struct g {};
|
|
struct h {};
|
|
struct hexdec_repeat {};
|
|
struct i {};
|
|
struct j {};
|
|
struct k {};
|
|
struct l {};
|
|
struct m {};
|
|
struct mod {};
|
|
struct mode_switch2 {};
|
|
struct n {};
|
|
struct number2 {};
|
|
struct number {};
|
|
struct o {};
|
|
struct p {};
|
|
struct property_name2 {};
|
|
struct property_name {};
|
|
struct property_value2 {};
|
|
struct property_value {};
|
|
struct range {};
|
|
struct repeat {};
|
|
struct s {}; using _start = s;
|
|
struct set2a {};
|
|
struct set2b {};
|
|
struct string2 {};
|
|
|
|
// 'action' types:
|
|
struct class_digit: ctll::action {};
|
|
struct class_horizontal_space: ctll::action {};
|
|
struct class_named_alnum: ctll::action {};
|
|
struct class_named_alpha: ctll::action {};
|
|
struct class_named_ascii: ctll::action {};
|
|
struct class_named_blank: ctll::action {};
|
|
struct class_named_cntrl: ctll::action {};
|
|
struct class_named_digit: ctll::action {};
|
|
struct class_named_graph: ctll::action {};
|
|
struct class_named_lower: ctll::action {};
|
|
struct class_named_print: ctll::action {};
|
|
struct class_named_punct: ctll::action {};
|
|
struct class_named_space: ctll::action {};
|
|
struct class_named_upper: ctll::action {};
|
|
struct class_named_word: ctll::action {};
|
|
struct class_named_xdigit: ctll::action {};
|
|
struct class_non_horizontal_space: ctll::action {};
|
|
struct class_non_vertical_space: ctll::action {};
|
|
struct class_nondigit: ctll::action {};
|
|
struct class_nonnewline: ctll::action {};
|
|
struct class_nonspace: ctll::action {};
|
|
struct class_nonword: ctll::action {};
|
|
struct class_space: ctll::action {};
|
|
struct class_vertical_space: ctll::action {};
|
|
struct class_word: ctll::action {};
|
|
struct create_hexdec: ctll::action {};
|
|
struct create_number: ctll::action {};
|
|
struct finish_hexdec: ctll::action {};
|
|
struct look_finish: ctll::action {};
|
|
struct make_alternate: ctll::action {};
|
|
struct make_atomic: ctll::action {};
|
|
struct make_back_reference: ctll::action {};
|
|
struct make_capture: ctll::action {};
|
|
struct make_capture_with_name: ctll::action {};
|
|
struct make_lazy: ctll::action {};
|
|
struct make_optional: ctll::action {};
|
|
struct make_possessive: ctll::action {};
|
|
struct make_property: ctll::action {};
|
|
struct make_property_negative: ctll::action {};
|
|
struct make_range: ctll::action {};
|
|
struct make_relative_back_reference: ctll::action {};
|
|
struct make_sequence: ctll::action {};
|
|
struct mode_case_insensitive: ctll::action {};
|
|
struct mode_case_sensitive: ctll::action {};
|
|
struct mode_multiline: ctll::action {};
|
|
struct mode_singleline: ctll::action {};
|
|
struct negate_class_named: ctll::action {};
|
|
struct prepare_capture: ctll::action {};
|
|
struct push_assert_begin: ctll::action {};
|
|
struct push_assert_end: ctll::action {};
|
|
struct push_assert_subject_begin: ctll::action {};
|
|
struct push_assert_subject_end: ctll::action {};
|
|
struct push_assert_subject_end_with_lineend: ctll::action {};
|
|
struct push_character: ctll::action {};
|
|
struct push_character_alarm: ctll::action {};
|
|
struct push_character_anything: ctll::action {};
|
|
struct push_character_escape: ctll::action {};
|
|
struct push_character_formfeed: ctll::action {};
|
|
struct push_character_newline: ctll::action {};
|
|
struct push_character_null: ctll::action {};
|
|
struct push_character_return_carriage: ctll::action {};
|
|
struct push_character_tab: ctll::action {};
|
|
struct push_empty: ctll::action {};
|
|
struct push_hexdec: ctll::action {};
|
|
struct push_name: ctll::action {};
|
|
struct push_not_word_boundary: ctll::action {};
|
|
struct push_number: ctll::action {};
|
|
struct push_property_name: ctll::action {};
|
|
struct push_property_value: ctll::action {};
|
|
struct push_word_boundary: ctll::action {};
|
|
struct repeat_ab: ctll::action {};
|
|
struct repeat_at_least: ctll::action {};
|
|
struct repeat_exactly: ctll::action {};
|
|
struct repeat_plus: ctll::action {};
|
|
struct repeat_star: ctll::action {};
|
|
struct reset_capture: ctll::action {};
|
|
struct set_combine: ctll::action {};
|
|
struct set_make: ctll::action {};
|
|
struct set_make_negative: ctll::action {};
|
|
struct set_start: ctll::action {};
|
|
struct start_atomic: ctll::action {};
|
|
struct start_lookahead_negative: ctll::action {};
|
|
struct start_lookahead_positive: ctll::action {};
|
|
struct start_lookbehind_negative: ctll::action {};
|
|
struct start_lookbehind_positive: ctll::action {};
|
|
|
|
// (q)LL1 function:
|
|
using _others = ctll::neg_set<'!','$','\x28','\x29','*','+',',','-','.','/',':','<','=','>','?','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','[','\\','0','\"',']','^','_','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','1','2','3','4','5','6','7','8','9'>;
|
|
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','-','=','>','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','1','2','3','4','5','6','7','8','9'>) -> 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, 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','-','=','>','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','1','2','3','4','5','6','7','8','9'>) -> 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','-','=','>','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','1','2','3','4','5','6','7','8','9'>) -> 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, 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','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','1','2','3','4','5','6','7','8','9'>) -> 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<'!','0','$','\x28','\x29','*','+',',','.','/',':','<','=','>','?','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','1','2','3','4','5','6','7','8','9'>) -> 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, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2>;
|
|
static constexpr auto rule(content, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2>;
|
|
static constexpr auto rule(content, ctll::term<'\x28'>) -> ctll::push<ctll::anything, prepare_capture, block, repeat, string2, content2>;
|
|
static constexpr auto rule(content, ctll::term<'^'>) -> ctll::push<ctll::anything, push_assert_begin, repeat, string2, content2>;
|
|
static constexpr auto rule(content, ctll::term<'$'>) -> ctll::push<ctll::anything, push_assert_end, repeat, string2, content2>;
|
|
static constexpr auto rule(content, ctll::set<'!',',','/',':','<','0','-','=','>','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','1','2','3','4','5','6','7','8','9'>) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
|
|
static constexpr auto rule(content, _others) -> ctll::push<ctll::anything, push_character, repeat, string2, content2>;
|
|
static constexpr auto rule(content, ctll::term<'.'>) -> ctll::push<ctll::anything, push_character_anything, repeat, string2, content2>;
|
|
static constexpr auto rule(content, ctll::set<'\x29','*','+','?','\x7B','|','\x7D'>) -> ctll::reject;
|
|
|
|
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','-','=','>','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','1','2','3','4','5','6','7','8','9'>) -> 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, 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(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','A','B','C','D','E','F','a','b','c','d','e','f','1','2','3','4','5','6','7','8','9'>) -> 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','*','+',',','.','/',':','<','=','>','?','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','\"','^','0','_','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','1','2','3','4','5','6','7','8','9'>) -> 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','A','B','C','D','E','F','a','b','c','d','e','f','1','2','3','4','5','6','7','8','9'>) -> 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','A','B','C','D','E','F','a','b','c','d','e','f','1','2','3','4','5','6','7','8','9'>) -> 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',':','<','=','>','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','|','1','2','3','4','5','6','7','8','9'>) -> 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<ctll::anything, create_number, number2, 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<ctll::anything, push_name, block_name2, 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(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','.','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','1','2','3','4','5','6','7','8','9'>) -> ctll::push<ctll::anything, push_property_name, property_name2>;
|
|
|
|
static constexpr auto rule(property_name, ctll::set<'0','.','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','1','2','3','4','5','6','7','8','9'>) -> 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','.','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','1','2','3','4','5','6','7','8','9'>) -> ctll::push<ctll::anything, push_property_value, property_value2>;
|
|
|
|
static constexpr auto rule(property_value, ctll::set<'0','.','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','1','2','3','4','5','6','7','8','9'>) -> ctll::push<ctll::anything, push_property_value, property_value2>;
|
|
|
|
static constexpr auto rule(range, ctll::set<'!','$','\x28','\x29','*','+',',','.','/','0',':','<','=','>','?','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','1','2','3','4','5','6','7','8','9'>) -> 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',':','<','=','>','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','|','1','2','3','4','5','6','7','8','9'>) -> 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::epsilon;
|
|
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','*','+',',','.','/',':','<','=','>','?','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','\"','^','0','_','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','1','2','3','4','5','6','7','8','9'>) -> 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::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','*','+',',','.','/',':','<','=','>','?','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','\"','^','0','_','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','1','2','3','4','5','6','7','8','9'>) -> 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','-','=','>','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','1','2','3','4','5','6','7','8','9'>) -> 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
|
|
|
|
#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
|
|
#include <cstdint>
|
|
|
|
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 value == V;
|
|
}
|
|
};
|
|
|
|
template <typename... Content> struct negative_set {
|
|
template <typename CharT> CTRE_FORCE_INLINE static constexpr bool match_char(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(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(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 (value >= A) && (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
|
|
|
|
#include <cstdint>
|
|
|
|
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
|
|
|
|
#include <string_view>
|
|
|
|
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>(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;
|
|
|
|
template <typename... Content> static auto rotate(select<Content...>) -> select<Content...>;
|
|
static auto rotate(empty) -> empty;
|
|
|
|
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
|
|
|
|
#include <type_traits>
|
|
|
|
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
|
|
|
|
#include <cstdint>
|
|
#include <limits>
|
|
|
|
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_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 __cpp_char8_t >= 201811
|
|
|
|
#include <string_view>
|
|
#include <iterator>
|
|
|
|
#if __cpp_lib_char8_t >= 201811L
|
|
#define CTRE_ENABLE_UTF8_RANGE
|
|
#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};
|
|
}
|
|
|
|
friend constexpr auto operator!=(self_type, const char8_t * other_ptr) noexcept {
|
|
return *other_ptr != char8_t{0};
|
|
}
|
|
|
|
#if __cpp_impl_three_way_comparison < 201907L
|
|
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};
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
#if __cpp_impl_three_way_comparison < 201907L
|
|
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 *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
|
|
|
|
#include <type_traits>
|
|
#include <tuple>
|
|
#include <string_view>
|
|
#include <string>
|
|
#include <iterator>
|
|
#ifdef _MSC_VER
|
|
#include <memory>
|
|
#endif
|
|
#include <iosfwd>
|
|
#if __has_include(<charconv>)
|
|
#include <charconv>
|
|
#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 __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 __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 __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> constexpr CTRE_FORCE_INLINE auto to_number(int base = 10) const noexcept -> R {
|
|
R result{0};
|
|
const auto view = to_view();
|
|
std::from_chars(view.data(), view.data() + view.size(), result, base);
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
template <typename T> struct identify;
|
|
|
|
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 std::basic_string<char_type> to_string() const noexcept {
|
|
#if __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 view() const noexcept {
|
|
return to_view();
|
|
}
|
|
|
|
constexpr CTRE_FORCE_INLINE auto str() const noexcept {
|
|
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 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();
|
|
}
|
|
};
|
|
};
|
|
|
|
struct capture_not_exists_tag { };
|
|
|
|
static constexpr inline 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, typename = std::enable_if_t<decltype(_captures)::template exists<Id>()>> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
|
|
return _captures.template select<Id>();
|
|
}
|
|
template <typename Name, typename = std::enable_if_t<decltype(_captures)::template exists<Name>()>> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
|
|
return _captures.template select<Name>();
|
|
}
|
|
#if CTRE_CNTTP_COMPILER_CHECK
|
|
template <ctll::fixed_string Name, typename = std::enable_if_t<decltype(_captures)::template exists<Name>()>> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
|
|
#else
|
|
template <const auto & Name, typename = std::enable_if_t<decltype(_captures)::template exists<Name>()>> CTRE_FORCE_INLINE constexpr auto get() const noexcept {
|
|
#endif
|
|
return _captures.template select<Name>();
|
|
}
|
|
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>());
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
#if __has_include(<charconv>)
|
|
template <typename R = int> constexpr CTRE_FORCE_INLINE auto to_number(int base = 10) const noexcept -> R {
|
|
return _captures.template select<0>().template to_number<R>(base);
|
|
}
|
|
#endif
|
|
|
|
constexpr CTRE_FORCE_INLINE auto to_view() const noexcept {
|
|
return _captures.template select<0>().to_view();
|
|
}
|
|
|
|
constexpr CTRE_FORCE_INLINE auto to_string() const noexcept {
|
|
return _captures.template select<0>().to_string();
|
|
}
|
|
|
|
constexpr CTRE_FORCE_INLINE auto view() const noexcept {
|
|
return _captures.template select<0>().view();
|
|
}
|
|
|
|
constexpr CTRE_FORCE_INLINE auto str() const noexcept {
|
|
return _captures.template select<0>().to_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) {
|
|
return str << rhs.view();
|
|
}
|
|
};
|
|
|
|
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 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 {
|
|
|
|
template <typename Pattern> constexpr auto find_captures(Pattern) noexcept {
|
|
return find_captures(ctll::list<Pattern>(), ctll::list<>());
|
|
}
|
|
|
|
template <typename... Output> constexpr auto find_captures(ctll::list<>, ctll::list<Output...> output) noexcept {
|
|
return output;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
template <typename... Tail, typename Output> constexpr auto find_captures(ctll::list<empty, Tail...>, Output output) noexcept {
|
|
return find_captures(ctll::list<Tail...>(), output);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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>)
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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>>());
|
|
}
|
|
|
|
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 (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... 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
|
|
|
|
#include <iterator>
|
|
|
|
// 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
|
|
|
|
#include <cstddef>
|
|
|
|
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 pointer = void;
|
|
using reference = 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 const value_type & 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
|
|
|
|
#include <string_view>
|
|
|
|
namespace ctre {
|
|
|
|
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 inline 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{};
|
|
}
|
|
};
|
|
|
|
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::template 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
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto match = regular_expression<typename regex_builder<input>::type, match_method, ctll::list<singleline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto search = regular_expression<typename regex_builder<input>::type, search_method, ctll::list<singleline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto starts_with = regular_expression<typename regex_builder<input>::type, starts_with_method, ctll::list<singleline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto range = regular_expression<typename regex_builder<input>::type, range_method, ctll::list<singleline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto split = regular_expression<typename regex_builder<input>::type, split_method, ctll::list<singleline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto tokenize = regular_expression<typename regex_builder<input>::type, tokenize_method, ctll::list<singleline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto iterator = regular_expression<typename regex_builder<input>::type, iterator_method, ctll::list<singleline, Modifiers...>>();
|
|
|
|
static constexpr inline auto sentinel = regex_end_iterator();
|
|
|
|
// multiline
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto multiline_match = regular_expression<typename regex_builder<input>::type, match_method, ctll::list<multiline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto multiline_search = regular_expression<typename regex_builder<input>::type, search_method, ctll::list<multiline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto multiline_starts_with = regular_expression<typename regex_builder<input>::type, starts_with_method, ctll::list<multiline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto multiline_range = regular_expression<typename regex_builder<input>::type, range_method, ctll::list<multiline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto multiline_split = regular_expression<typename regex_builder<input>::type, split_method, ctll::list<multiline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto multiline_tokenize = regular_expression<typename regex_builder<input>::type, tokenize_method, ctll::list<multiline, Modifiers...>>();
|
|
|
|
template <CTRE_REGEX_INPUT_TYPE input, typename... Modifiers> static constexpr inline auto multiline_iterator = regular_expression<typename regex_builder<input>::type, iterator_method, ctll::list<multiline, Modifiers...>>();
|
|
|
|
static constexpr inline auto multiline_sentinel = regex_end_iterator();
|
|
|
|
}
|
|
|
|
#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
|