├── .conan ├── build.py └── test_package │ ├── CMakeLists.txt │ ├── conanfile.py │ └── test_package.cpp ├── .github └── workflows │ └── tests.yml ├── .gitignore ├── .gitmodules ├── .tm_properties ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── NOTES.md ├── README.md ├── clang-bench.txt ├── conanfile.py ├── ctre.cppm ├── docs ├── api.rst ├── conf.py ├── examples.rst ├── index.rst └── regex_syntax.rst ├── future.cpp ├── gcc-bench.txt ├── include ├── ctll.hpp ├── ctll │ ├── actions.hpp │ ├── fixed_string.hpp │ ├── grammars.hpp │ ├── list.hpp │ ├── parser.hpp │ └── utilities.hpp ├── ctre-unicode.hpp ├── ctre.hpp ├── ctre │ ├── actions │ │ ├── asserts.inc.hpp │ │ ├── atomic_group.inc.hpp │ │ ├── backreference.inc.hpp │ │ ├── boundaries.inc.hpp │ │ ├── capture.inc.hpp │ │ ├── characters.inc.hpp │ │ ├── class.inc.hpp │ │ ├── fusion.inc.hpp │ │ ├── hexdec.inc.hpp │ │ ├── look.inc.hpp │ │ ├── mode.inc.hpp │ │ ├── named_class.inc.hpp │ │ ├── options.inc.hpp │ │ ├── properties.inc.hpp │ │ ├── repeat.inc.hpp │ │ ├── sequence.inc.hpp │ │ └── set.inc.hpp │ ├── atoms.hpp │ ├── atoms_characters.hpp │ ├── atoms_unicode.hpp │ ├── evaluation.hpp │ ├── find_captures.hpp │ ├── first.hpp │ ├── flags_and_modes.hpp │ ├── functions.hpp │ ├── id.hpp │ ├── iterators.hpp │ ├── literals.hpp │ ├── operators.hpp │ ├── pcre.gram │ ├── pcre.hpp │ ├── pcre_actions.hpp │ ├── range.hpp │ ├── return_type.hpp │ ├── rotate.hpp │ ├── starts_with_anchor.hpp │ ├── utf8.hpp │ ├── utility.hpp │ └── wrapper.hpp ├── unicode-db.hpp └── unicode-db │ ├── unicode-db.hpp │ └── unicode_interface.hpp ├── packaging └── pkgconfig.pc.in ├── single-header ├── ctre-unicode.hpp ├── ctre.hpp └── unicode-db.hpp └── tests ├── CMakeLists.txt ├── __utf8.cpp ├── _bad_cycle.cpp ├── _fixed-string.cpp ├── _unicode.cpp ├── benchmark-exec ├── .gitignore ├── .tm_properties ├── Makefile ├── baseline.cpp ├── boost.cpp ├── common.hpp ├── ctre.cpp ├── jsc.js ├── node-v8.js ├── pattern.hpp ├── pcre-jit.cpp ├── pcre.cpp ├── re2.cpp ├── srell.cpp ├── std.cpp └── xpressive.cpp ├── benchmark-range ├── load-file.hpp └── measurement.cpp ├── benchmark ├── many-of-different-ctll.cpp ├── many-of-different-x5-ctll.cpp ├── many-of-same-ctll.cpp ├── many-of-same-proto.cpp ├── same.cpp └── unique.cpp ├── ci.cpp ├── cnttp.cpp ├── correct-conversion.cpp ├── gcc8.cpp ├── generating.cpp ├── gets.cpp ├── is_prime.cpp ├── many-of-same-proto.cpp ├── matching.cpp ├── matching2-msvc-greedy.cpp ├── matching2.cpp ├── matching3.cpp ├── mode.cpp ├── msvc.cpp ├── parsing.cpp ├── range.cpp ├── results.cpp ├── string.cpp ├── trampoline.cpp ├── wide-pattern.cpp └── z_matching.cpp /.conan/build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | import os 4 | from cpt.packager import ConanMultiPackager 5 | 6 | 7 | def get_travis_branch(): 8 | return os.getenv("TRAVIS_BRANCH") 9 | 10 | 11 | def get_reference(): 12 | return "CTRE/{}".format(get_travis_branch()) 13 | 14 | 15 | if __name__ == "__main__": 16 | builder = ConanMultiPackager( 17 | reference=get_reference(), 18 | username="ctre", 19 | upload="https://api.bintray.com/conan/hanickadot/ctre", 20 | upload_only_when_stable=True, 21 | stable_branch_pattern="v?\d+\.\d+.*", 22 | test_folder=os.path.join(".conan", "test_package")) 23 | builder.add_common_builds() 24 | builder.run() 25 | -------------------------------------------------------------------------------- /.conan/test_package/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(test_package CXX) 2 | cmake_minimum_required(VERSION 2.8 FATAL_ERROR) 3 | 4 | set(CMAKE_VERBOSE_MAKEFILE TRUE) 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") 6 | 7 | include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) 8 | conan_basic_setup() 9 | 10 | add_executable(${PROJECT_NAME} test_package.cpp) 11 | target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS}) 12 | -------------------------------------------------------------------------------- /.conan/test_package/conanfile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from conans import ConanFile, CMake, tools, RunEnvironment 5 | import os 6 | 7 | 8 | class TestPackageConan(ConanFile): 9 | settings = "os", "compiler", "build_type", "arch" 10 | generators = "cmake" 11 | 12 | def build(self): 13 | cmake = CMake(self) 14 | cmake.configure() 15 | cmake.build() 16 | 17 | def test(self): 18 | assert os.path.exists(os.path.join(self.deps_cpp_info["CTRE"].rootpath, "licenses", "LICENSE")) 19 | bin_path = os.path.join("bin", "test_package") 20 | self.run(bin_path, run_environment=True) 21 | -------------------------------------------------------------------------------- /.conan/test_package/test_package.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | using namespace std::string_view_literals; 9 | using namespace ctre::literals; 10 | 11 | struct date { std::string_view year; std::string_view month; std::string_view day; }; 12 | 13 | static constexpr ctll::fixed_string pattern = "^([0-9]{4})/([0-9]{1,2}+)/([0-9]{1,2}+)$"; 14 | 15 | constexpr std::optional extract_date(std::string_view s) noexcept { 16 | if (auto [whole, year, month, day] = ctre::match(s); whole 17 | ) { 18 | return date{year.to_view(), month.to_view(), day.to_view()}; 19 | } else { 20 | return std::nullopt; 21 | } 22 | } 23 | 24 | int main() { 25 | 26 | assert(extract_date("2018/08/27"sv).has_value()); 27 | assert(extract_date("2018/08/27"sv)->year == "2018"sv); 28 | assert(extract_date("2018/08/27"sv)->month == "08"sv); 29 | assert(extract_date("2018/08/27"sv)->day == "27"sv); 30 | 31 | return EXIT_SUCCESS; 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | on: [push, pull_request] 3 | jobs: 4 | appleclang: 5 | strategy: 6 | matrix: 7 | macos: [13, 14, 15] 8 | standard: [17, 20] 9 | fail-fast: false 10 | name: "AppleClang (MacOS ${{ matrix.macos }}, C++${{ matrix.standard }})" 11 | runs-on: macos-${{ matrix.macos }} 12 | steps: 13 | - uses: actions/checkout@v2 14 | - run: c++ -v 15 | - run: make CXX=c++ CXX_STANDARD=2a 16 | if: ${{ matrix.standard == '20' }} 17 | - run: make CXX=c++ CXX_STANDARD=17 18 | if: ${{ matrix.standard == '17' }} 19 | gcc: 20 | strategy: 21 | matrix: 22 | gcc: [9, 10, 11, 13, 14, 15] 23 | standard: [17, 20] 24 | fail-fast: false 25 | name: "GCC ${{ matrix.gcc }} (C++${{ matrix.standard }})" 26 | runs-on: ubuntu-latest 27 | steps: 28 | - run: sudo apt-get install g++-${{ matrix.gcc }} 29 | - uses: actions/checkout@v2 30 | - run: c++ -v 31 | - run: make CXX=c++ CXX_STANDARD=2a 32 | if: ${{ matrix.standard == '20' }} 33 | - run: make CXX=c++ CXX_STANDARD=17 CXXFLAGS=-DCTRE_ENABLE_LITERALS PEDANTIC="" 34 | if: ${{ matrix.standard == '17' }} 35 | clang: 36 | strategy: 37 | matrix: 38 | clang: [14, 15, 16, 17, 18, 19, 20] 39 | stdlib: ["libc++", "libstdc++"] 40 | standard: [17, 20] 41 | fail-fast: false 42 | name: "Clang ${{ matrix.clang }} (C++${{ matrix.standard }}, ${{ matrix.stdlib }})" 43 | runs-on: ubuntu-latest 44 | steps: 45 | - name: "Install Clang" 46 | uses: egor-tensin/setup-clang@v1 47 | with: 48 | version: ${{ matrix.clang }} 49 | - name: "Install libc++" 50 | if: ${{ matrix.stdlib == 'libc++' }} 51 | run: sudo apt-get install libc++abi-${{ matrix.clang }}-dev libc++1-${{ matrix.clang }} libc++-${{ matrix.clang }}-dev 52 | - uses: actions/checkout@v2 53 | - run: c++ -v 54 | - run: make CXX=c++ CXX_STANDARD=2a CXXFLAGS=-stdlib=${{ matrix.stdlib }} 55 | if: ${{ matrix.standard == '20' }} 56 | - run: make CXX=c++ CXX_STANDARD=17 CXXFLAGS=-stdlib=${{ matrix.stdlib }} 57 | if: ${{ matrix.standard == '17' }} 58 | msvc: 59 | strategy: 60 | matrix: 61 | version: [14.29, ""] 62 | fail-fast: false 63 | name: "MSVC ${{ matrix.version }} (C++20)" 64 | runs-on: windows-2022 65 | steps: 66 | - name: Add MSVC ${{ matrix.version }} to PATH 67 | uses: ilammy/msvc-dev-cmd@v1 68 | with: 69 | toolset: ${{ matrix.version }} 70 | - name: "Install Ninja & CMake" 71 | run: choco install ninja cmake 72 | - uses: actions/checkout@v2 73 | - name: "Configure" 74 | run: cmake . -G Ninja -B build -DCTRE_BUILD_TESTS=ON -DCTRE_CXX_STANDARD=20 75 | - name: "Build" 76 | run: cmake --build build --target ctre-test --verbose 77 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.d 3 | **/*.tmp 4 | test 5 | result 6 | tests/benchmark-exec/* 7 | !tests/benchmark-exec/Makefile 8 | !tests/benchmark-exec/.gitignore 9 | !tests/benchmark-exec/.tm_properties 10 | !tests/benchmark-exec/*.cpp 11 | !tests/benchmark-exec/*.hpp 12 | !tests/benchmark-exec/*.js 13 | *.pyc 14 | .conan/test_package/build 15 | mtent12.txt 16 | *.zip 17 | tests/benchmark-range/* 18 | !tests/benchmark-range/*.cpp 19 | !tests/benchmark-range/*.hpp 20 | build 21 | cmake-build-*/* 22 | .idea/* -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanickadot/compile-time-regular-expressions/e34c26ba149b9fd9c34aa0f678e39739641a0d1e/.gitmodules -------------------------------------------------------------------------------- /.tm_properties: -------------------------------------------------------------------------------- 1 | exclude = "{$exclude,**/*.dSYM,**/*.d,**/*.o,test,*.tmp}" 2 | include = "{$include,.gitignore,.github,.travis*,.conan}" 3 | excludeInFolderSearch = "{$excludeInFolderSearch,./ctre.hpp}" 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | dist: focal 3 | os: linux 4 | 5 | jobs: 6 | include: 7 | - os: linux 8 | language: python 9 | python: "3.6" 10 | services: 11 | - docker 12 | env: 13 | - COMPILER=g++-8 14 | - CONAN_GCC_VERSIONS=8 15 | - CONAN_DOCKER_IMAGE=lasote/conangcc8 16 | install: 17 | - pip install -U conan conan-package-tools 18 | script: 19 | - python .conan/build.py 20 | 21 | - os: linux 22 | compiler: gcc 23 | env: 24 | - COMPILER=g++-8 25 | - CXX_STANDARD=17 26 | addons: 27 | apt: 28 | packages: ['g++-8'] 29 | 30 | - os: linux 31 | compiler: gcc 32 | env: 33 | - COMPILER=g++-8 34 | - CXX_STANDARD=2a 35 | addons: 36 | apt: 37 | packages: ['g++-8'] 38 | 39 | - os: linux 40 | compiler: clang 41 | env: 42 | - COMPILER=clang++-6.0 43 | - CXX_STANDARD=17 44 | addons: 45 | apt: 46 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0'] 47 | packages: ['g++-8', 'clang-6.0'] 48 | 49 | - os: linux 50 | compiler: clang 51 | env: 52 | - COMPILER=clang++-6.0 53 | - CXX_STANDARD=2a 54 | addons: 55 | apt: 56 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0'] 57 | packages: ['g++-8', 'clang-6.0'] 58 | 59 | # FIXME: don't use GCC10 in 17 mode for tests as they are depending on operator"" 60 | # - os: linux 61 | # compiler: gcc 62 | # env: 63 | # - COMPILER=g++-10 64 | # - CXX_STANDARD=17 65 | # addons: 66 | # apt: 67 | # packages: ['g++-10'] 68 | 69 | - os: linux 70 | compiler: gcc 71 | env: 72 | - COMPILER=g++-10 73 | - CXX_STANDARD=20 74 | addons: 75 | apt: 76 | packages: ['g++-10'] 77 | 78 | - os: osx 79 | osx_image: xcode10 80 | env: 81 | - CXX_STANDARD=17 82 | 83 | - os: osx 84 | osx_image: xcode10 85 | env: 86 | - CXX_STANDARD=2a 87 | 88 | - os: osx 89 | osx_image: xcode11 90 | env: 91 | - CXX_STANDARD=17 92 | 93 | - os: osx 94 | osx_image: xcode11 95 | env: 96 | - CXX_STANDARD=2a 97 | 98 | - os: osx 99 | osx_image: xcode12 100 | env: 101 | - CXX_STANDARD=17 102 | 103 | - os: osx 104 | osx_image: xcode12 105 | env: 106 | - CXX_STANDARD=2a 107 | 108 | install: 109 | - if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi 110 | - uname -a 111 | - $CXX --version 112 | script: 113 | - make CXX_STANDARD=$CXX_STANDARD 114 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14...3.29) 2 | 3 | if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.29.20240416") 4 | set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") 5 | set(CMAKE_CXX_MODULE_STD 1) 6 | endif() 7 | 8 | # When updating to a newer version of CMake, see if we can use the following 9 | project(ctre 10 | HOMEPAGE_URL "https://compile-time.re" 11 | VERSION 3.9.0 12 | LANGUAGES CXX) 13 | set(PROJECT_DESCRIPTION "Fast compile-time regular expressions with support for matching/searching/capturing during compile-time or runtime.") 14 | 15 | include(CMakePackageConfigHelpers) 16 | include(CMakeDependentOption) 17 | include(GNUInstallDirs) 18 | include(CTest) 19 | 20 | find_program(CTRE_DPKG_BUILDPACKAGE_FOUND dpkg-buildpackage) 21 | find_program(CTRE_RPMBUILD_FOUND rpmbuild) 22 | 23 | cmake_dependent_option(CTRE_BUILD_TESTS "Build ctre Tests" ON 24 | "BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF) 25 | cmake_dependent_option(CTRE_BUILD_PACKAGE "Build ctre Packages" ON 26 | "CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF) 27 | cmake_dependent_option(CTRE_BUILD_PACKAGE_DEB 28 | "Create DEB Package (${PROJECT_NAME})" ON 29 | "CTRE_BUILD_PACKAGE;CTRE_DPKG_BUILDPACKAGE_FOUND" OFF) 30 | cmake_dependent_option(CTRE_BUILD_PACKAGE_RPM 31 | "Create RPM Package (${PROJECT_NAME})" ON 32 | "CTRE_BUILD_PACKAGE;CTRE_RPMBUILD_FOUND" OFF) 33 | 34 | option(CTRE_MODULE "build C++ module" OFF) 35 | 36 | if(CTRE_MODULE) 37 | if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.29.20240416") 38 | add_library(${PROJECT_NAME}) 39 | 40 | target_sources(${PROJECT_NAME} PUBLIC FILE_SET CXX_MODULES TYPE CXX_MODULES FILES ctre.cppm) 41 | target_sources(${PROJECT_NAME} PUBLIC FILE_SET HEADERS TYPE HEADERS 42 | BASE_DIRS 43 | "${CMAKE_CURRENT_SOURCE_DIR}/include" 44 | FILES 45 | include/ctll.hpp 46 | include/ctre/functions.hpp 47 | include/ctre/utility.hpp 48 | include/ctre/utf8.hpp 49 | include/ctre/evaluation.hpp 50 | include/ctre/starts_with_anchor.hpp 51 | include/ctre/pcre_actions.hpp 52 | include/ctre/rotate.hpp 53 | include/ctre/iterators.hpp 54 | include/ctre/literals.hpp 55 | include/ctre/return_type.hpp 56 | include/ctre/find_captures.hpp 57 | include/ctre/id.hpp 58 | include/ctre/atoms_characters.hpp 59 | include/ctre/actions/mode.inc.hpp 60 | include/ctre/actions/characters.inc.hpp 61 | include/ctre/actions/class.inc.hpp 62 | include/ctre/actions/look.inc.hpp 63 | include/ctre/actions/sequence.inc.hpp 64 | include/ctre/actions/fusion.inc.hpp 65 | include/ctre/actions/asserts.inc.hpp 66 | include/ctre/actions/capture.inc.hpp 67 | include/ctre/actions/named_class.inc.hpp 68 | include/ctre/actions/backreference.inc.hpp 69 | include/ctre/actions/options.inc.hpp 70 | include/ctre/actions/atomic_group.inc.hpp 71 | include/ctre/actions/set.inc.hpp 72 | include/ctre/actions/hexdec.inc.hpp 73 | include/ctre/actions/repeat.inc.hpp 74 | include/ctre/actions/properties.inc.hpp 75 | include/ctre/actions/boundaries.inc.hpp 76 | include/ctre/operators.hpp 77 | include/ctre/pcre.hpp 78 | include/ctre/atoms_unicode.hpp 79 | include/ctre/range.hpp 80 | include/ctre/wrapper.hpp 81 | include/ctre/first.hpp 82 | include/ctre/flags_and_modes.hpp 83 | include/ctre/atoms.hpp 84 | include/unicode-db.hpp 85 | include/unicode-db/unicode_interface.hpp 86 | include/unicode-db/unicode-db.hpp 87 | include/ctll/parser.hpp 88 | include/ctll/actions.hpp 89 | include/ctll/fixed_string.hpp 90 | include/ctll/list.hpp 91 | include/ctll/utilities.hpp 92 | include/ctll/grammars.hpp 93 | include/ctre.hpp 94 | include/ctre-unicode.hpp 95 | ) 96 | 97 | # we are using `import std;` 98 | if (NOT DEFINED CTRE_CXX_STANDARD OR CTRE_CXX_STANDARD LESS 23) 99 | set(CTRE_CXX_STANDARD 23) 100 | endif() 101 | 102 | target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_${CTRE_CXX_STANDARD}) 103 | 104 | install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets 105 | FILE_SET CXX_MODULES DESTINATION "${CMAKE_INSTALL_LIBDIR}/cxx/${PROJECT_NAME}" 106 | FILE_SET HEADERS DESTINATION "include") 107 | else() 108 | message(FATAL_ERROR "unsupported cmake for c++ modules") 109 | endif() 110 | else() 111 | add_library(${PROJECT_NAME} INTERFACE) 112 | 113 | target_include_directories(${PROJECT_NAME} INTERFACE 114 | $ 115 | $) 116 | 117 | if (NOT CTRE_CXX_STANDARD) 118 | set(CTRE_CXX_STANDARD 20) 119 | endif() 120 | 121 | target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_${CTRE_CXX_STANDARD}) 122 | set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_SCAN_FOR_MODULES 0) 123 | 124 | install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets) 125 | install(DIRECTORY include/ DESTINATION include 126 | FILES_MATCHING PATTERN *.hpp) 127 | endif() 128 | 129 | add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) 130 | 131 | if (NOT EXISTS "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake.in") 132 | file(WRITE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake.in [[ 133 | @PACKAGE_INIT@ 134 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") 135 | ]]) 136 | endif() 137 | 138 | configure_package_config_file( 139 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake.in" 140 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" 141 | INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" 142 | NO_SET_AND_CHECK_MACRO 143 | NO_CHECK_REQUIRED_COMPONENTS_MACRO) 144 | 145 | write_basic_package_version_file(ctre-config-version.cmake 146 | VERSION ${PROJECT_VERSION} 147 | COMPATIBILITY SameMajorVersion) 148 | 149 | install(EXPORT ${PROJECT_NAME}-targets 150 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" 151 | NAMESPACE ${PROJECT_NAME}::) 152 | install( 153 | FILES 154 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" 155 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" 156 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) 157 | 158 | if(CTRE_BUILD_TESTS) 159 | add_subdirectory(tests) 160 | endif() 161 | 162 | if (NOT CTRE_BUILD_PACKAGE) 163 | return() 164 | endif() 165 | 166 | list(APPEND source-generators TBZ2 TGZ TXZ ZIP) 167 | 168 | if (CTRE_BUILD_PACKAGE_DEB) 169 | list(APPEND binary-generators "DEB") 170 | endif() 171 | 172 | if (CTRE_BUILD_PACKAGE_RPM) 173 | list(APPEND binary-generators "RPM") 174 | endif() 175 | 176 | set(CPACK_SOURCE_GENERATOR ${source-generators}) 177 | set(CPACK_GENERATOR ${binary-generators}) 178 | 179 | set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}") 180 | set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}") 181 | 182 | set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Hana Dusíková") 183 | set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}") 184 | set(CPACK_DEBIAN_PACKAGE_NAME "lib${PROJECT_NAME}-dev") 185 | 186 | set(CPACK_RPM_PACKAGE_NAME "lib${PROJECT_NAME}-devel") 187 | 188 | set(PKG_CONFIG_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc") 189 | configure_file("${CMAKE_CURRENT_SOURCE_DIR}/packaging/pkgconfig.pc.in" "${PKG_CONFIG_FILE_NAME}" @ONLY) 190 | install(FILES "${PKG_CONFIG_FILE_NAME}" 191 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" 192 | ) 193 | 194 | list(APPEND CPACK_SOURCE_IGNORE_FILES /.git/ /build/ .gitignore .DS_Store) 195 | 196 | include(CPack) 197 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: default all clean grammar compare single-header single-header/ctre.hpp single-header/ctre-unicode.hpp single-header/unicode-db.hpp 2 | 3 | default: all 4 | 5 | TARGETS := $(wildcard tests/benchmark-exec/*.cpp) 6 | IGNORE := $(wildcard tests/benchmark/*.cpp) $(wildcard tests/benchmark-exec/*.cpp) 7 | 8 | DESATOMAT := /bin/false 9 | 10 | CXX_STANDARD := 20 11 | 12 | PYTHON := python3.9 13 | 14 | PEDANTIC:=-pedantic 15 | 16 | override CXXFLAGS := $(CXXFLAGS) -std=c++$(CXX_STANDARD) -Iinclude -O3 $(PEDANTIC) -Wall -Wextra -Werror -Wconversion 17 | LDFLAGS := 18 | 19 | TESTS := $(wildcard tests/*.cpp) $(wildcard tests/benchmark/*.cpp) 20 | TRUE_TARGETS := $(TARGETS:%.cpp=%) 21 | override TRUE_TARGETS := $(filter-out $(IGNORE:%.cpp=%), $(TRUE_TARGETS)) 22 | OBJECTS := $(TARGETS:%.cpp=%.o) $(TESTS:%.cpp=%.o) 23 | override OBJECTS := $(filter-out $(IGNORE:%.cpp=%.o),$(OBJECTS)) 24 | DEPEDENCY_FILES := $(OBJECTS:%.o=%.d) 25 | 26 | all: $(TRUE_TARGETS) $(OBJECTS) 27 | 28 | list: 29 | echo $(SUPPORTED_CPP20) 30 | 31 | $(TRUE_TARGETS): %: %.o 32 | $(CXX) $< $(LDFLAGS) -o $@ 33 | 34 | $(OBJECTS): %.o: %.cpp 35 | $(CXX) $(CXXFLAGS) -MMD -c $< -o $@ 36 | 37 | -include $(DEPEDENCY_FILES) 38 | 39 | benchmark: 40 | @$(MAKE) clean 41 | @$(MAKE) IGNORE="" 42 | 43 | benchmark-clean: 44 | @$(MAKE) IGNORE="" clean 45 | 46 | clean: 47 | rm -f $(TRUE_TARGETS) $(OBJECTS) $(DEPEDENCY_FILES) mtent12.txt mtent12.zip 48 | 49 | grammar: include/ctre/pcre.hpp 50 | 51 | regrammar: 52 | @rm -f include/ctre/pcre.hpp 53 | @$(MAKE) grammar 54 | 55 | include/ctre/pcre.hpp: include/ctre/pcre.gram 56 | @echo "LL1q $<" 57 | @$(DESATOMAT) --ll --q --input=include/ctre/pcre.gram --output=include/ctre/ --generator=cpp_ctll_v2 --cfg:fname=pcre.hpp --cfg:namespace=ctre --cfg:guard=CTRE__PCRE__HPP --cfg:grammar_name=pcre 58 | 59 | mtent12.zip: 60 | curl -s http://www.gutenberg.org/files/3200/old/mtent12.zip -o mtent12.zip 61 | 62 | mtent12.txt: mtent12.zip 63 | unzip -o mtent12.zip 64 | touch mtent12.txt 65 | 66 | single-header: single-header/ctre.hpp single-header/ctre-unicode.hpp single-header/unicode-db.hpp 67 | 68 | single-header/unicode-db.hpp: include/unicode-db/unicode-db.hpp 69 | cp $+ $@ 70 | 71 | single-header/ctre.hpp: 72 | ${PYTHON} -m quom include/ctre.hpp ctre.hpp.tmp 73 | echo "/*" > single-header/ctre.hpp 74 | cat LICENSE >> single-header/ctre.hpp 75 | echo "*/" >> single-header/ctre.hpp 76 | cat ctre.hpp.tmp >> single-header/ctre.hpp 77 | rm ctre.hpp.tmp 78 | 79 | single-header/ctre-unicode.hpp: 80 | ${PYTHON} -m quom include/ctre-unicode.hpp ctre-unicode.hpp.tmp 81 | echo "/*" > single-header/ctre-unicode.hpp 82 | cat LICENSE >> single-header/ctre-unicode.hpp 83 | echo "*/" >> single-header/ctre-unicode.hpp 84 | cat ctre-unicode.hpp.tmp >> single-header/ctre-unicode.hpp 85 | rm ctre-unicode.hpp.tmp 86 | 87 | REPEAT:=10 88 | 89 | compare: mtent12.txt 90 | $(CXX) $(CXXFLAGS) -MMD -march=native -DPATTERN="\"(${PATTERN})\"" -c tests/benchmark-range/measurement.cpp -o tests/benchmark-range/measurement.o 91 | $(CXX) tests/benchmark-range/measurement.o -lboost_regex -lpcre2-8 -lre2 -o tests/benchmark-range/measurement 92 | tests/benchmark-range/measurement all mtent12.txt ${REPEAT} 93 | -------------------------------------------------------------------------------- /NOTES.md: -------------------------------------------------------------------------------- 1 | # Unsupported PCRE constructs 2 | 3 | * `\0dd` `\ddd` `\0{dd...}` octal numbers 4 | * `\Q...\E` quoting 5 | * `\cx` control characters 6 | * `\C` data unit 7 | * `\h` `\H` horizontal character classes 8 | * `\v` `\V` vertical character classes 9 | * `\p{xx}` `\P{xx}` character properties 10 | * `\X` unicode grapheme cluster 11 | * boundaries other than `^$` 12 | * atomic groups 13 | * comments 14 | * options/modes 15 | * subroutines 16 | * conditional patterns 17 | * callouts 18 | * match point reset `\K` 19 | 20 | 21 | # Other unsupported "things" 22 | * `[[.hyphen.]]` named characters 23 | * `[[=M=]]` whatever this is 24 | 25 | -------------------------------------------------------------------------------- /clang-bench.txt: -------------------------------------------------------------------------------- 1 | //--------- ABCD|DEFGH|EFGHI|A{4,} 2 | egrep 0m49.353s 3 | CTRE 0m10.093s 4 | PCRE 0m12.515s 5 | std::regex 21m9.309s 6 | //--------- [0-9a-fA-F]{8,16} 7 | egrep 0m32.256s 8 | CTRE 0m14.197s 9 | PCRE 0m17.832s 10 | std::regex 2m34.505s 11 | //--------- ^([0-9]{4,16})?[aA] 12 | egrep 0m12.880s 13 | CTRE 0m7.596s 14 | PCRE 0m6.590s 15 | std::regex 7m54.793s 16 | //--------- ([aAbB]{4,}|[xXyY]{4,}|[1234]{4,})0 17 | egrep 1m56.412s 18 | CTRE 0m59.864s 19 | PCRE 0m43.486s 20 | std::regex 27m35.004s 21 | -------------------------------------------------------------------------------- /conanfile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from conans import ConanFile 5 | 6 | 7 | class CtreConan(ConanFile): 8 | name = "CTRE" 9 | license = "Apache 2.0 with LLVM Exception" 10 | url = "https://github.com/hanickadot/compile-time-regular-expressions" 11 | author = "Hana Dusíková (ctre@hanicka.net)" 12 | description = "Compile Time Regular Expression for C++17/20" 13 | homepage = "https://github.com/hanickadot/compile-time-regular-expressions" 14 | no_copy_source = True 15 | scm = { 16 | "type": "git", 17 | "url": "auto", 18 | "revision": "auto" 19 | } 20 | 21 | def package(self): 22 | self.copy("LICENSE", "licenses") 23 | self.copy("*.hpp") 24 | 25 | def package_id(self): 26 | self.info.header_only() 27 | 28 | -------------------------------------------------------------------------------- /ctre.cppm: -------------------------------------------------------------------------------- 1 | module; 2 | 3 | #ifdef _MSVC_LANG 4 | #pragma warning( disable : 5202 ) 5 | #endif 6 | 7 | import std; 8 | 9 | export module ctre; 10 | 11 | #define CTRE_IN_A_MODULE 12 | #define CTLL_IN_A_MODULE 13 | #define UNICODE_DB_IN_A_MODULE 14 | 15 | using std::int16_t; 16 | using std::int32_t; 17 | using std::int64_t; 18 | using std::int8_t; 19 | using std::size_t; 20 | using std::uint16_t; 21 | using std::uint32_t; 22 | using std::uint64_t; 23 | using std::uint8_t; 24 | 25 | #include "ctre.hpp" 26 | #include "unicode-db.hpp" 27 | -------------------------------------------------------------------------------- /docs/api.rst: -------------------------------------------------------------------------------- 1 | API 2 | === 3 | 4 | .. class:: ctll::fixed_string 5 | 6 | A compile-time fixed string. 7 | 8 | Example: :: 9 | 10 | static constexpr auto pattern = ctll::fixed_string{ "h.*" }; 11 | 12 | constexpr auto match(std::string_view sv) noexcept { 13 | return ctre::match(sv); 14 | } 15 | 16 | .. class:: template ctre::regex_results 17 | 18 | .. type:: char_type = typename std::iterator_traits::value_type 19 | 20 | The character type used by the ``Iterator``. 21 | 22 | .. function:: template constexpr captured_content::storage get() 23 | template constexpr captured_content::storage get() 24 | template constexpr captured_content::storage get() 25 | 26 | Returns the capture specified by ``Id`` or ``Name``. ID ``0`` is the full match, ID ``1`` is the first capture group, ID ``2`` is the second, etc. 27 | Named groups are specified using ``(?)``. 28 | 29 | Example: :: 30 | 31 | if (auto m = ctre::match<"(?[a-z]+)([0-9]+)">("abc123")) { 32 | m.get<"chars">(); //abc 33 | m.get<2>(); //123 34 | } 35 | 36 | .. function:: constexpr size_t size() 37 | 38 | Returns the number of captures in this result object. 39 | 40 | .. function:: constexpr operator bool() const noexcept 41 | 42 | Returns whether the match was successful. 43 | 44 | .. function:: constexpr operator std::basic_string_view() const noexcept 45 | constexpr std::basic_string_view to_view() const noexcept 46 | constexpr std::basic_string_view view() const noexcept 47 | 48 | Converts the match to a string view. 49 | 50 | .. function:: constexpr explicit operator std::basic_string() const noexcept 51 | constexpr std::basic_string to_string() const noexcept 52 | constexpr std::basic_string str() const noexcept 53 | 54 | Converts the match to a string view. 55 | 56 | .. class:: template captured_content 57 | 58 | .. class:: template storage 59 | 60 | .. function:: constexpr auto begin() const noexcept 61 | constexpr auto end() const noexcept 62 | 63 | Returns the begin or end iterator for the captured content. 64 | 65 | .. function:: constexpr operator bool() const noexcept 66 | 67 | Returns whether the match was successful. 68 | 69 | .. function:: constexpr auto size() const noexcept 70 | 71 | Returns the number of characters in the capture. 72 | 73 | .. function:: constexpr operator std::basic_string_view() const noexcept 74 | constexpr std::basic_string_view to_view() const noexcept 75 | constexpr std::basic_string_view view() const noexcept 76 | 77 | Converts the capture to a string view. 78 | 79 | .. function:: constexpr explicit operator std::basic_string() const noexcept 80 | constexpr std::basic_string to_string() const noexcept 81 | constexpr std::basic_string str() const noexcept 82 | 83 | Converts the capture to a string view. 84 | 85 | .. function:: constexpr static size_t get_id() noexcept 86 | 87 | Returns ``Id`` 88 | 89 | .. function:: template constexpr ctre::regex_results match(Args&&... args) 90 | template constexpr ctre::regex_results match(Args&&... args) 91 | 92 | Matches ``RE`` against the whole input. 93 | ``Args...`` must be either a string-like object with ``begin`` and ``end`` member functions, or a pair of forward iterators. 94 | 95 | .. function:: template constexpr ctre::regex_results search(Args&&... args) 96 | template constexpr ctre::regex_results search(Args&&... args) 97 | 98 | Searches for a match somewhere within the input. 99 | ``Args...`` must be either a string-like object with ``begin`` and ``end`` member functions, or a pair of forward iterators. 100 | 101 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # http://www.sphinx-doc.org/en/master/config 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'ctre' 21 | copyright = '2019, Hana Dusikova' 22 | author = 'Hana Dusikova' 23 | master_doc = 'index' 24 | primary_domain = 'cpp' 25 | highlight_language = 'cpp' 26 | 27 | # -- General configuration --------------------------------------------------- 28 | 29 | # Add any Sphinx extension module names here, as strings. They can be 30 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 31 | # ones. 32 | extensions = [ 33 | ] 34 | 35 | # Add any paths that contain templates here, relative to this directory. 36 | templates_path = ['_templates'] 37 | 38 | # List of patterns, relative to source directory, that match files and 39 | # directories to ignore when looking for source files. 40 | # This pattern also affects html_static_path and html_extra_path. 41 | exclude_patterns = [] 42 | 43 | 44 | # -- Options for HTML output ------------------------------------------------- 45 | 46 | # The theme to use for HTML and HTML Help pages. See the documentation for 47 | # a list of builtin themes. 48 | # 49 | html_theme = 'sphinx_rtd_theme' 50 | 51 | # Add any paths that contain custom static files (such as style sheets) here, 52 | # relative to this directory. They are copied after the builtin static files, 53 | # so a file named "default.css" will overwrite the builtin "default.css". 54 | html_static_path = ['_static'] 55 | -------------------------------------------------------------------------------- /docs/examples.rst: -------------------------------------------------------------------------------- 1 | Examples 2 | ======== 3 | 4 | Extracting a number from input 5 | ------------------------------ 6 | :: 7 | 8 | std::optional extract_number(std::string_view s) noexcept { 9 | if (auto m = ctre::match<"[a-z]+([0-9]+)">(s)) { 10 | return m.get<1>().to_view(); 11 | } else { 12 | return std::nullopt; 13 | } 14 | } 15 | 16 | `link to compiler explorer `_ 17 | 18 | Extracting values from date 19 | --------------------------- 20 | :: 21 | 22 | 23 | struct date { std::string_view year; std::string_view month; std::string_view day; }; 24 | std::optional extract_date(std::string_view s) noexcept { 25 | using namespace ctre::literals; 26 | if (auto [whole, year, month, day] = ctre::match<"(\\d{4})/(\\d{1,2})/(\\d{1,2})">(s); whole) { 27 | return date{year, month, day}; 28 | } else { 29 | return std::nullopt; 30 | } 31 | } 32 | 33 | //static_assert(extract_date("2018/08/27"sv).has_value()); 34 | //static_assert((*extract_date("2018/08/27"sv)).year == "2018"sv); 35 | //static_assert((*extract_date("2018/08/27"sv)).month == "08"sv); 36 | //static_assert((*extract_date("2018/08/27"sv)).day == "27"sv); 37 | 38 | `link to compiler explorer `_ 39 | 40 | Lexer 41 | ----- 42 | :: 43 | 44 | enum class type { 45 | unknown, identifier, number 46 | }; 47 | 48 | struct lex_item { 49 | type t; 50 | std::string_view c; 51 | }; 52 | 53 | std::optional lexer(std::string_view v) noexcept { 54 | if (auto [m,id,num] = ctre::match<"([a-z]+)|([0-9]+)">(v); m) { 55 | if (id) { 56 | return lex_item{type::identifier, id}; 57 | } else if (num) { 58 | return lex_item{type::number, num}; 59 | } 60 | } 61 | return std::nullopt; 62 | } 63 | 64 | `link to compiler explorer `_ 65 | 66 | Range over input 67 | ---------------- 68 | 69 | This support is preliminary and probably the API will be changed. 70 | 71 | :: 72 | 73 | auto input = "123,456,768"sv; 74 | 75 | for (auto match: ctre::range<"([0-9]+),?">(input)) { 76 | std::cout << std::string_view{match.get<0>()} << "\n"; 77 | } -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ctre 2 | ==== 3 | 4 | A compile-time (almost) PCRE-compatible regular expression matcher for C++. 5 | 6 | Overview 7 | ======== 8 | 9 | Fast compile-time regular expressions with support for matching/searching/capturing at compile-time or runtime. :: 10 | 11 | ctre::match<"REGEX">(subject); // C++20 12 | "REGEX"_ctre.match(subject); // C++17 + N3599 extension 13 | 14 | .. toctree:: 15 | :maxdepth: 2 16 | 17 | api 18 | examples 19 | regex_syntax 20 | 21 | Supported compilers 22 | =================== 23 | 24 | - clang 6.0+ (template UDL, C++17 syntax) 25 | - xcode clang 10.0+ (template UDL, C++17 syntax) 26 | - gcc 7.4+ (template UDL, C++17 syntax) 27 | - gcc 9.0+ (C++17 & C++20 cNTTP syntax) 28 | - MSVC 15.8.8+ (C++17 syntax only) 29 | 30 | Basic Usage 31 | =========== 32 | 33 | Template UDL syntax 34 | ------------------- 35 | 36 | Compiler must support N3599 extension, as GNU extension in gcc (not in GCC 9.1+) and clang. :: 37 | 38 | constexpr auto match(std::string_view sv) noexcept { 39 | using namespace ctre::literals; 40 | return "h.*"_ctre.match(sv); 41 | } 42 | 43 | If you need N3599 extension in GCC 9.1+ you can't use -pedantic mode and define the macro ``CTRE_ENABLE_LITERALS``. 44 | 45 | C++17 syntax 46 | ------------ 47 | 48 | You can provide pattern as a constexpr ``ctll::fixed_string variable``. :: 49 | 50 | static constexpr auto pattern = ctll::fixed_string{ "h.*" }; 51 | 52 | constexpr auto match(std::string_view sv) noexcept { 53 | return ctre::match(sv); 54 | } 55 | 56 | (this is tested in MSVC 15.8.8) 57 | 58 | C++20 syntax 59 | ------------ 60 | 61 | Currently only compiler which supports cNTTP syntax ``ctre::match(subject)`` is GCC 9+. :: 62 | 63 | constexpr auto match(std::string_view sv) noexcept { 64 | return ctre::match<"h.*">(sv); 65 | } 66 | 67 | -------------------------------------------------------------------------------- /docs/regex_syntax.rst: -------------------------------------------------------------------------------- 1 | Regex Syntax 2 | ============ 3 | 4 | The library supports most of the `PCRE `_ syntax with a few exceptions: 5 | 6 | - callouts 7 | - comments 8 | - conditional patterns 9 | - control characters (\\cX) 10 | - horizontal / vertical character classes (\\h\\H\\v\\V) 11 | - match point reset (\\K) 12 | - named characters 13 | - octal numbers 14 | - options / modes 15 | - subroutines 16 | - unicode grapheme cluster (\\X) 17 | 18 | TODO more detailed regex information -------------------------------------------------------------------------------- /future.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | std::string match(std::string_view sv) { 6 | if (auto match = ctre::match<"[a-z]+">(sv); match) { 7 | return match.to_string(); 8 | } else { 9 | return "not_match"; 10 | } 11 | } 12 | 13 | int main() { 14 | std::cout << match("hello") << "\n"; 15 | } -------------------------------------------------------------------------------- /gcc-bench.txt: -------------------------------------------------------------------------------- 1 | //--------- ABCD|DEFGH|EFGHI|A{4,} 2 | egrep 0m50.036s 3 | CTRE 0m3.982s 4 | PCRE 0m8.621s 5 | std::regex 0m55.058s 6 | //--------- [0-9a-fA-F]{8,16} 7 | egrep 0m32.361s 8 | CTRE 0m4.291s 9 | PCRE 0m13.958s 10 | std::regex 0m18.179s 11 | //--------- ^([0-9]{4,16})?[aA] 12 | egrep 0m12.819s 13 | CTRE 0m2.844s 14 | PCRE 0m2.614s 15 | std::regex 0m22.876s 16 | //--------- ([aAbB]{4,}|[xXyY]{4,}|[1234]{4,})0 17 | egrep 1m45.696s 18 | CTRE 0m7.623s 19 | PCRE 0m39.808s 20 | std::regex 1m2.799s 21 | -------------------------------------------------------------------------------- /include/ctll.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE_V2__CTLL__HPP 2 | #define CTRE_V2__CTLL__HPP 3 | 4 | #include "ctll/parser.hpp" 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/ctll/actions.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTLL__ACTIONS__HPP 2 | #define CTLL__ACTIONS__HPP 3 | 4 | namespace ctll { 5 | struct empty_subject { }; 6 | 7 | struct empty_actions { 8 | // dummy operator so using Actions::operator() later will not give error 9 | template static constexpr auto apply(Action, InputSymbol, Subject subject) { 10 | return subject; 11 | } 12 | }; 13 | 14 | template struct identity: public Actions { 15 | using Actions::apply; 16 | // allow empty_subject to exists 17 | template constexpr static auto apply(Action, term, empty_subject) -> empty_subject { return {}; } 18 | template constexpr static auto apply(Action, epsilon, empty_subject) -> empty_subject { return {}; } 19 | }; 20 | 21 | template struct ignore_unknown: public Actions { 22 | using Actions::apply; 23 | // allow flow thru unknown actions 24 | template constexpr static auto apply(Action, term, Subject) -> Subject { return {}; } 25 | template constexpr static auto apply(Action, epsilon, Subject) -> Subject { return {}; } 26 | }; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/ctll/grammars.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTLL__GRAMMARS__HPP 2 | #define CTLL__GRAMMARS__HPP 3 | 4 | namespace ctll { 5 | 6 | // terminal type representing symbol / character of any type 7 | template struct term { 8 | static constexpr auto value = v; 9 | }; 10 | 11 | // epsilon = nothing on input tape 12 | // also used as an command for parsing means "do nothing" 13 | struct epsilon { 14 | static constexpr auto value = '-'; 15 | }; 16 | 17 | // empty_stack_symbol = nothing on stack 18 | struct empty_stack_symbol {}; 19 | 20 | // push is alias to list 21 | template using push = list; 22 | 23 | // accept/reject type for controlling output of LL1 machine 24 | struct accept { constexpr explicit operator bool() noexcept { return true; } }; 25 | struct reject { constexpr explicit operator bool() noexcept { return false; } }; 26 | 27 | // action type, every action item in grammar must inherit from 28 | struct action { 29 | struct action_tag { }; 30 | }; 31 | 32 | // move one character forward and pop it from stack command 33 | struct pop_input { 34 | struct pop_input_tag { }; 35 | }; 36 | 37 | // additional overloads for type list 38 | template constexpr auto push_front(pop_input, list) -> list { return {}; } 39 | 40 | template constexpr auto push_front(epsilon, list) -> list { return {}; } 41 | 42 | template constexpr auto push_front(list, list) -> list { return {}; } 43 | 44 | template constexpr auto pop_front_and_push_front(T item, list l) { 45 | return push_front(item, pop_front(l)); 46 | } 47 | 48 | // SPECIAL matching types for nicer grammars 49 | 50 | // match any term 51 | struct anything { 52 | constexpr inline anything() noexcept { } 53 | template constexpr anything(term) noexcept; 54 | }; 55 | 56 | // match range of term A-B 57 | template struct range { 58 | constexpr inline range() noexcept { } 59 | //template constexpr range(term) noexcept requires (A <= V) && (V <= B); 60 | template > constexpr range(term) noexcept; 61 | }; 62 | 63 | #ifdef __EDG__ 64 | template struct contains { 65 | static constexpr bool value = ((Set == V) || ... || false); 66 | }; 67 | #endif 68 | 69 | // match terms defined in set 70 | template struct set { 71 | constexpr inline set() noexcept { } 72 | #ifdef __EDG__ 73 | template ::value>> constexpr set(term) noexcept; 74 | #else 75 | template > constexpr set(term) noexcept; 76 | #endif 77 | }; 78 | 79 | // match terms not defined in set 80 | template struct neg_set { 81 | constexpr inline neg_set() noexcept { } 82 | 83 | #ifdef __EDG__ 84 | template ::value>> constexpr neg_set(term) noexcept; 85 | #else 86 | template > constexpr neg_set(term) noexcept; 87 | #endif 88 | }; 89 | 90 | // AUGMENTED grammar which completes user-defined grammar for all other cases 91 | template struct augment_grammar: public Grammar { 92 | // start nonterminal is defined in parent type 93 | using typename Grammar::_start; 94 | 95 | // grammar rules are inherited from Grammar parent type 96 | using Grammar::rule; 97 | 98 | // term on stack and on input means pop_input; 99 | template static constexpr auto rule(term, term) -> ctll::pop_input; 100 | 101 | // if the type on stack (range, set, neg_set, anything) is constructible from the terminal => pop_input 102 | template static constexpr auto rule(Expected, term) -> std::enable_if_t>, ctll::pop_input>; 103 | 104 | // empty stack and empty input means we are accepting 105 | static constexpr auto rule(empty_stack_symbol, epsilon) -> ctll::accept; 106 | 107 | // not matching anything else => reject 108 | static constexpr auto rule(...) -> ctll::reject; 109 | 110 | // start stack is just a list; 111 | using start_stack = list; 112 | }; 113 | 114 | 115 | 116 | } 117 | 118 | 119 | 120 | 121 | 122 | #endif 123 | 124 | -------------------------------------------------------------------------------- /include/ctll/list.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTLL__TYPE_STACK__HPP 2 | #define CTLL__TYPE_STACK__HPP 3 | 4 | #include "utilities.hpp" 5 | 6 | namespace ctll { 7 | 8 | template struct list { }; 9 | 10 | struct _nothing { }; 11 | 12 | using empty_list = list<>; 13 | 14 | // calculate size of list content 15 | template constexpr auto size(list) noexcept { return sizeof...(Ts); } 16 | 17 | 18 | // check if the list is empty 19 | template constexpr bool empty(list) noexcept { return false; } 20 | constexpr bool empty(empty_list) { return true; } 21 | 22 | 23 | // concat two lists together left to right 24 | template constexpr auto concat(list, list) noexcept -> list { return {}; } 25 | 26 | 27 | // push something to the front of a list 28 | template constexpr auto push_front(T, list) noexcept -> list { return {}; } 29 | 30 | 31 | // pop element from the front of a list 32 | template constexpr auto pop_front(list) noexcept -> list { return {}; } 33 | constexpr auto pop_front(empty_list) -> empty_list; 34 | 35 | // pop element from the front of a list and return new typelist too 36 | template struct list_pop_pair { 37 | Front front{}; 38 | List list{}; 39 | constexpr list_pop_pair() = default; 40 | }; 41 | 42 | template constexpr auto pop_and_get_front(list, T = T()) noexcept -> list_pop_pair> { return {}; } 43 | template constexpr auto pop_and_get_front(empty_list, T = T()) noexcept -> list_pop_pair { return {}; } 44 | 45 | 46 | // return front of the list 47 | template constexpr auto front(list, T = T()) noexcept -> Head { return {}; } 48 | template constexpr auto front(empty_list, T = T()) noexcept -> T { return {}; } 49 | 50 | // rotate list 51 | template struct rotate_item { 52 | template friend constexpr auto operator+(list, rotate_item) noexcept -> list { return {}; } 53 | }; 54 | 55 | template constexpr auto rotate(list) -> decltype((list<>{} + ... + rotate_item{})) { 56 | return {}; 57 | } 58 | 59 | // set operations 60 | template struct item_matcher { 61 | struct not_selected { 62 | template friend constexpr auto operator+(list, not_selected) -> list; 63 | }; 64 | template struct wrapper { 65 | template friend constexpr auto operator+(list, wrapper) -> list; 66 | }; 67 | 68 | static constexpr auto check(T) { return std::true_type{}; } 69 | static constexpr auto check(...) { return std::false_type{}; } 70 | static constexpr auto select(T) { return not_selected{}; } 71 | template static constexpr auto select(Y) { return wrapper{}; } 72 | }; 73 | 74 | template constexpr bool exists_in(T, list) noexcept { 75 | return (item_matcher::check(Ts{}) || ... || false); 76 | } 77 | 78 | template constexpr auto add_item(T item, list l) noexcept { 79 | if constexpr (exists_in(item, l)) { 80 | return l; 81 | } else { 82 | return list{}; 83 | } 84 | } 85 | 86 | template constexpr auto remove_item(T, list) noexcept { 87 | item_matcher matcher; 88 | return decltype((list<>{} + ... + matcher.select(Ts{}))){}; 89 | } 90 | 91 | } 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /include/ctll/utilities.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTLL__UTILITIES__HPP 2 | #define CTLL__UTILITIES__HPP 3 | 4 | #ifndef CTLL_IN_A_MODULE 5 | #include 6 | #endif 7 | 8 | #ifdef CTLL_IN_A_MODULE 9 | #define CTLL_EXPORT export 10 | #else 11 | #define CTLL_EXPORT 12 | #endif 13 | 14 | #if defined __cpp_nontype_template_parameter_class 15 | #define CTLL_CNTTP_COMPILER_CHECK 1 16 | #elif defined __cpp_nontype_template_args 17 | // compiler which defines correctly feature test macro (not you clang) 18 | #if __cpp_nontype_template_args >= 201911L 19 | #define CTLL_CNTTP_COMPILER_CHECK 1 20 | #elif __cpp_nontype_template_args >= 201411L 21 | // appleclang 13+ 22 | #if defined __apple_build_version__ 23 | #if defined __clang_major__ && __clang_major__ >= 13 24 | // but only in c++20 and more 25 | #if __cplusplus > 201703L 26 | #define CTLL_CNTTP_COMPILER_CHECK 1 27 | #endif 28 | #endif 29 | #else 30 | // clang 12+ 31 | #if defined __clang_major__ && __clang_major__ >= 12 32 | // but only in c++20 and more 33 | #if __cplusplus > 201703L 34 | #define CTLL_CNTTP_COMPILER_CHECK 1 35 | #endif 36 | #endif 37 | #endif 38 | #endif 39 | #endif 40 | 41 | #ifndef CTLL_CNTTP_COMPILER_CHECK 42 | #define CTLL_CNTTP_COMPILER_CHECK 0 43 | #endif 44 | 45 | #ifdef _MSC_VER 46 | #define CTLL_FORCE_INLINE __forceinline 47 | #else 48 | #define CTLL_FORCE_INLINE __attribute__((always_inline)) 49 | #endif 50 | 51 | namespace ctll { 52 | 53 | template struct conditional_helper; 54 | 55 | template <> struct conditional_helper { 56 | template using type = A; 57 | }; 58 | 59 | template <> struct conditional_helper { 60 | template using type = B; 61 | }; 62 | 63 | template using conditional = typename conditional_helper::template type; 64 | 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /include/ctre-unicode.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE_V2__CTRE_UNICODE__HPP 2 | #define CTRE_V2__CTRE_UNICODE__HPP 3 | 4 | #include "ctre.hpp" 5 | #include "unicode-db.hpp" 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /include/ctre.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE_V2__CTRE__HPP 2 | #define CTRE_V2__CTRE__HPP 3 | 4 | #include "ctre/literals.hpp" 5 | #include "ctre/functions.hpp" 6 | #include "ctre/iterators.hpp" 7 | #include "ctre/range.hpp" 8 | #include "ctre/operators.hpp" 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/ctre/actions/asserts.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__ASSERTS__HPP 2 | #define CTRE__ACTIONS__ASSERTS__HPP 3 | 4 | // push_assert_begin 5 | template static constexpr auto apply(pcre::push_assert_begin, ctll::term, pcre_context, Parameters> subject) { 6 | return pcre_context{ctll::push_front(assert_line_begin(), subject.stack), subject.parameters}; 7 | } 8 | 9 | // push_assert_end 10 | template static constexpr auto apply(pcre::push_assert_end, ctll::term, pcre_context, Parameters> subject) { 11 | return pcre_context{ctll::push_front(assert_line_end(), subject.stack), subject.parameters}; 12 | } 13 | 14 | // push_assert_begin 15 | template static constexpr auto apply(pcre::push_assert_subject_begin, ctll::term, pcre_context, Parameters> subject) { 16 | return pcre_context{ctll::push_front(assert_subject_begin(), subject.stack), subject.parameters}; 17 | } 18 | 19 | // push_assert_subject_end 20 | template static constexpr auto apply(pcre::push_assert_subject_end, ctll::term, pcre_context, Parameters> subject) { 21 | return pcre_context{ctll::push_front(assert_subject_end(), subject.stack), subject.parameters}; 22 | } 23 | 24 | // push_assert_subject_end_with_lineend 25 | template static constexpr auto apply(pcre::push_assert_subject_end_with_lineend, ctll::term, pcre_context, Parameters> subject) { 26 | return pcre_context{ctll::push_front(assert_subject_end_line(), subject.stack), subject.parameters}; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/ctre/actions/atomic_group.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__ATOMIC_GROUP__HPP 2 | #define CTRE__ACTIONS__ATOMIC_GROUP__HPP 3 | 4 | // atomic start 5 | template static constexpr auto apply(pcre::start_atomic, ctll::term, pcre_context, pcre_parameters>) { 6 | return pcre_context{ctll::list(), pcre_parameters()}; 7 | } 8 | 9 | // atomic 10 | template static constexpr auto apply(pcre::make_atomic, ctll::term, pcre_context, pcre_parameters>) { 11 | return pcre_context{ctll::list, Ts...>(), pcre_parameters()}; 12 | } 13 | 14 | // atomic sequence 15 | template static constexpr auto apply(pcre::make_atomic, ctll::term, pcre_context, atomic_start, Ts...>, pcre_parameters>) { 16 | return pcre_context{ctll::list, Ts...>(), pcre_parameters()}; 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/ctre/actions/backreference.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__BACKREFERENCE__HPP 2 | #define CTRE__ACTIONS__BACKREFERENCE__HPP 3 | 4 | // backreference with name 5 | template static constexpr auto apply(pcre::make_back_reference, ctll::term, pcre_context, Ts...>, pcre_parameters>) { 6 | return pcre_context{ctll::push_front(back_reference_with_name>(), ctll::list()), pcre_parameters()}; 7 | } 8 | 9 | // with just a number 10 | template static constexpr auto apply(pcre::make_back_reference, ctll::term, pcre_context, Ts...>, pcre_parameters>) { 11 | // if we are looking outside of existing list of Ids ... reject input during parsing 12 | if constexpr (Counter < Id) { 13 | return ctll::reject{}; 14 | } else { 15 | return pcre_context{ctll::push_front(back_reference(), ctll::list()), pcre_parameters()}; 16 | } 17 | } 18 | 19 | // relative backreference 20 | template static constexpr auto apply(pcre::make_relative_back_reference, ctll::term, [[maybe_unused]] pcre_context, Ts...>, pcre_parameters>) { 21 | // if we are looking outside of existing list of Ids ... reject input during parsing 22 | if constexpr (Counter < Id) { 23 | return ctll::reject{}; 24 | } else { 25 | constexpr size_t absolute_id = (Counter + 1) - Id; 26 | return pcre_context{ctll::push_front(back_reference(), ctll::list()), pcre_parameters()}; 27 | } 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/ctre/actions/boundaries.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__BOUNDARIES__HPP 2 | #define CTRE__ACTIONS__BOUNDARIES__HPP 3 | 4 | // push_word_boundary 5 | template static constexpr auto apply(pcre::push_word_boundary, ctll::term, pcre_context, Parameters> subject) { 6 | return pcre_context{ctll::push_front(boundary(), subject.stack), subject.parameters}; 7 | } 8 | 9 | // push_not_word_boundary 10 | template static constexpr auto apply(pcre::push_not_word_boundary, ctll::term, pcre_context, Parameters> subject) { 11 | return pcre_context{ctll::push_front(boundary>(), subject.stack), subject.parameters}; 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/ctre/actions/capture.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__CAPTURE__HPP 2 | #define CTRE__ACTIONS__CAPTURE__HPP 3 | 4 | // prepare_capture 5 | template static constexpr auto apply(pcre::prepare_capture, ctll::term, pcre_context, pcre_parameters>) { 6 | return pcre_context{ctll::push_front(capture_id(), ctll::list()), pcre_parameters()}; 7 | } 8 | 9 | // reset_capture 10 | template static constexpr auto apply(pcre::reset_capture, ctll::term, pcre_context, Ts...>, pcre_parameters>) { 11 | return pcre_context{ctll::list(), pcre_parameters()}; 12 | } 13 | 14 | // capture 15 | template static constexpr auto apply(pcre::make_capture, ctll::term, pcre_context, Ts...>, pcre_parameters>) { 16 | return pcre_context{ctll::push_front(capture(), ctll::list()), pcre_parameters()}; 17 | } 18 | // capture (sequence) 19 | template static constexpr auto apply(pcre::make_capture, ctll::term, pcre_context, capture_id, Ts...>, pcre_parameters>) { 20 | return pcre_context{ctll::push_front(capture(), ctll::list()), pcre_parameters()}; 21 | } 22 | // push_name 23 | template static constexpr auto apply(pcre::push_name, ctll::term, pcre_context, Parameters> subject) { 24 | return pcre_context{ctll::push_front(id(), subject.stack), subject.parameters}; 25 | } 26 | // push_name (concat) 27 | template static constexpr auto apply(pcre::push_name, ctll::term, pcre_context, Ts...>, Parameters> subject) { 28 | return pcre_context{ctll::push_front(id(), ctll::list()), subject.parameters}; 29 | } 30 | // capture with name 31 | template static constexpr auto apply(pcre::make_capture_with_name, ctll::term, pcre_context, capture_id, Ts...>, pcre_parameters>) { 32 | return pcre_context{ctll::push_front(capture_with_name, A>(), ctll::list()), pcre_parameters()}; 33 | } 34 | // capture with name (sequence) 35 | template static constexpr auto apply(pcre::make_capture_with_name, ctll::term, pcre_context, id, capture_id, Ts...>, pcre_parameters>) { 36 | return pcre_context{ctll::push_front(capture_with_name, Content...>(), ctll::list()), pcre_parameters()}; 37 | } 38 | 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /include/ctre/actions/characters.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__CHARACTERS__HPP 2 | #define CTRE__ACTIONS__CHARACTERS__HPP 3 | 4 | // push character 5 | template static constexpr auto apply(pcre::push_character, ctll::term, pcre_context, Parameters> subject) { 6 | return pcre_context{ctll::push_front(character(), subject.stack), subject.parameters}; 7 | } 8 | // push_any_character 9 | template static constexpr auto apply(pcre::push_character_anything, ctll::term, pcre_context, Parameters> subject) { 10 | return pcre_context{ctll::push_front(any(), subject.stack), subject.parameters}; 11 | } 12 | // character_alarm 13 | template static constexpr auto apply(pcre::push_character_alarm, ctll::term, pcre_context, Parameters> subject) { 14 | return pcre_context{ctll::push_front(character<'\x07'>(), subject.stack), subject.parameters}; 15 | } 16 | // character_escape 17 | template static constexpr auto apply(pcre::push_character_escape, ctll::term, pcre_context, Parameters> subject) { 18 | return pcre_context{ctll::push_front(character<'\x14'>(), subject.stack), subject.parameters}; 19 | } 20 | // character_formfeed 21 | template static constexpr auto apply(pcre::push_character_formfeed, ctll::term, pcre_context, Parameters> subject) { 22 | return pcre_context{ctll::push_front(character<'\x0C'>(), subject.stack), subject.parameters}; 23 | } 24 | // push_character_newline 25 | template static constexpr auto apply(pcre::push_character_newline, ctll::term, pcre_context, Parameters> subject) { 26 | return pcre_context{ctll::push_front(character<'\x0A'>(), subject.stack), subject.parameters}; 27 | } 28 | // push_character_null 29 | template static constexpr auto apply(pcre::push_character_null, ctll::term, pcre_context, Parameters> subject) { 30 | return pcre_context{ctll::push_front(character<'\0'>(), subject.stack), subject.parameters}; 31 | } 32 | // push_character_return_carriage 33 | template static constexpr auto apply(pcre::push_character_return_carriage, ctll::term, pcre_context, Parameters> subject) { 34 | return pcre_context{ctll::push_front(character<'\x0D'>(), subject.stack), subject.parameters}; 35 | } 36 | // push_character_tab 37 | template static constexpr auto apply(pcre::push_character_tab, ctll::term, pcre_context, Parameters> subject) { 38 | return pcre_context{ctll::push_front(character<'\x09'>(), subject.stack), subject.parameters}; 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /include/ctre/actions/class.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__CLASS__HPP 2 | #define CTRE__ACTIONS__CLASS__HPP 3 | 4 | // class_digit 5 | template static constexpr auto apply(pcre::class_digit, ctll::term, pcre_context, Parameters> subject) { 6 | return pcre_context{ctll::push_front(ctre::set(), subject.stack), subject.parameters}; 7 | } 8 | // class_non_digit 9 | template static constexpr auto apply(pcre::class_nondigit, ctll::term, pcre_context, Parameters> subject) { 10 | return pcre_context{ctll::push_front(ctre::negative_set(), subject.stack), subject.parameters}; 11 | } 12 | // class_space 13 | template static constexpr auto apply(pcre::class_space, ctll::term, pcre_context, Parameters> subject) { 14 | return pcre_context{ctll::push_front(ctre::set(), subject.stack), subject.parameters}; 15 | } 16 | // class_nonspace 17 | template static constexpr auto apply(pcre::class_nonspace, ctll::term, pcre_context, Parameters> subject) { 18 | return pcre_context{ctll::push_front(ctre::negative_set(), subject.stack), subject.parameters}; 19 | } 20 | 21 | // class_horizontal_space 22 | template static constexpr auto apply(pcre::class_horizontal_space, ctll::term, pcre_context, Parameters> subject) { 23 | return pcre_context{ctll::push_front(ctre::set(), subject.stack), subject.parameters}; 24 | } 25 | // class_horizontal_nonspace 26 | template static constexpr auto apply(pcre::class_non_horizontal_space, ctll::term, pcre_context, Parameters> subject) { 27 | return pcre_context{ctll::push_front(ctre::negative_set(), subject.stack), subject.parameters}; 28 | } 29 | // class_vertical_space 30 | template static constexpr auto apply(pcre::class_vertical_space, ctll::term, pcre_context, Parameters> subject) { 31 | return pcre_context{ctll::push_front(ctre::set(), subject.stack), subject.parameters}; 32 | } 33 | // class_vertical_nonspace 34 | template static constexpr auto apply(pcre::class_non_vertical_space, ctll::term, pcre_context, Parameters> subject) { 35 | return pcre_context{ctll::push_front(ctre::negative_set(), subject.stack), subject.parameters}; 36 | } 37 | 38 | // class_word 39 | template static constexpr auto apply(pcre::class_word, ctll::term, pcre_context, Parameters> subject) { 40 | return pcre_context{ctll::push_front(ctre::set(), subject.stack), subject.parameters}; 41 | } 42 | // class_nonword 43 | template static constexpr auto apply(pcre::class_nonword, ctll::term, pcre_context, Parameters> subject) { 44 | return pcre_context{ctll::push_front(ctre::negative_set(), subject.stack), subject.parameters}; 45 | } 46 | // class_nonnewline 47 | template static constexpr auto apply(pcre::class_nonnewline, ctll::term, pcre_context, Parameters> subject) { 48 | return pcre_context{ctll::push_front(ctre::negative_set>(), subject.stack), subject.parameters}; 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /include/ctre/actions/fusion.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__FUSION__HPP 2 | #define CTRE__ACTIONS__FUSION__HPP 3 | 4 | static constexpr size_t combine_max_repeat_length(size_t A, size_t B) { 5 | if (A && B) return A+B; 6 | else return 0; 7 | } 8 | 9 | template static constexpr auto combine_repeat(repeat, repeat) { 10 | return repeat(); 11 | } 12 | 13 | template static constexpr auto combine_repeat(lazy_repeat, lazy_repeat) { 14 | return lazy_repeat(); 15 | } 16 | 17 | template static constexpr auto combine_repeat(possessive_repeat, possessive_repeat) { 18 | [[maybe_unused]] constexpr bool first_is_unbounded = (MaxA == 0); 19 | [[maybe_unused]] constexpr bool second_is_nonempty = (MinB > 0); 20 | [[maybe_unused]] constexpr bool second_can_be_empty = (MinB == 0); 21 | 22 | if constexpr (first_is_unbounded && second_is_nonempty) { 23 | // will always reject, but I keep the content, so I have some amount of captures 24 | return sequence(); 25 | } else if constexpr (first_is_unbounded) { 26 | return possessive_repeat(); 27 | } else if constexpr (second_can_be_empty) { 28 | return possessive_repeat(); 29 | } else { 30 | return possessive_repeat(); 31 | } 32 | } 33 | 34 | // concat repeat sequences 35 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context, repeat, Ts...>, Parameters> subject) { 36 | return pcre_context{ctll::push_front(combine_repeat(repeat(), repeat()), ctll::list()), subject.parameters}; 37 | } 38 | 39 | // concat lazy repeat sequences 40 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context, lazy_repeat, Ts...>, Parameters> subject) { 41 | return pcre_context{ctll::push_front(combine_repeat(lazy_repeat(), lazy_repeat()), ctll::list()), subject.parameters}; 42 | } 43 | 44 | // concat possessive repeat seqeunces 45 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context, possessive_repeat, Ts...>, Parameters> subject) { 46 | return pcre_context{ctll::push_front(combine_repeat(possessive_repeat(), possessive_repeat()), ctll::list()), subject.parameters}; 47 | } 48 | 49 | // concat repeat sequences into sequence 50 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context, As...>,repeat,Ts...>, Parameters> subject) { 51 | using result = decltype(combine_repeat(repeat(), repeat())); 52 | 53 | return pcre_context{ctll::push_front(sequence(), ctll::list()), subject.parameters}; 54 | } 55 | 56 | // concat lazy repeat sequences into sequence 57 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context, As...>,lazy_repeat,Ts...>, Parameters> subject) { 58 | using result = decltype(combine_repeat(lazy_repeat(), lazy_repeat())); 59 | 60 | return pcre_context{ctll::push_front(sequence(), ctll::list()), subject.parameters}; 61 | } 62 | 63 | // concat possessive repeat sequences into sequence 64 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context, As...>,possessive_repeat,Ts...>, Parameters> subject) { 65 | using result = decltype(combine_repeat(possessive_repeat(), possessive_repeat())); 66 | 67 | return pcre_context{ctll::push_front(sequence(), ctll::list()), subject.parameters}; 68 | } 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /include/ctre/actions/hexdec.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__HEXDEC__HPP 2 | #define CTRE__ACTIONS__HEXDEC__HPP 3 | 4 | // hexdec character support (seed) 5 | template static constexpr auto apply(pcre::create_hexdec, ctll::term, pcre_context, Parameters> subject) { 6 | return pcre_context{ctll::push_front(number<0ull>(), subject.stack), subject.parameters}; 7 | } 8 | // hexdec character support (push value) 9 | template static constexpr auto apply(pcre::push_hexdec, ctll::term, pcre_context, Ts...>, Parameters> subject) { 10 | constexpr auto previous = N << 4ull; 11 | if constexpr (V >= 'a' && V <= 'f') { 12 | return pcre_context{ctll::push_front(number<(previous + (V - 'a' + 10))>(), ctll::list()), subject.parameters}; 13 | } else if constexpr (V >= 'A' && V <= 'F') { 14 | return pcre_context{ctll::push_front(number<(previous + (V - 'A' + 10))>(), ctll::list()), subject.parameters}; 15 | } else { 16 | return pcre_context{ctll::push_front(number<(previous + (V - '0'))>(), ctll::list()), subject.parameters}; 17 | } 18 | } 19 | // hexdec character support (convert to character) 20 | template static constexpr auto apply(pcre::finish_hexdec, ctll::term, pcre_context, Ts...>, Parameters> subject) { 21 | constexpr size_t max_char = (std::numeric_limits::max)(); 22 | if constexpr (N <= max_char) { 23 | return pcre_context{ctll::push_front(character(), ctll::list()), subject.parameters}; 24 | } else { 25 | return pcre_context{ctll::push_front(character(), ctll::list()), subject.parameters}; 26 | } 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/ctre/actions/look.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__LOOKAHEAD__HPP 2 | #define CTRE__ACTIONS__LOOKAHEAD__HPP 3 | 4 | // lookahead positive start 5 | template static constexpr auto apply(pcre::start_lookahead_positive, ctll::term, pcre_context, pcre_parameters>) { 6 | return pcre_context{ctll::list>, Ts...>(), pcre_parameters()}; 7 | } 8 | 9 | // lookahead positive end 10 | template static constexpr auto apply(pcre::look_finish, ctll::term, pcre_context>, Ts...>, pcre_parameters>) { 11 | return pcre_context{ctll::list, Ts...>(), pcre_parameters()}; 12 | } 13 | 14 | // lookahead positive end (sequence) 15 | template static constexpr auto apply(pcre::look_finish, ctll::term, pcre_context, look_start>, Ts...>, pcre_parameters>) { 16 | return pcre_context{ctll::list, Ts...>(), pcre_parameters()}; 17 | } 18 | 19 | // lookahead negative start 20 | template static constexpr auto apply(pcre::start_lookahead_negative, ctll::term, pcre_context, pcre_parameters>) { 21 | return pcre_context{ctll::list>, Ts...>(), pcre_parameters()}; 22 | } 23 | 24 | // lookahead negative end 25 | template static constexpr auto apply(pcre::look_finish, ctll::term, pcre_context>, Ts...>, pcre_parameters>) { 26 | return pcre_context{ctll::list, Ts...>(), pcre_parameters()}; 27 | } 28 | 29 | // lookahead negative end (sequence) 30 | template static constexpr auto apply(pcre::look_finish, ctll::term, pcre_context, look_start>, Ts...>, pcre_parameters>) { 31 | return pcre_context{ctll::list, Ts...>(), pcre_parameters()}; 32 | } 33 | 34 | // LOOKBEHIND 35 | 36 | // lookbehind positive start 37 | template static constexpr auto apply(pcre::start_lookbehind_positive, ctll::term, pcre_context, pcre_parameters>) { 38 | return pcre_context{ctll::list>, Ts...>(), pcre_parameters()}; 39 | } 40 | 41 | // lookbehind positive end 42 | template static constexpr auto apply(pcre::look_finish, ctll::term, pcre_context>, Ts...>, pcre_parameters>) { 43 | return pcre_context{ctll::list, Ts...>(), pcre_parameters()}; 44 | } 45 | 46 | // lookbehind positive end (sequence) 47 | template static constexpr auto apply(pcre::look_finish, ctll::term, pcre_context, look_start>, Ts...>, pcre_parameters>) { 48 | using my_lookbehind = decltype(ctre::convert_to_basic_list(ctll::rotate(ctll::list{}))); 49 | return pcre_context{ctll::list(), pcre_parameters()}; 50 | } 51 | 52 | // lookbehind negative start 53 | template static constexpr auto apply(pcre::start_lookbehind_negative, ctll::term, pcre_context, pcre_parameters>) { 54 | return pcre_context{ctll::list>, Ts...>(), pcre_parameters()}; 55 | } 56 | 57 | // lookbehind negative end 58 | template static constexpr auto apply(pcre::look_finish, ctll::term, pcre_context>, Ts...>, pcre_parameters>) { 59 | return pcre_context{ctll::list, Ts...>(), pcre_parameters()}; 60 | } 61 | 62 | // lookbehind negative end (sequence) 63 | template static constexpr auto apply(pcre::look_finish, ctll::term, pcre_context, look_start>, Ts...>, pcre_parameters>) { 64 | using my_lookbehind = decltype(ctre::convert_to_basic_list(ctll::rotate(ctll::list{}))); 65 | return pcre_context{ctll::list(), pcre_parameters()}; 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /include/ctre/actions/mode.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__MODE__HPP 2 | #define CTRE__ACTIONS__MODE__HPP 3 | 4 | // we need to reset counter and wrap Mode into mode_switch 5 | template static constexpr auto apply_mode(Mode, ctll::list, Parameters) { 6 | return pcre_context, Ts...>, Parameters>{}; 7 | } 8 | 9 | template static constexpr auto apply_mode(Mode, ctll::list, Ts...>, pcre_parameters) { 10 | return pcre_context, Ts...>, pcre_parameters>{}; 11 | } 12 | 13 | // catch a semantic action into mode 14 | template static constexpr auto apply(pcre::mode_case_insensitive mode, ctll::term,pcre_context, Parameters>) { 15 | return apply_mode(mode, ctll::list{}, Parameters{}); 16 | } 17 | 18 | template static constexpr auto apply(pcre::mode_case_sensitive mode, ctll::term,pcre_context, Parameters>) { 19 | return apply_mode(mode, ctll::list{}, Parameters{}); 20 | } 21 | 22 | template static constexpr auto apply(pcre::mode_singleline mode, ctll::term,pcre_context, Parameters>) { 23 | return apply_mode(mode, ctll::list{}, Parameters{}); 24 | } 25 | 26 | template static constexpr auto apply(pcre::mode_multiline mode, ctll::term,pcre_context, Parameters>) { 27 | return apply_mode(mode, ctll::list{}, Parameters{}); 28 | } 29 | 30 | // to properly reset capture 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /include/ctre/actions/named_class.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__NAMED_CLASS__HPP 2 | #define CTRE__ACTIONS__NAMED_CLASS__HPP 3 | 4 | // class_named_alnum 5 | template static constexpr auto apply(pcre::class_named_alnum, ctll::term, pcre_context, Parameters> subject) { 6 | return pcre_context{ctll::push_front(ctre::alphanum_chars(), subject.stack), subject.parameters}; 7 | } 8 | // class_named_alpha 9 | template static constexpr auto apply(pcre::class_named_alpha, ctll::term, pcre_context, Parameters> subject) { 10 | return pcre_context{ctll::push_front(ctre::alpha_chars(), subject.stack), subject.parameters}; 11 | } 12 | // class_named_digit 13 | template static constexpr auto apply(pcre::class_named_digit, ctll::term, pcre_context, Parameters> subject) { 14 | return pcre_context{ctll::push_front(ctre::digit_chars(), subject.stack), subject.parameters}; 15 | } 16 | // class_named_ascii 17 | template static constexpr auto apply(pcre::class_named_ascii, ctll::term, pcre_context, Parameters> subject) { 18 | return pcre_context{ctll::push_front(ctre::ascii_chars(), subject.stack), subject.parameters}; 19 | } 20 | // class_named_blank 21 | template static constexpr auto apply(pcre::class_named_blank, ctll::term, pcre_context, Parameters> subject) { 22 | return pcre_context{ctll::push_front(ctre::enumeration<' ','\t'>(), subject.stack), subject.parameters}; 23 | } 24 | // class_named_cntrl 25 | template static constexpr auto apply(pcre::class_named_cntrl, ctll::term, pcre_context, Parameters> subject) { 26 | return pcre_context{ctll::push_front(ctre::set, ctre::character<'\x7F'>>(), subject.stack), subject.parameters}; 27 | } 28 | // class_named_graph 29 | template static constexpr auto apply(pcre::class_named_graph, ctll::term, pcre_context, Parameters> subject) { 30 | return pcre_context{ctll::push_front(ctre::char_range<'\x21','\x7E'>(), subject.stack), subject.parameters}; 31 | } 32 | // class_named_lower 33 | template static constexpr auto apply(pcre::class_named_lower, ctll::term, pcre_context, Parameters> subject) { 34 | return pcre_context{ctll::push_front(ctre::char_range<'a','z'>(), subject.stack), subject.parameters}; 35 | } 36 | // class_named_upper 37 | template static constexpr auto apply(pcre::class_named_upper, ctll::term, pcre_context, Parameters> subject) { 38 | return pcre_context{ctll::push_front(ctre::char_range<'A','Z'>(), subject.stack), subject.parameters}; 39 | } 40 | // class_named_print 41 | template static constexpr auto apply(pcre::class_named_print, ctll::term, pcre_context, Parameters> subject) { 42 | return pcre_context{ctll::push_front(ctre::char_range<'\x20','\x7E'>(), subject.stack), subject.parameters}; 43 | } 44 | // class_named_space 45 | template static constexpr auto apply(pcre::class_named_space, ctll::term, pcre_context, Parameters> subject) { 46 | return pcre_context{ctll::push_front(space_chars(), subject.stack), subject.parameters}; 47 | } 48 | // class_named_word 49 | template static constexpr auto apply(pcre::class_named_word, ctll::term, pcre_context, Parameters> subject) { 50 | return pcre_context{ctll::push_front(word_chars(), subject.stack), subject.parameters}; 51 | } 52 | // class_named_punct 53 | template static constexpr auto apply(pcre::class_named_punct, ctll::term, pcre_context, Parameters> subject) { 54 | return pcre_context{ctll::push_front(punct_chars(), subject.stack), subject.parameters}; 55 | } 56 | // class_named_xdigit 57 | template static constexpr auto apply(pcre::class_named_xdigit, ctll::term, pcre_context, Parameters> subject) { 58 | return pcre_context{ctll::push_front(xdigit_chars(), subject.stack), subject.parameters}; 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /include/ctre/actions/options.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__OPTIONS__HPP 2 | #define CTRE__ACTIONS__OPTIONS__HPP 3 | 4 | // empty option for alternate 5 | template static constexpr auto apply(pcre::push_empty, ctll::term, pcre_context, Parameters> subject) { 6 | return pcre_context{ctll::push_front(empty(), subject.stack), subject.parameters}; 7 | } 8 | 9 | // empty option for empty regex 10 | template static constexpr auto apply(pcre::push_empty, ctll::epsilon, pcre_context, Parameters> subject) { 11 | return pcre_context{ctll::push_front(empty(), subject.stack), subject.parameters}; 12 | } 13 | 14 | // make_alternate (A|B) 15 | template static constexpr auto apply(pcre::make_alternate, ctll::term, pcre_context, Parameters> subject) { 16 | return pcre_context{ctll::push_front(select(), ctll::list()), subject.parameters}; 17 | } 18 | // make_alternate (As..)|B => (As..|B) 19 | template static constexpr auto apply(pcre::make_alternate, ctll::term, pcre_context, A, Ts...>, Parameters> subject) { 20 | return pcre_context{ctll::push_front(select(), ctll::list()), subject.parameters}; 21 | } 22 | 23 | 24 | // make_optional 25 | template static constexpr auto apply(pcre::make_optional, ctll::term, pcre_context, Parameters> subject) { 26 | return pcre_context{ctll::push_front(optional(), ctll::list()), subject.parameters}; 27 | } 28 | 29 | template static constexpr auto apply(pcre::make_optional, ctll::term, pcre_context, Ts...>, Parameters> subject) { 30 | return pcre_context{ctll::push_front(optional(), ctll::list()), subject.parameters}; 31 | } 32 | 33 | // prevent from creating wrapped optionals 34 | template static constexpr auto apply(pcre::make_optional, ctll::term, pcre_context, Ts...>, Parameters> subject) { 35 | return pcre_context{ctll::push_front(optional(), ctll::list()), subject.parameters}; 36 | } 37 | 38 | // in case inner optional is lazy, result should be lazy too 39 | template static constexpr auto apply(pcre::make_optional, ctll::term, pcre_context, Ts...>, Parameters> subject) { 40 | return pcre_context{ctll::push_front(lazy_optional(), ctll::list()), subject.parameters}; 41 | } 42 | 43 | // make_lazy (optional) 44 | template static constexpr auto apply(pcre::make_lazy, ctll::term, pcre_context, Ts...>, Parameters> subject) { 45 | return pcre_context{ctll::push_front(lazy_optional(), ctll::list()), subject.parameters}; 46 | } 47 | 48 | // if you already got a lazy optional, make_lazy is no-op 49 | template static constexpr auto apply(pcre::make_lazy, ctll::term, pcre_context, Ts...>, Parameters> subject) { 50 | return pcre_context{ctll::push_front(lazy_optional(), ctll::list()), subject.parameters}; 51 | } 52 | 53 | 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /include/ctre/actions/properties.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__PROPERTIES__HPP 2 | #define CTRE__ACTIONS__PROPERTIES__HPP 3 | 4 | // push_property_name 5 | template static constexpr auto apply(pcre::push_property_name, ctll::term, pcre_context, Parameters> subject) { 6 | return pcre_context{ctll::push_front(property_name(), subject.stack), subject.parameters}; 7 | } 8 | // push_property_name (concat) 9 | template static constexpr auto apply(pcre::push_property_name, ctll::term, pcre_context, Ts...>, Parameters> subject) { 10 | return pcre_context{ctll::push_front(property_name(), ctll::list()), subject.parameters}; 11 | } 12 | 13 | // push_property_value 14 | template static constexpr auto apply(pcre::push_property_value, ctll::term, pcre_context, Parameters> subject) { 15 | return pcre_context{ctll::push_front(property_value(), subject.stack), subject.parameters}; 16 | } 17 | // push_property_value (concat) 18 | template static constexpr auto apply(pcre::push_property_value, ctll::term, pcre_context, Ts...>, Parameters> subject) { 19 | return pcre_context{ctll::push_front(property_value(), ctll::list()), subject.parameters}; 20 | } 21 | 22 | // make_property 23 | template static constexpr auto apply(pcre::make_property, ctll::term, [[maybe_unused]] pcre_context, Ts...>, Parameters> subject) { 24 | //return ctll::reject{}; 25 | constexpr char name[sizeof...(Name)]{static_cast(Name)...}; 26 | constexpr auto p = uni::detail::binary_prop_from_string(get_string_view(name)); 27 | 28 | if constexpr (uni::detail::is_unknown(p)) { 29 | return ctll::reject{}; 30 | } else { 31 | return pcre_context{ctll::push_front(make_binary_property

(), ctll::list()), subject.parameters}; 32 | } 33 | } 34 | 35 | // make_property 36 | template static constexpr auto apply(pcre::make_property, ctll::term, [[maybe_unused]] pcre_context, property_name, Ts...>, Parameters> subject) { 37 | //return ctll::reject{}; 38 | constexpr auto prop = property_builder::template get(); 39 | 40 | if constexpr (std::is_same_v) { 41 | return ctll::reject{}; 42 | } else { 43 | return pcre_context{ctll::push_front(prop, ctll::list()), subject.parameters}; 44 | } 45 | } 46 | 47 | 48 | // make_property_negative 49 | template static constexpr auto apply(pcre::make_property_negative, ctll::term, [[maybe_unused]] pcre_context, Ts...>, Parameters> subject) { 50 | //return ctll::reject{}; 51 | constexpr char name[sizeof...(Name)]{static_cast(Name)...}; 52 | constexpr auto p = uni::detail::binary_prop_from_string(get_string_view(name)); 53 | 54 | if constexpr (uni::detail::is_unknown(p)) { 55 | return ctll::reject{}; 56 | } else { 57 | return pcre_context{ctll::push_front(negate>(), ctll::list()), subject.parameters}; 58 | } 59 | } 60 | 61 | // make_property_negative 62 | template static constexpr auto apply(pcre::make_property_negative, ctll::term, [[maybe_unused]] pcre_context, property_name, Ts...>, Parameters> subject) { 63 | //return ctll::reject{}; 64 | constexpr auto prop = property_builder::template get(); 65 | 66 | if constexpr (std::is_same_v) { 67 | return ctll::reject{}; 68 | } else { 69 | return pcre_context{ctll::push_front(negate(), ctll::list()), subject.parameters}; 70 | } 71 | } 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /include/ctre/actions/repeat.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__REPEAT__HPP 2 | #define CTRE__ACTIONS__REPEAT__HPP 3 | 4 | // repeat 1..N 5 | template static constexpr auto apply(pcre::repeat_plus, ctll::term, pcre_context, Parameters> subject) { 6 | return pcre_context{ctll::push_front(plus(), ctll::list()), subject.parameters}; 7 | } 8 | // repeat 1..N (sequence) 9 | template static constexpr auto apply(pcre::repeat_plus, ctll::term, pcre_context, Ts...>, Parameters> subject) { 10 | return pcre_context{ctll::push_front(plus(), ctll::list()), subject.parameters}; 11 | } 12 | 13 | // repeat 0..N 14 | template static constexpr auto apply(pcre::repeat_star, ctll::term, pcre_context, Parameters> subject) { 15 | return pcre_context{ctll::push_front(star(), ctll::list()), subject.parameters}; 16 | } 17 | // repeat 0..N (sequence) 18 | template static constexpr auto apply(pcre::repeat_star, ctll::term, pcre_context, Ts...>, Parameters> subject) { 19 | return pcre_context{ctll::push_front(star(), ctll::list()), subject.parameters}; 20 | } 21 | 22 | // create_number (seed) 23 | template static constexpr auto apply(pcre::create_number, ctll::term, pcre_context, Parameters> subject) { 24 | return pcre_context{ctll::push_front(number(V - '0')>(), subject.stack), subject.parameters}; 25 | } 26 | // push_number 27 | template static constexpr auto apply(pcre::push_number, ctll::term, pcre_context, Ts...>, Parameters> subject) { 28 | constexpr size_t previous = N * 10ull; 29 | return pcre_context{ctll::push_front(number<(previous + (V - '0'))>(), ctll::list()), subject.parameters}; 30 | } 31 | 32 | // repeat A..B 33 | template static constexpr auto apply(pcre::repeat_ab, ctll::term, pcre_context, number, Subject, Ts...>, Parameters> subject) { 34 | return pcre_context{ctll::push_front(repeat(), ctll::list()), subject.parameters}; 35 | } 36 | // repeat A..B (sequence) 37 | template static constexpr auto apply(pcre::repeat_ab, ctll::term, pcre_context, number, sequence, Ts...>, Parameters> subject) { 38 | return pcre_context{ctll::push_front(repeat(), ctll::list()), subject.parameters}; 39 | } 40 | 41 | // repeat_exactly 42 | template static constexpr auto apply(pcre::repeat_exactly, ctll::term, pcre_context, Subject, Ts...>, Parameters> subject) { 43 | return pcre_context{ctll::push_front(repeat(), ctll::list()), subject.parameters}; 44 | } 45 | // repeat_exactly A..B (sequence) 46 | template static constexpr auto apply(pcre::repeat_exactly, ctll::term, pcre_context, sequence, Ts...>, Parameters> subject) { 47 | return pcre_context{ctll::push_front(repeat(), ctll::list()), subject.parameters}; 48 | } 49 | 50 | // repeat_at_least (A+) 51 | template static constexpr auto apply(pcre::repeat_at_least, ctll::term, pcre_context, Subject, Ts...>, Parameters> subject) { 52 | return pcre_context{ctll::push_front(repeat(), ctll::list()), subject.parameters}; 53 | } 54 | // repeat_at_least (A+) (sequence) 55 | template static constexpr auto apply(pcre::repeat_at_least, ctll::term, pcre_context, sequence, Ts...>, Parameters> subject) { 56 | return pcre_context{ctll::push_front(repeat(), ctll::list()), subject.parameters}; 57 | } 58 | 59 | // make_lazy (plus) 60 | template static constexpr auto apply(pcre::make_lazy, ctll::term, pcre_context, Ts...>, Parameters> subject) { 61 | return pcre_context{ctll::push_front(lazy_plus(), ctll::list()), subject.parameters}; 62 | } 63 | 64 | // make_lazy (star) 65 | template static constexpr auto apply(pcre::make_lazy, ctll::term, pcre_context, Ts...>, Parameters> subject) { 66 | return pcre_context{ctll::push_front(lazy_star(), ctll::list()), subject.parameters}; 67 | } 68 | 69 | // make_lazy (repeat) 70 | template static constexpr auto apply(pcre::make_lazy, ctll::term, pcre_context, Ts...>, Parameters> subject) { 71 | return pcre_context{ctll::push_front(lazy_repeat(), ctll::list()), subject.parameters}; 72 | } 73 | 74 | // make_possessive (plus) 75 | template static constexpr auto apply(pcre::make_possessive, ctll::term, pcre_context, Ts...>, Parameters> subject) { 76 | return pcre_context{ctll::push_front(possessive_plus(), ctll::list()), subject.parameters}; 77 | } 78 | 79 | // make_possessive (star) 80 | template static constexpr auto apply(pcre::make_possessive, ctll::term, pcre_context, Ts...>, Parameters> subject) { 81 | return pcre_context{ctll::push_front(possessive_star(), ctll::list()), subject.parameters}; 82 | } 83 | 84 | // make_possessive (repeat) 85 | template static constexpr auto apply(pcre::make_possessive, ctll::term, pcre_context, Ts...>, Parameters> subject) { 86 | return pcre_context{ctll::push_front(possessive_repeat(), ctll::list()), subject.parameters}; 87 | } 88 | 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /include/ctre/actions/sequence.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__SEQUENCE__HPP 2 | #define CTRE__ACTIONS__SEQUENCE__HPP 3 | 4 | // make_sequence 5 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context, Parameters> subject) { 6 | return pcre_context{ctll::push_front(sequence(), ctll::list()), subject.parameters}; 7 | } 8 | // make_sequence (concat) 9 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context,A,Ts...>, Parameters> subject) { 10 | return pcre_context{ctll::push_front(sequence(), ctll::list()), subject.parameters}; 11 | } 12 | 13 | // make_sequence (make string) 14 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context,character,Ts...>, Parameters> subject) { 15 | return pcre_context{ctll::push_front(string(), ctll::list()), subject.parameters}; 16 | } 17 | // make_sequence (concat string) 18 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context,character,Ts...>, Parameters> subject) { 19 | return pcre_context{ctll::push_front(string(), ctll::list()), subject.parameters}; 20 | } 21 | 22 | // make_sequence (make string in front of different items) 23 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context,Sq...>,character,Ts...>, Parameters> subject) { 24 | return pcre_context{ctll::push_front(sequence,Sq...>(), ctll::list()), subject.parameters}; 25 | } 26 | // make_sequence (concat string in front of different items) 27 | template static constexpr auto apply(pcre::make_sequence, ctll::term, pcre_context,Sq...>,character,Ts...>, Parameters> subject) { 28 | return pcre_context{ctll::push_front(sequence,Sq...>(), ctll::list()), subject.parameters}; 29 | } 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /include/ctre/actions/set.inc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTRE__ACTIONS__SET__HPP 2 | #define CTRE__ACTIONS__SET__HPP 3 | 4 | // UTILITY 5 | // add into set if not exists 6 | template